]> git.proxmox.com Git - mirror_zfs.git/blame - lib/libefi/rdwr_efi.c
Define the needed ISA types for Sparc
[mirror_zfs.git] / lib / libefi / rdwr_efi.c
CommitLineData
5c363129
BB
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
572e2857 23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
5c363129
BB
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <errno.h>
29#include <strings.h>
30#include <unistd.h>
31#include <uuid/uuid.h>
d603ed6c 32#include <zlib.h>
5c363129
BB
33#include <libintl.h>
34#include <sys/types.h>
35#include <sys/dkio.h>
36#include <sys/vtoc.h>
37#include <sys/mhd.h>
38#include <sys/param.h>
39#include <sys/dktp/fdisk.h>
40#include <sys/efi_partition.h>
41#include <sys/byteorder.h>
d603ed6c
BB
42#if defined(__linux__)
43#include <linux/fs.h>
44#endif
5c363129
BB
45
46static struct uuid_to_ptag {
47 struct uuid uuid;
48} conversion_array[] = {
49 { EFI_UNUSED },
50 { EFI_BOOT },
51 { EFI_ROOT },
52 { EFI_SWAP },
53 { EFI_USR },
54 { EFI_BACKUP },
d603ed6c 55 { EFI_UNUSED }, /* STAND is never used */
5c363129
BB
56 { EFI_VAR },
57 { EFI_HOME },
58 { EFI_ALTSCTR },
d603ed6c 59 { EFI_UNUSED }, /* CACHE (cachefs) is never used */
5c363129
BB
60 { EFI_RESERVED },
61 { EFI_SYSTEM },
62 { EFI_LEGACY_MBR },
572e2857
BB
63 { EFI_SYMC_PUB },
64 { EFI_SYMC_CDS },
5c363129
BB
65 { EFI_MSFT_RESV },
66 { EFI_DELL_BASIC },
67 { EFI_DELL_RAID },
68 { EFI_DELL_SWAP },
69 { EFI_DELL_LVM },
70 { EFI_DELL_RESV },
71 { EFI_AAPL_HFS },
72 { EFI_AAPL_UFS }
73};
74
75/*
76 * Default vtoc information for non-SVr4 partitions
77 */
78struct dk_map2 default_vtoc_map[NDKMAP] = {
79 { V_ROOT, 0 }, /* a - 0 */
80 { V_SWAP, V_UNMNT }, /* b - 1 */
81 { V_BACKUP, V_UNMNT }, /* c - 2 */
82 { V_UNASSIGNED, 0 }, /* d - 3 */
83 { V_UNASSIGNED, 0 }, /* e - 4 */
84 { V_UNASSIGNED, 0 }, /* f - 5 */
85 { V_USR, 0 }, /* g - 6 */
86 { V_UNASSIGNED, 0 }, /* h - 7 */
87
88#if defined(_SUNOS_VTOC_16)
89
d7ec8d4f
BB
90#if defined(i386) || defined(__amd64) || defined(__arm) || \
91 defined(__powerpc) || defined(__sparc)
5c363129
BB
92 { V_BOOT, V_UNMNT }, /* i - 8 */
93 { V_ALTSCTR, 0 }, /* j - 9 */
94
95#else
96#error No VTOC format defined.
97#endif /* defined(i386) */
98
99 { V_UNASSIGNED, 0 }, /* k - 10 */
100 { V_UNASSIGNED, 0 }, /* l - 11 */
101 { V_UNASSIGNED, 0 }, /* m - 12 */
102 { V_UNASSIGNED, 0 }, /* n - 13 */
103 { V_UNASSIGNED, 0 }, /* o - 14 */
104 { V_UNASSIGNED, 0 }, /* p - 15 */
105#endif /* defined(_SUNOS_VTOC_16) */
106};
107
108#ifdef DEBUG
109int efi_debug = 1;
110#else
111int efi_debug = 0;
112#endif
113
d603ed6c
BB
114static int efi_read(int, struct dk_gpt *);
115
116/*
117 * Return a 32-bit CRC of the contents of the buffer. Pre-and-post
118 * one's conditioning will be handled by crc32() internally.
119 */
120static uint32_t
121efi_crc32(const unsigned char *buf, unsigned int size)
122{
123 uint32_t crc = crc32(0, Z_NULL, 0);
124
125 crc = crc32(crc, buf, size);
126
127 return (crc);
128}
5c363129
BB
129
130static int
131read_disk_info(int fd, diskaddr_t *capacity, uint_t *lbsize)
132{
d603ed6c
BB
133 int sector_size;
134 unsigned long long capacity_size;
135
d1d7e268
MK
136 if (ioctl(fd, BLKSSZGET, &sector_size) < 0)
137 return (-1);
d603ed6c
BB
138
139 if (ioctl(fd, BLKGETSIZE64, &capacity_size) < 0)
140 return (-1);
141
142 *lbsize = (uint_t)sector_size;
143 *capacity = (diskaddr_t)(capacity_size / sector_size);
144
145 return (0);
146}
5c363129 147
d603ed6c
BB
148static int
149efi_get_info(int fd, struct dk_cinfo *dki_info)
150{
151#if defined(__linux__)
152 char *path;
153 char *dev_path;
154 int rval = 0;
155
d1d7e268 156 memset(dki_info, 0, sizeof (*dki_info));
d603ed6c
BB
157
158 path = calloc(PATH_MAX, 1);
159 if (path == NULL)
160 goto error;
161
162 /*
163 * The simplest way to get the partition number under linux is
164 * to parse it out of the /dev/<disk><parition> block device name.
165 * The kernel creates this using the partition number when it
166 * populates /dev/ so it may be trusted. The tricky bit here is
167 * that the naming convention is based on the block device type.
168 * So we need to take this in to account when parsing out the
169 * partition information. Another issue is that the libefi API
170 * API only provides the open fd and not the file path. To handle
171 * this realpath(3) is used to resolve the block device name from
172 * /proc/self/fd/<fd>. Aside from the partition number we collect
173 * some additional device info.
174 */
175 (void) sprintf(path, "/proc/self/fd/%d", fd);
176 dev_path = realpath(path, NULL);
177 free(path);
178
179 if (dev_path == NULL)
180 goto error;
181
182 if ((strncmp(dev_path, "/dev/sd", 7) == 0)) {
183 strcpy(dki_info->dki_cname, "sd");
184 dki_info->dki_ctype = DKC_SCSI_CCS;
185 rval = sscanf(dev_path, "/dev/%[a-zA-Z]%hu",
d1d7e268
MK
186 dki_info->dki_dname,
187 &dki_info->dki_partition);
d603ed6c
BB
188 } else if ((strncmp(dev_path, "/dev/hd", 7) == 0)) {
189 strcpy(dki_info->dki_cname, "hd");
190 dki_info->dki_ctype = DKC_DIRECT;
191 rval = sscanf(dev_path, "/dev/%[a-zA-Z]%hu",
d1d7e268
MK
192 dki_info->dki_dname,
193 &dki_info->dki_partition);
d603ed6c
BB
194 } else if ((strncmp(dev_path, "/dev/md", 7) == 0)) {
195 strcpy(dki_info->dki_cname, "pseudo");
196 dki_info->dki_ctype = DKC_MD;
197 rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9]p%hu",
d1d7e268
MK
198 dki_info->dki_dname,
199 &dki_info->dki_partition);
2932b6a8
RL
200 } else if ((strncmp(dev_path, "/dev/vd", 7) == 0)) {
201 strcpy(dki_info->dki_cname, "vd");
202 dki_info->dki_ctype = DKC_MD;
203 rval = sscanf(dev_path, "/dev/%[a-zA-Z]%hu",
d1d7e268
MK
204 dki_info->dki_dname,
205 &dki_info->dki_partition);
d603ed6c
BB
206 } else if ((strncmp(dev_path, "/dev/dm-", 8) == 0)) {
207 strcpy(dki_info->dki_cname, "pseudo");
208 dki_info->dki_ctype = DKC_VBD;
209 rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9-]p%hu",
d1d7e268
MK
210 dki_info->dki_dname,
211 &dki_info->dki_partition);
d603ed6c
BB
212 } else if ((strncmp(dev_path, "/dev/ram", 8) == 0)) {
213 strcpy(dki_info->dki_cname, "pseudo");
214 dki_info->dki_ctype = DKC_PCMCIA_MEM;
215 rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9]p%hu",
d1d7e268
MK
216 dki_info->dki_dname,
217 &dki_info->dki_partition);
d603ed6c
BB
218 } else if ((strncmp(dev_path, "/dev/loop", 9) == 0)) {
219 strcpy(dki_info->dki_cname, "pseudo");
220 dki_info->dki_ctype = DKC_VBD;
221 rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9]p%hu",
d1d7e268
MK
222 dki_info->dki_dname,
223 &dki_info->dki_partition);
d603ed6c
BB
224 } else {
225 strcpy(dki_info->dki_dname, "unknown");
226 strcpy(dki_info->dki_cname, "unknown");
227 dki_info->dki_ctype = DKC_UNKNOWN;
228 }
229
230 switch (rval) {
231 case 0:
232 errno = EINVAL;
233 goto error;
234 case 1:
235 dki_info->dki_partition = 0;
236 }
237
238 free(dev_path);
239#else
240 if (ioctl(fd, DKIOCINFO, (caddr_t)dki_info) == -1)
241 goto error;
242#endif
5c363129 243 return (0);
d603ed6c
BB
244error:
245 if (efi_debug)
246 (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno);
247
248 switch (errno) {
249 case EIO:
250 return (VT_EIO);
251 case EINVAL:
252 return (VT_EINVAL);
253 default:
254 return (VT_ERROR);
255 }
5c363129
BB
256}
257
258/*
259 * the number of blocks the EFI label takes up (round up to nearest
260 * block)
261 */
262#define NBLOCKS(p, l) (1 + ((((p) * (int)sizeof (efi_gpe_t)) + \
263 ((l) - 1)) / (l)))
264/* number of partitions -- limited by what we can malloc */
265#define MAX_PARTS ((4294967295UL - sizeof (struct dk_gpt)) / \
266 sizeof (struct dk_part))
267
268int
269efi_alloc_and_init(int fd, uint32_t nparts, struct dk_gpt **vtoc)
270{
d603ed6c
BB
271 diskaddr_t capacity = 0;
272 uint_t lbsize = 0;
5c363129
BB
273 uint_t nblocks;
274 size_t length;
275 struct dk_gpt *vptr;
276 struct uuid uuid;
d603ed6c 277 struct dk_cinfo dki_info;
5c363129 278
b3b4f547 279 if (read_disk_info(fd, &capacity, &lbsize) != 0)
5c363129 280 return (-1);
b3b4f547 281
d603ed6c 282#if defined(__linux__)
b3b4f547 283 if (efi_get_info(fd, &dki_info) != 0)
d603ed6c 284 return (-1);
d603ed6c
BB
285
286 if (dki_info.dki_partition != 0)
287 return (-1);
288
289 if ((dki_info.dki_ctype == DKC_PCMCIA_MEM) ||
290 (dki_info.dki_ctype == DKC_VBD) ||
291 (dki_info.dki_ctype == DKC_UNKNOWN))
292 return (-1);
293#endif
5c363129
BB
294
295 nblocks = NBLOCKS(nparts, lbsize);
296 if ((nblocks * lbsize) < EFI_MIN_ARRAY_SIZE + lbsize) {
297 /* 16K plus one block for the GPT */
298 nblocks = EFI_MIN_ARRAY_SIZE / lbsize + 1;
299 }
300
301 if (nparts > MAX_PARTS) {
302 if (efi_debug) {
303 (void) fprintf(stderr,
304 "the maximum number of partitions supported is %lu\n",
305 MAX_PARTS);
306 }
307 return (-1);
308 }
309
310 length = sizeof (struct dk_gpt) +
311 sizeof (struct dk_part) * (nparts - 1);
312
313 if ((*vtoc = calloc(length, 1)) == NULL)
314 return (-1);
315
316 vptr = *vtoc;
317
318 vptr->efi_version = EFI_VERSION_CURRENT;
319 vptr->efi_lbasize = lbsize;
320 vptr->efi_nparts = nparts;
321 /*
322 * add one block here for the PMBR; on disks with a 512 byte
323 * block size and 128 or fewer partitions, efi_first_u_lba
324 * should work out to "34"
325 */
326 vptr->efi_first_u_lba = nblocks + 1;
327 vptr->efi_last_lba = capacity - 1;
328 vptr->efi_altern_lba = capacity -1;
329 vptr->efi_last_u_lba = vptr->efi_last_lba - nblocks;
330
331 (void) uuid_generate((uchar_t *)&uuid);
332 UUID_LE_CONVERT(vptr->efi_disk_uguid, uuid);
333 return (0);
334}
335
336/*
337 * Read EFI - return partition number upon success.
338 */
339int
340efi_alloc_and_read(int fd, struct dk_gpt **vtoc)
341{
342 int rval;
343 uint32_t nparts;
344 int length;
345
346 /* figure out the number of entries that would fit into 16K */
347 nparts = EFI_MIN_ARRAY_SIZE / sizeof (efi_gpe_t);
348 length = (int) sizeof (struct dk_gpt) +
349 (int) sizeof (struct dk_part) * (nparts - 1);
350 if ((*vtoc = calloc(length, 1)) == NULL)
351 return (VT_ERROR);
352
353 (*vtoc)->efi_nparts = nparts;
354 rval = efi_read(fd, *vtoc);
355
356 if ((rval == VT_EINVAL) && (*vtoc)->efi_nparts > nparts) {
357 void *tmp;
358 length = (int) sizeof (struct dk_gpt) +
359 (int) sizeof (struct dk_part) *
360 ((*vtoc)->efi_nparts - 1);
361 nparts = (*vtoc)->efi_nparts;
362 if ((tmp = realloc(*vtoc, length)) == NULL) {
363 free (*vtoc);
364 *vtoc = NULL;
365 return (VT_ERROR);
366 } else {
367 *vtoc = tmp;
368 rval = efi_read(fd, *vtoc);
369 }
370 }
371
372 if (rval < 0) {
373 if (efi_debug) {
374 (void) fprintf(stderr,
375 "read of EFI table failed, rval=%d\n", rval);
376 }
377 free (*vtoc);
378 *vtoc = NULL;
379 }
380
381 return (rval);
382}
383
384static int
385efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
386{
387 void *data = dk_ioc->dki_data;
388 int error;
d603ed6c
BB
389#if defined(__linux__)
390 diskaddr_t capacity;
391 uint_t lbsize;
392
393 /*
394 * When the IO is not being performed in kernel as an ioctl we need
395 * to know the sector size so we can seek to the proper byte offset.
396 */
397 if (read_disk_info(fd, &capacity, &lbsize) == -1) {
398 if (efi_debug)
d1d7e268 399 fprintf(stderr, "unable to read disk info: %d", errno);
d603ed6c
BB
400
401 errno = EIO;
d1d7e268 402 return (-1);
d603ed6c
BB
403 }
404
405 switch (cmd) {
406 case DKIOCGETEFI:
407 if (lbsize == 0) {
408 if (efi_debug)
409 (void) fprintf(stderr, "DKIOCGETEFI assuming "
d1d7e268 410 "LBA %d bytes\n", DEV_BSIZE);
d603ed6c
BB
411
412 lbsize = DEV_BSIZE;
413 }
414
415 error = lseek(fd, dk_ioc->dki_lba * lbsize, SEEK_SET);
416 if (error == -1) {
417 if (efi_debug)
418 (void) fprintf(stderr, "DKIOCGETEFI lseek "
d1d7e268
MK
419 "error: %d\n", errno);
420 return (error);
d603ed6c
BB
421 }
422
423 error = read(fd, data, dk_ioc->dki_length);
424 if (error == -1) {
425 if (efi_debug)
426 (void) fprintf(stderr, "DKIOCGETEFI read "
d1d7e268
MK
427 "error: %d\n", errno);
428 return (error);
d603ed6c 429 }
5c363129 430
d603ed6c
BB
431 if (error != dk_ioc->dki_length) {
432 if (efi_debug)
433 (void) fprintf(stderr, "DKIOCGETEFI short "
d1d7e268 434 "read of %d bytes\n", error);
d603ed6c 435 errno = EIO;
d1d7e268 436 return (-1);
d603ed6c
BB
437 }
438 error = 0;
439 break;
440
441 case DKIOCSETEFI:
442 if (lbsize == 0) {
443 if (efi_debug)
444 (void) fprintf(stderr, "DKIOCSETEFI unknown "
d1d7e268 445 "LBA size\n");
d603ed6c 446 errno = EIO;
d1d7e268 447 return (-1);
d603ed6c
BB
448 }
449
450 error = lseek(fd, dk_ioc->dki_lba * lbsize, SEEK_SET);
451 if (error == -1) {
452 if (efi_debug)
453 (void) fprintf(stderr, "DKIOCSETEFI lseek "
d1d7e268
MK
454 "error: %d\n", errno);
455 return (error);
d603ed6c
BB
456 }
457
458 error = write(fd, data, dk_ioc->dki_length);
459 if (error == -1) {
460 if (efi_debug)
461 (void) fprintf(stderr, "DKIOCSETEFI write "
d1d7e268
MK
462 "error: %d\n", errno);
463 return (error);
d603ed6c
BB
464 }
465
466 if (error != dk_ioc->dki_length) {
467 if (efi_debug)
468 (void) fprintf(stderr, "DKIOCSETEFI short "
d1d7e268 469 "write of %d bytes\n", error);
d603ed6c 470 errno = EIO;
d1d7e268 471 return (-1);
d603ed6c
BB
472 }
473
474 /* Sync the new EFI table to disk */
475 error = fsync(fd);
476 if (error == -1)
d1d7e268 477 return (error);
d603ed6c
BB
478
479 /* Ensure any local disk cache is also flushed */
480 if (ioctl(fd, BLKFLSBUF, 0) == -1)
d1d7e268 481 return (error);
d603ed6c
BB
482
483 error = 0;
484 break;
485
486 default:
487 if (efi_debug)
488 (void) fprintf(stderr, "unsupported ioctl()\n");
489
490 errno = EIO;
d1d7e268 491 return (-1);
d603ed6c
BB
492 }
493#else
5c363129
BB
494 dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data;
495 error = ioctl(fd, cmd, (void *)dk_ioc);
496 dk_ioc->dki_data = data;
d603ed6c 497#endif
5c363129
BB
498 return (error);
499}
500
d1d7e268
MK
501int
502efi_rescan(int fd)
d603ed6c 503{
b5a28807 504#if defined(__linux__)
d603ed6c
BB
505 int retry = 5;
506 int error;
507
508 /* Notify the kernel a devices partition table has been updated */
509 while ((error = ioctl(fd, BLKRRPART)) != 0) {
510 if (--retry == 0) {
511 (void) fprintf(stderr, "the kernel failed to rescan "
d1d7e268 512 "the partition table: %d\n", errno);
d603ed6c
BB
513 return (-1);
514 }
515 }
b5a28807 516#endif
d603ed6c
BB
517
518 return (0);
519}
d603ed6c 520
5c363129
BB
521static int
522check_label(int fd, dk_efi_t *dk_ioc)
523{
524 efi_gpt_t *efi;
525 uint_t crc;
526
527 if (efi_ioctl(fd, DKIOCGETEFI, dk_ioc) == -1) {
528 switch (errno) {
529 case EIO:
530 return (VT_EIO);
531 default:
532 return (VT_ERROR);
533 }
534 }
535 efi = dk_ioc->dki_data;
536 if (efi->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) {
537 if (efi_debug)
538 (void) fprintf(stderr,
539 "Bad EFI signature: 0x%llx != 0x%llx\n",
540 (long long)efi->efi_gpt_Signature,
541 (long long)LE_64(EFI_SIGNATURE));
542 return (VT_EINVAL);
543 }
544
545 /*
546 * check CRC of the header; the size of the header should
547 * never be larger than one block
548 */
549 crc = efi->efi_gpt_HeaderCRC32;
550 efi->efi_gpt_HeaderCRC32 = 0;
7a023273 551 len_t headerSize = (len_t)LE_32(efi->efi_gpt_HeaderSize);
5c363129 552
d1d7e268 553 if (headerSize < EFI_MIN_LABEL_SIZE || headerSize > EFI_LABEL_SIZE) {
7a023273
ZB
554 if (efi_debug)
555 (void) fprintf(stderr,
556 "Invalid EFI HeaderSize %llu. Assuming %d.\n",
557 headerSize, EFI_MIN_LABEL_SIZE);
558 }
559
560 if ((headerSize > dk_ioc->dki_length) ||
561 crc != LE_32(efi_crc32((unsigned char *)efi, headerSize))) {
5c363129
BB
562 if (efi_debug)
563 (void) fprintf(stderr,
564 "Bad EFI CRC: 0x%x != 0x%x\n",
7a023273
ZB
565 crc, LE_32(efi_crc32((unsigned char *)efi,
566 headerSize)));
5c363129
BB
567 return (VT_EINVAL);
568 }
569
570 return (0);
571}
572
573static int
574efi_read(int fd, struct dk_gpt *vtoc)
575{
576 int i, j;
577 int label_len;
578 int rval = 0;
579 int md_flag = 0;
580 int vdc_flag = 0;
d603ed6c
BB
581 diskaddr_t capacity = 0;
582 uint_t lbsize = 0;
5c363129
BB
583 struct dk_minfo disk_info;
584 dk_efi_t dk_ioc;
585 efi_gpt_t *efi;
586 efi_gpe_t *efi_parts;
587 struct dk_cinfo dki_info;
588 uint32_t user_length;
589 boolean_t legacy_label = B_FALSE;
590
591 /*
592 * get the partition number for this file descriptor.
593 */
d603ed6c 594 if ((rval = efi_get_info(fd, &dki_info)) != 0)
d1d7e268 595 return (rval);
d603ed6c 596
5c363129
BB
597 if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) &&
598 (strncmp(dki_info.dki_dname, "md", 3) == 0)) {
599 md_flag++;
600 } else if ((strncmp(dki_info.dki_cname, "vdc", 4) == 0) &&
601 (strncmp(dki_info.dki_dname, "vdc", 4) == 0)) {
602 /*
603 * The controller and drive name "vdc" (virtual disk client)
604 * indicates a LDoms virtual disk.
605 */
606 vdc_flag++;
607 }
608
609 /* get the LBA size */
d603ed6c 610 if (read_disk_info(fd, &capacity, &lbsize) == -1) {
5c363129
BB
611 if (efi_debug) {
612 (void) fprintf(stderr,
d1d7e268
MK
613 "unable to read disk info: %d",
614 errno);
5c363129 615 }
d603ed6c 616 return (VT_EINVAL);
5c363129 617 }
d603ed6c
BB
618
619 disk_info.dki_lbsize = lbsize;
620 disk_info.dki_capacity = capacity;
621
5c363129
BB
622 if (disk_info.dki_lbsize == 0) {
623 if (efi_debug) {
624 (void) fprintf(stderr,
625 "efi_read: assuming LBA 512 bytes\n");
626 }
627 disk_info.dki_lbsize = DEV_BSIZE;
628 }
629 /*
630 * Read the EFI GPT to figure out how many partitions we need
631 * to deal with.
632 */
633 dk_ioc.dki_lba = 1;
634 if (NBLOCKS(vtoc->efi_nparts, disk_info.dki_lbsize) < 34) {
635 label_len = EFI_MIN_ARRAY_SIZE + disk_info.dki_lbsize;
636 } else {
637 label_len = vtoc->efi_nparts * (int) sizeof (efi_gpe_t) +
638 disk_info.dki_lbsize;
639 if (label_len % disk_info.dki_lbsize) {
640 /* pad to physical sector size */
641 label_len += disk_info.dki_lbsize;
642 label_len &= ~(disk_info.dki_lbsize - 1);
643 }
644 }
645
d603ed6c 646 if (posix_memalign((void **)&dk_ioc.dki_data,
d1d7e268 647 disk_info.dki_lbsize, label_len))
5c363129
BB
648 return (VT_ERROR);
649
d603ed6c 650 memset(dk_ioc.dki_data, 0, label_len);
5c363129
BB
651 dk_ioc.dki_length = disk_info.dki_lbsize;
652 user_length = vtoc->efi_nparts;
653 efi = dk_ioc.dki_data;
654 if (md_flag) {
655 dk_ioc.dki_length = label_len;
656 if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) {
657 switch (errno) {
658 case EIO:
659 return (VT_EIO);
660 default:
661 return (VT_ERROR);
662 }
663 }
664 } else if ((rval = check_label(fd, &dk_ioc)) == VT_EINVAL) {
665 /*
666 * No valid label here; try the alternate. Note that here
667 * we just read GPT header and save it into dk_ioc.data,
668 * Later, we will read GUID partition entry array if we
669 * can get valid GPT header.
670 */
671
672 /*
673 * This is a workaround for legacy systems. In the past, the
674 * last sector of SCSI disk was invisible on x86 platform. At
675 * that time, backup label was saved on the next to the last
676 * sector. It is possible for users to move a disk from previous
677 * solaris system to present system. Here, we attempt to search
678 * legacy backup EFI label first.
679 */
680 dk_ioc.dki_lba = disk_info.dki_capacity - 2;
681 dk_ioc.dki_length = disk_info.dki_lbsize;
682 rval = check_label(fd, &dk_ioc);
683 if (rval == VT_EINVAL) {
684 /*
685 * we didn't find legacy backup EFI label, try to
686 * search backup EFI label in the last block.
687 */
688 dk_ioc.dki_lba = disk_info.dki_capacity - 1;
689 dk_ioc.dki_length = disk_info.dki_lbsize;
690 rval = check_label(fd, &dk_ioc);
691 if (rval == 0) {
692 legacy_label = B_TRUE;
693 if (efi_debug)
694 (void) fprintf(stderr,
695 "efi_read: primary label corrupt; "
696 "using EFI backup label located on"
697 " the last block\n");
698 }
699 } else {
700 if ((efi_debug) && (rval == 0))
701 (void) fprintf(stderr, "efi_read: primary label"
702 " corrupt; using legacy EFI backup label "
703 " located on the next to last block\n");
704 }
705
706 if (rval == 0) {
707 dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA);
708 vtoc->efi_flags |= EFI_GPT_PRIMARY_CORRUPT;
709 vtoc->efi_nparts =
710 LE_32(efi->efi_gpt_NumberOfPartitionEntries);
711 /*
712 * Partition tables are between backup GPT header
713 * table and ParitionEntryLBA (the starting LBA of
714 * the GUID partition entries array). Now that we
715 * already got valid GPT header and saved it in
716 * dk_ioc.dki_data, we try to get GUID partition
717 * entry array here.
718 */
719 /* LINTED */
720 dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data
721 + disk_info.dki_lbsize);
722 if (legacy_label)
723 dk_ioc.dki_length = disk_info.dki_capacity - 1 -
724 dk_ioc.dki_lba;
725 else
726 dk_ioc.dki_length = disk_info.dki_capacity - 2 -
727 dk_ioc.dki_lba;
728 dk_ioc.dki_length *= disk_info.dki_lbsize;
729 if (dk_ioc.dki_length >
730 ((len_t)label_len - sizeof (*dk_ioc.dki_data))) {
731 rval = VT_EINVAL;
732 } else {
733 /*
734 * read GUID partition entry array
735 */
736 rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc);
737 }
738 }
739
740 } else if (rval == 0) {
741
742 dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA);
743 /* LINTED */
744 dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data
745 + disk_info.dki_lbsize);
746 dk_ioc.dki_length = label_len - disk_info.dki_lbsize;
747 rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc);
748
749 } else if (vdc_flag && rval == VT_ERROR && errno == EINVAL) {
750 /*
751 * When the device is a LDoms virtual disk, the DKIOCGETEFI
752 * ioctl can fail with EINVAL if the virtual disk backend
753 * is a ZFS volume serviced by a domain running an old version
754 * of Solaris. This is because the DKIOCGETEFI ioctl was
755 * initially incorrectly implemented for a ZFS volume and it
756 * expected the GPT and GPE to be retrieved with a single ioctl.
757 * So we try to read the GPT and the GPE using that old style
758 * ioctl.
759 */
760 dk_ioc.dki_lba = 1;
761 dk_ioc.dki_length = label_len;
762 rval = check_label(fd, &dk_ioc);
763 }
764
765 if (rval < 0) {
766 free(efi);
767 return (rval);
768 }
769
770 /* LINTED -- always longlong aligned */
771 efi_parts = (efi_gpe_t *)(((char *)efi) + disk_info.dki_lbsize);
772
773 /*
774 * Assemble this into a "dk_gpt" struct for easier
775 * digestibility by applications.
776 */
777 vtoc->efi_version = LE_32(efi->efi_gpt_Revision);
778 vtoc->efi_nparts = LE_32(efi->efi_gpt_NumberOfPartitionEntries);
779 vtoc->efi_part_size = LE_32(efi->efi_gpt_SizeOfPartitionEntry);
780 vtoc->efi_lbasize = disk_info.dki_lbsize;
781 vtoc->efi_last_lba = disk_info.dki_capacity - 1;
782 vtoc->efi_first_u_lba = LE_64(efi->efi_gpt_FirstUsableLBA);
783 vtoc->efi_last_u_lba = LE_64(efi->efi_gpt_LastUsableLBA);
784 vtoc->efi_altern_lba = LE_64(efi->efi_gpt_AlternateLBA);
785 UUID_LE_CONVERT(vtoc->efi_disk_uguid, efi->efi_gpt_DiskGUID);
786
787 /*
788 * If the array the user passed in is too small, set the length
789 * to what it needs to be and return
790 */
791 if (user_length < vtoc->efi_nparts) {
792 return (VT_EINVAL);
793 }
794
795 for (i = 0; i < vtoc->efi_nparts; i++) {
796
797 UUID_LE_CONVERT(vtoc->efi_parts[i].p_guid,
798 efi_parts[i].efi_gpe_PartitionTypeGUID);
799
800 for (j = 0;
801 j < sizeof (conversion_array)
802 / sizeof (struct uuid_to_ptag); j++) {
803
804 if (bcmp(&vtoc->efi_parts[i].p_guid,
805 &conversion_array[j].uuid,
806 sizeof (struct uuid)) == 0) {
807 vtoc->efi_parts[i].p_tag = j;
808 break;
809 }
810 }
811 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED)
812 continue;
813 vtoc->efi_parts[i].p_flag =
814 LE_16(efi_parts[i].efi_gpe_Attributes.PartitionAttrs);
815 vtoc->efi_parts[i].p_start =
816 LE_64(efi_parts[i].efi_gpe_StartingLBA);
817 vtoc->efi_parts[i].p_size =
818 LE_64(efi_parts[i].efi_gpe_EndingLBA) -
819 vtoc->efi_parts[i].p_start + 1;
820 for (j = 0; j < EFI_PART_NAME_LEN; j++) {
821 vtoc->efi_parts[i].p_name[j] =
822 (uchar_t)LE_16(
823 efi_parts[i].efi_gpe_PartitionName[j]);
824 }
825
826 UUID_LE_CONVERT(vtoc->efi_parts[i].p_uguid,
827 efi_parts[i].efi_gpe_UniquePartitionGUID);
828 }
829 free(efi);
830
831 return (dki_info.dki_partition);
832}
833
834/* writes a "protective" MBR */
835static int
836write_pmbr(int fd, struct dk_gpt *vtoc)
837{
838 dk_efi_t dk_ioc;
839 struct mboot mb;
840 uchar_t *cp;
841 diskaddr_t size_in_lba;
842 uchar_t *buf;
843 int len;
844
845 len = (vtoc->efi_lbasize == 0) ? sizeof (mb) : vtoc->efi_lbasize;
d603ed6c
BB
846 if (posix_memalign((void **)&buf, len, len))
847 return (VT_ERROR);
5c363129
BB
848
849 /*
850 * Preserve any boot code and disk signature if the first block is
851 * already an MBR.
852 */
d603ed6c 853 memset(buf, 0, len);
5c363129
BB
854 dk_ioc.dki_lba = 0;
855 dk_ioc.dki_length = len;
856 /* LINTED -- always longlong aligned */
857 dk_ioc.dki_data = (efi_gpt_t *)buf;
858 if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) {
859 (void *) memcpy(&mb, buf, sizeof (mb));
860 bzero(&mb, sizeof (mb));
861 mb.signature = LE_16(MBB_MAGIC);
862 } else {
863 (void *) memcpy(&mb, buf, sizeof (mb));
864 if (mb.signature != LE_16(MBB_MAGIC)) {
865 bzero(&mb, sizeof (mb));
866 mb.signature = LE_16(MBB_MAGIC);
867 }
868 }
869
870 bzero(&mb.parts, sizeof (mb.parts));
871 cp = (uchar_t *)&mb.parts[0];
872 /* bootable or not */
873 *cp++ = 0;
874 /* beginning CHS; 0xffffff if not representable */
875 *cp++ = 0xff;
876 *cp++ = 0xff;
877 *cp++ = 0xff;
878 /* OS type */
879 *cp++ = EFI_PMBR;
880 /* ending CHS; 0xffffff if not representable */
881 *cp++ = 0xff;
882 *cp++ = 0xff;
883 *cp++ = 0xff;
884 /* starting LBA: 1 (little endian format) by EFI definition */
885 *cp++ = 0x01;
886 *cp++ = 0x00;
887 *cp++ = 0x00;
888 *cp++ = 0x00;
889 /* ending LBA: last block on the disk (little endian format) */
890 size_in_lba = vtoc->efi_last_lba;
891 if (size_in_lba < 0xffffffff) {
892 *cp++ = (size_in_lba & 0x000000ff);
893 *cp++ = (size_in_lba & 0x0000ff00) >> 8;
894 *cp++ = (size_in_lba & 0x00ff0000) >> 16;
895 *cp++ = (size_in_lba & 0xff000000) >> 24;
896 } else {
897 *cp++ = 0xff;
898 *cp++ = 0xff;
899 *cp++ = 0xff;
900 *cp++ = 0xff;
901 }
902
903 (void *) memcpy(buf, &mb, sizeof (mb));
904 /* LINTED -- always longlong aligned */
905 dk_ioc.dki_data = (efi_gpt_t *)buf;
906 dk_ioc.dki_lba = 0;
907 dk_ioc.dki_length = len;
908 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
909 free(buf);
910 switch (errno) {
911 case EIO:
912 return (VT_EIO);
913 case EINVAL:
914 return (VT_EINVAL);
915 default:
916 return (VT_ERROR);
917 }
918 }
919 free(buf);
920 return (0);
921}
922
923/* make sure the user specified something reasonable */
924static int
925check_input(struct dk_gpt *vtoc)
926{
927 int resv_part = -1;
928 int i, j;
929 diskaddr_t istart, jstart, isize, jsize, endsect;
930
931 /*
932 * Sanity-check the input (make sure no partitions overlap)
933 */
934 for (i = 0; i < vtoc->efi_nparts; i++) {
935 /* It can't be unassigned and have an actual size */
936 if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) &&
937 (vtoc->efi_parts[i].p_size != 0)) {
938 if (efi_debug) {
d603ed6c
BB
939 (void) fprintf(stderr, "partition %d is "
940 "\"unassigned\" but has a size of %llu",
941 i, vtoc->efi_parts[i].p_size);
5c363129
BB
942 }
943 return (VT_EINVAL);
944 }
945 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) {
946 if (uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_guid))
947 continue;
948 /* we have encountered an unknown uuid */
949 vtoc->efi_parts[i].p_tag = 0xff;
950 }
951 if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
952 if (resv_part != -1) {
953 if (efi_debug) {
d603ed6c
BB
954 (void) fprintf(stderr, "found "
955 "duplicate reserved partition "
956 "at %d\n", i);
5c363129
BB
957 }
958 return (VT_EINVAL);
959 }
960 resv_part = i;
961 }
962 if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) ||
963 (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) {
964 if (efi_debug) {
965 (void) fprintf(stderr,
966 "Partition %d starts at %llu. ",
967 i,
968 vtoc->efi_parts[i].p_start);
969 (void) fprintf(stderr,
970 "It must be between %llu and %llu.\n",
971 vtoc->efi_first_u_lba,
972 vtoc->efi_last_u_lba);
973 }
974 return (VT_EINVAL);
975 }
976 if ((vtoc->efi_parts[i].p_start +
977 vtoc->efi_parts[i].p_size <
978 vtoc->efi_first_u_lba) ||
979 (vtoc->efi_parts[i].p_start +
980 vtoc->efi_parts[i].p_size >
981 vtoc->efi_last_u_lba + 1)) {
982 if (efi_debug) {
983 (void) fprintf(stderr,
984 "Partition %d ends at %llu. ",
985 i,
986 vtoc->efi_parts[i].p_start +
987 vtoc->efi_parts[i].p_size);
988 (void) fprintf(stderr,
989 "It must be between %llu and %llu.\n",
990 vtoc->efi_first_u_lba,
991 vtoc->efi_last_u_lba);
992 }
993 return (VT_EINVAL);
994 }
995
996 for (j = 0; j < vtoc->efi_nparts; j++) {
997 isize = vtoc->efi_parts[i].p_size;
998 jsize = vtoc->efi_parts[j].p_size;
999 istart = vtoc->efi_parts[i].p_start;
1000 jstart = vtoc->efi_parts[j].p_start;
1001 if ((i != j) && (isize != 0) && (jsize != 0)) {
1002 endsect = jstart + jsize -1;
1003 if ((jstart <= istart) &&
1004 (istart <= endsect)) {
1005 if (efi_debug) {
1006 (void) fprintf(stderr,
d603ed6c
BB
1007 "Partition %d overlaps "
1008 "partition %d.", i, j);
5c363129
BB
1009 }
1010 return (VT_EINVAL);
1011 }
1012 }
1013 }
1014 }
1015 /* just a warning for now */
1016 if ((resv_part == -1) && efi_debug) {
1017 (void) fprintf(stderr,
1018 "no reserved partition found\n");
1019 }
1020 return (0);
1021}
1022
1023/*
1024 * add all the unallocated space to the current label
1025 */
1026int
1027efi_use_whole_disk(int fd)
1028{
1029 struct dk_gpt *efi_label;
1030 int rval;
1031 int i;
cee43a74
ED
1032 uint_t resv_index = 0, data_index = 0;
1033 diskaddr_t resv_start = 0, data_start = 0;
1034 diskaddr_t difference;
5c363129
BB
1035
1036 rval = efi_alloc_and_read(fd, &efi_label);
1037 if (rval < 0) {
1038 return (rval);
1039 }
1040
5c363129
BB
1041 /*
1042 * If alter_lba is 1, we are using the backup label.
1043 * Since we can locate the backup label by disk capacity,
1044 * there must be no unallocated space.
1045 */
1046 if ((efi_label->efi_altern_lba == 1) || (efi_label->efi_altern_lba
1047 >= efi_label->efi_last_lba)) {
1048 if (efi_debug) {
1049 (void) fprintf(stderr,
1050 "efi_use_whole_disk: requested space not found\n");
1051 }
1052 efi_free(efi_label);
1053 return (VT_ENOSPC);
1054 }
1055
cee43a74
ED
1056 difference = efi_label->efi_last_lba - efi_label->efi_altern_lba;
1057
1058 /*
1059 * Find the last physically non-zero partition.
1060 * This is the reserved partition.
1061 */
1062 for (i = 0; i < efi_label->efi_nparts; i ++) {
1063 if (resv_start < efi_label->efi_parts[i].p_start) {
1064 resv_start = efi_label->efi_parts[i].p_start;
1065 resv_index = i;
1066 }
1067 }
1068
5c363129 1069 /*
cee43a74
ED
1070 * Find the last physically non-zero partition before that.
1071 * This is the data partition.
5c363129 1072 */
cee43a74
ED
1073 for (i = 0; i < resv_index; i ++) {
1074 if (data_start < efi_label->efi_parts[i].p_start) {
1075 data_start = efi_label->efi_parts[i].p_start;
1076 data_index = i;
1077 }
5c363129
BB
1078 }
1079
1080 /*
1081 * Move the reserved partition. There is currently no data in
1082 * here except fabricated devids (which get generated via
1083 * efi_write()). So there is no need to copy data.
1084 */
cee43a74
ED
1085 efi_label->efi_parts[data_index].p_size += difference;
1086 efi_label->efi_parts[resv_index].p_start += difference;
1087 efi_label->efi_last_u_lba += difference;
5c363129
BB
1088
1089 rval = efi_write(fd, efi_label);
1090 if (rval < 0) {
1091 if (efi_debug) {
1092 (void) fprintf(stderr,
1093 "efi_use_whole_disk:fail to write label, rval=%d\n",
1094 rval);
1095 }
1096 efi_free(efi_label);
1097 return (rval);
1098 }
1099
1100 efi_free(efi_label);
1101 return (0);
1102}
1103
1104
1105/*
1106 * write EFI label and backup label
1107 */
1108int
1109efi_write(int fd, struct dk_gpt *vtoc)
1110{
1111 dk_efi_t dk_ioc;
1112 efi_gpt_t *efi;
1113 efi_gpe_t *efi_parts;
1114 int i, j;
1115 struct dk_cinfo dki_info;
d603ed6c 1116 int rval;
5c363129
BB
1117 int md_flag = 0;
1118 int nblocks;
1119 diskaddr_t lba_backup_gpt_hdr;
1120
d603ed6c 1121 if ((rval = efi_get_info(fd, &dki_info)) != 0)
d1d7e268 1122 return (rval);
5c363129
BB
1123
1124 /* check if we are dealing wih a metadevice */
1125 if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) &&
1126 (strncmp(dki_info.dki_dname, "md", 3) == 0)) {
1127 md_flag = 1;
1128 }
1129
1130 if (check_input(vtoc)) {
1131 /*
1132 * not valid; if it's a metadevice just pass it down
1133 * because SVM will do its own checking
1134 */
1135 if (md_flag == 0) {
1136 return (VT_EINVAL);
1137 }
1138 }
1139
1140 dk_ioc.dki_lba = 1;
1141 if (NBLOCKS(vtoc->efi_nparts, vtoc->efi_lbasize) < 34) {
1142 dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + vtoc->efi_lbasize;
1143 } else {
1144 dk_ioc.dki_length = NBLOCKS(vtoc->efi_nparts,
1145 vtoc->efi_lbasize) *
1146 vtoc->efi_lbasize;
1147 }
1148
1149 /*
1150 * the number of blocks occupied by GUID partition entry array
1151 */
1152 nblocks = dk_ioc.dki_length / vtoc->efi_lbasize - 1;
1153
1154 /*
1155 * Backup GPT header is located on the block after GUID
1156 * partition entry array. Here, we calculate the address
1157 * for backup GPT header.
1158 */
1159 lba_backup_gpt_hdr = vtoc->efi_last_u_lba + 1 + nblocks;
d603ed6c 1160 if (posix_memalign((void **)&dk_ioc.dki_data,
d1d7e268 1161 vtoc->efi_lbasize, dk_ioc.dki_length))
5c363129
BB
1162 return (VT_ERROR);
1163
d603ed6c 1164 memset(dk_ioc.dki_data, 0, dk_ioc.dki_length);
5c363129
BB
1165 efi = dk_ioc.dki_data;
1166
1167 /* stuff user's input into EFI struct */
1168 efi->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
1169 efi->efi_gpt_Revision = LE_32(vtoc->efi_version); /* 0x02000100 */
7a023273 1170 efi->efi_gpt_HeaderSize = LE_32(sizeof (struct efi_gpt) - LEN_EFI_PAD);
5c363129
BB
1171 efi->efi_gpt_Reserved1 = 0;
1172 efi->efi_gpt_MyLBA = LE_64(1ULL);
1173 efi->efi_gpt_AlternateLBA = LE_64(lba_backup_gpt_hdr);
1174 efi->efi_gpt_FirstUsableLBA = LE_64(vtoc->efi_first_u_lba);
1175 efi->efi_gpt_LastUsableLBA = LE_64(vtoc->efi_last_u_lba);
1176 efi->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
1177 efi->efi_gpt_NumberOfPartitionEntries = LE_32(vtoc->efi_nparts);
1178 efi->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (struct efi_gpe));
1179 UUID_LE_CONVERT(efi->efi_gpt_DiskGUID, vtoc->efi_disk_uguid);
1180
1181 /* LINTED -- always longlong aligned */
1182 efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + vtoc->efi_lbasize);
1183
1184 for (i = 0; i < vtoc->efi_nparts; i++) {
1185 for (j = 0;
1186 j < sizeof (conversion_array) /
1187 sizeof (struct uuid_to_ptag); j++) {
1188
1189 if (vtoc->efi_parts[i].p_tag == j) {
1190 UUID_LE_CONVERT(
1191 efi_parts[i].efi_gpe_PartitionTypeGUID,
1192 conversion_array[j].uuid);
1193 break;
1194 }
1195 }
1196
1197 if (j == sizeof (conversion_array) /
1198 sizeof (struct uuid_to_ptag)) {
1199 /*
1200 * If we didn't have a matching uuid match, bail here.
1201 * Don't write a label with unknown uuid.
1202 */
1203 if (efi_debug) {
1204 (void) fprintf(stderr,
1205 "Unknown uuid for p_tag %d\n",
1206 vtoc->efi_parts[i].p_tag);
1207 }
1208 return (VT_EINVAL);
1209 }
1210
d603ed6c
BB
1211 /* Zero's should be written for empty partitions */
1212 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED)
1213 continue;
1214
5c363129
BB
1215 efi_parts[i].efi_gpe_StartingLBA =
1216 LE_64(vtoc->efi_parts[i].p_start);
1217 efi_parts[i].efi_gpe_EndingLBA =
1218 LE_64(vtoc->efi_parts[i].p_start +
1219 vtoc->efi_parts[i].p_size - 1);
1220 efi_parts[i].efi_gpe_Attributes.PartitionAttrs =
1221 LE_16(vtoc->efi_parts[i].p_flag);
1222 for (j = 0; j < EFI_PART_NAME_LEN; j++) {
1223 efi_parts[i].efi_gpe_PartitionName[j] =
1224 LE_16((ushort_t)vtoc->efi_parts[i].p_name[j]);
1225 }
1226 if ((vtoc->efi_parts[i].p_tag != V_UNASSIGNED) &&
1227 uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_uguid)) {
1228 (void) uuid_generate((uchar_t *)
1229 &vtoc->efi_parts[i].p_uguid);
1230 }
1231 bcopy(&vtoc->efi_parts[i].p_uguid,
1232 &efi_parts[i].efi_gpe_UniquePartitionGUID,
1233 sizeof (uuid_t));
1234 }
1235 efi->efi_gpt_PartitionEntryArrayCRC32 =
1236 LE_32(efi_crc32((unsigned char *)efi_parts,
1237 vtoc->efi_nparts * (int)sizeof (struct efi_gpe)));
1238 efi->efi_gpt_HeaderCRC32 =
7a023273
ZB
1239 LE_32(efi_crc32((unsigned char *)efi,
1240 LE_32(efi->efi_gpt_HeaderSize)));
5c363129
BB
1241
1242 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1243 free(dk_ioc.dki_data);
1244 switch (errno) {
1245 case EIO:
1246 return (VT_EIO);
1247 case EINVAL:
1248 return (VT_EINVAL);
1249 default:
1250 return (VT_ERROR);
1251 }
1252 }
1253 /* if it's a metadevice we're done */
1254 if (md_flag) {
1255 free(dk_ioc.dki_data);
1256 return (0);
1257 }
1258
1259 /* write backup partition array */
1260 dk_ioc.dki_lba = vtoc->efi_last_u_lba + 1;
1261 dk_ioc.dki_length -= vtoc->efi_lbasize;
1262 /* LINTED */
1263 dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data +
1264 vtoc->efi_lbasize);
1265
1266 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1267 /*
1268 * we wrote the primary label okay, so don't fail
1269 */
1270 if (efi_debug) {
1271 (void) fprintf(stderr,
1272 "write of backup partitions to block %llu "
1273 "failed, errno %d\n",
1274 vtoc->efi_last_u_lba + 1,
1275 errno);
1276 }
1277 }
1278 /*
1279 * now swap MyLBA and AlternateLBA fields and write backup
1280 * partition table header
1281 */
1282 dk_ioc.dki_lba = lba_backup_gpt_hdr;
1283 dk_ioc.dki_length = vtoc->efi_lbasize;
1284 /* LINTED */
1285 dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data -
1286 vtoc->efi_lbasize);
1287 efi->efi_gpt_AlternateLBA = LE_64(1ULL);
1288 efi->efi_gpt_MyLBA = LE_64(lba_backup_gpt_hdr);
1289 efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1);
1290 efi->efi_gpt_HeaderCRC32 = 0;
1291 efi->efi_gpt_HeaderCRC32 =
1292 LE_32(efi_crc32((unsigned char *)dk_ioc.dki_data,
7a023273 1293 LE_32(efi->efi_gpt_HeaderSize)));
5c363129
BB
1294
1295 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1296 if (efi_debug) {
1297 (void) fprintf(stderr,
1298 "write of backup header to block %llu failed, "
1299 "errno %d\n",
1300 lba_backup_gpt_hdr,
1301 errno);
1302 }
1303 }
1304 /* write the PMBR */
1305 (void) write_pmbr(fd, vtoc);
1306 free(dk_ioc.dki_data);
d603ed6c 1307
5c363129
BB
1308 return (0);
1309}
1310
1311void
1312efi_free(struct dk_gpt *ptr)
1313{
1314 free(ptr);
1315}
1316
1317/*
1318 * Input: File descriptor
1319 * Output: 1 if disk has an EFI label, or > 2TB with no VTOC or legacy MBR.
1320 * Otherwise 0.
1321 */
1322int
1323efi_type(int fd)
1324{
d603ed6c 1325#if 0
5c363129
BB
1326 struct vtoc vtoc;
1327 struct extvtoc extvtoc;
1328
1329 if (ioctl(fd, DKIOCGEXTVTOC, &extvtoc) == -1) {
1330 if (errno == ENOTSUP)
1331 return (1);
1332 else if (errno == ENOTTY) {
1333 if (ioctl(fd, DKIOCGVTOC, &vtoc) == -1)
1334 if (errno == ENOTSUP)
1335 return (1);
1336 }
1337 }
1338 return (0);
d603ed6c
BB
1339#else
1340 return (ENOSYS);
1341#endif
5c363129
BB
1342}
1343
1344void
1345efi_err_check(struct dk_gpt *vtoc)
1346{
1347 int resv_part = -1;
1348 int i, j;
1349 diskaddr_t istart, jstart, isize, jsize, endsect;
1350 int overlap = 0;
1351
1352 /*
1353 * make sure no partitions overlap
1354 */
1355 for (i = 0; i < vtoc->efi_nparts; i++) {
1356 /* It can't be unassigned and have an actual size */
1357 if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) &&
1358 (vtoc->efi_parts[i].p_size != 0)) {
1359 (void) fprintf(stderr,
1360 "partition %d is \"unassigned\" but has a size "
1361 "of %llu\n", i, vtoc->efi_parts[i].p_size);
1362 }
1363 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) {
1364 continue;
1365 }
1366 if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
1367 if (resv_part != -1) {
1368 (void) fprintf(stderr,
1369 "found duplicate reserved partition at "
1370 "%d\n", i);
1371 }
1372 resv_part = i;
1373 if (vtoc->efi_parts[i].p_size != EFI_MIN_RESV_SIZE)
1374 (void) fprintf(stderr,
1375 "Warning: reserved partition size must "
1376 "be %d sectors\n", EFI_MIN_RESV_SIZE);
1377 }
1378 if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) ||
1379 (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) {
1380 (void) fprintf(stderr,
1381 "Partition %d starts at %llu\n",
1382 i,
1383 vtoc->efi_parts[i].p_start);
1384 (void) fprintf(stderr,
1385 "It must be between %llu and %llu.\n",
1386 vtoc->efi_first_u_lba,
1387 vtoc->efi_last_u_lba);
1388 }
1389 if ((vtoc->efi_parts[i].p_start +
1390 vtoc->efi_parts[i].p_size <
1391 vtoc->efi_first_u_lba) ||
1392 (vtoc->efi_parts[i].p_start +
1393 vtoc->efi_parts[i].p_size >
1394 vtoc->efi_last_u_lba + 1)) {
1395 (void) fprintf(stderr,
1396 "Partition %d ends at %llu\n",
1397 i,
1398 vtoc->efi_parts[i].p_start +
1399 vtoc->efi_parts[i].p_size);
1400 (void) fprintf(stderr,
1401 "It must be between %llu and %llu.\n",
1402 vtoc->efi_first_u_lba,
1403 vtoc->efi_last_u_lba);
1404 }
1405
1406 for (j = 0; j < vtoc->efi_nparts; j++) {
1407 isize = vtoc->efi_parts[i].p_size;
1408 jsize = vtoc->efi_parts[j].p_size;
1409 istart = vtoc->efi_parts[i].p_start;
1410 jstart = vtoc->efi_parts[j].p_start;
1411 if ((i != j) && (isize != 0) && (jsize != 0)) {
1412 endsect = jstart + jsize -1;
1413 if ((jstart <= istart) &&
1414 (istart <= endsect)) {
1415 if (!overlap) {
1416 (void) fprintf(stderr,
1417 "label error: EFI Labels do not "
1418 "support overlapping partitions\n");
1419 }
1420 (void) fprintf(stderr,
1421 "Partition %d overlaps partition "
1422 "%d.\n", i, j);
1423 overlap = 1;
1424 }
1425 }
1426 }
1427 }
1428 /* make sure there is a reserved partition */
1429 if (resv_part == -1) {
1430 (void) fprintf(stderr,
1431 "no reserved partition found\n");
1432 }
1433}
1434
1435/*
1436 * We need to get information necessary to construct a *new* efi
1437 * label type
1438 */
1439int
1440efi_auto_sense(int fd, struct dk_gpt **vtoc)
1441{
1442
1443 int i;
1444
1445 /*
1446 * Now build the default partition table
1447 */
1448 if (efi_alloc_and_init(fd, EFI_NUMPAR, vtoc) != 0) {
1449 if (efi_debug) {
1450 (void) fprintf(stderr, "efi_alloc_and_init failed.\n");
1451 }
1452 return (-1);
1453 }
1454
d603ed6c 1455 for (i = 0; i < MIN((*vtoc)->efi_nparts, V_NUMPAR); i++) {
5c363129
BB
1456 (*vtoc)->efi_parts[i].p_tag = default_vtoc_map[i].p_tag;
1457 (*vtoc)->efi_parts[i].p_flag = default_vtoc_map[i].p_flag;
1458 (*vtoc)->efi_parts[i].p_start = 0;
1459 (*vtoc)->efi_parts[i].p_size = 0;
1460 }
1461 /*
1462 * Make constants first
1463 * and variable partitions later
1464 */
1465
1466 /* root partition - s0 128 MB */
1467 (*vtoc)->efi_parts[0].p_start = 34;
1468 (*vtoc)->efi_parts[0].p_size = 262144;
1469
1470 /* partition - s1 128 MB */
1471 (*vtoc)->efi_parts[1].p_start = 262178;
1472 (*vtoc)->efi_parts[1].p_size = 262144;
1473
1474 /* partition -s2 is NOT the Backup disk */
1475 (*vtoc)->efi_parts[2].p_tag = V_UNASSIGNED;
1476
1477 /* partition -s6 /usr partition - HOG */
1478 (*vtoc)->efi_parts[6].p_start = 524322;
1479 (*vtoc)->efi_parts[6].p_size = (*vtoc)->efi_last_u_lba - 524322
1480 - (1024 * 16);
1481
1482 /* efi reserved partition - s9 16K */
1483 (*vtoc)->efi_parts[8].p_start = (*vtoc)->efi_last_u_lba - (1024 * 16);
1484 (*vtoc)->efi_parts[8].p_size = (1024 * 16);
1485 (*vtoc)->efi_parts[8].p_tag = V_RESERVED;
1486 return (0);
1487}