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.
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.
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]
23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2018 by Delphix. All rights reserved.
34 #include <uuid/uuid.h>
37 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/dktp/fdisk.h>
43 #include <sys/efi_partition.h>
44 #include <sys/byteorder.h>
45 #include <sys/vdev_disk.h>
47 #include <linux/blkpg.h>
49 static struct uuid_to_ptag
{
51 } conversion_array
[] = {
58 { EFI_UNUSED
}, /* STAND is never used */
62 { EFI_UNUSED
}, /* CACHE (cachefs) is never used */
79 { EFI_FREEBSD_VINUM
},
89 { EFI_MSFT_STORAGESPACES
},
97 { EFI_FREEBSD_DISKLABEL
},
99 { EFI_AAPL_RAIDOFFLINE
},
102 { EFI_AAPL_TVRECOVERY
},
103 { EFI_AAPL_CORESTORAGE
},
109 { EFI_NETBSD_CRYPT
},
114 { EFI_MIDNIGHTBSD_BOOT
},
115 { EFI_MIDNIGHTBSD_DATA
},
116 { EFI_MIDNIGHTBSD_SWAP
},
117 { EFI_MIDNIGHTBSD_UFS
},
118 { EFI_MIDNIGHTBSD_VINUM
},
119 { EFI_MIDNIGHTBSD_ZFS
},
120 { EFI_CEPH_JOURNAL
},
121 { EFI_CEPH_DMCRYPTJOURNAL
},
123 { EFI_CEPH_DMCRYPTOSD
},
125 { EFI_CEPH_DMCRYPTCREATE
},
126 { EFI_OPENBSD_DISKLABEL
},
133 { EFI_RHT_ROOTAMD64
},
135 { EFI_RHT_ROOTARM64
},
136 { EFI_ACRONIS_SECUREZONE
},
139 { EFI_IBM_PPRPBOOT
},
140 { EFI_FREEDESKTOP_BOOT
}
145 static int efi_read(int, struct dk_gpt
*);
148 * Return a 32-bit CRC of the contents of the buffer. Pre-and-post
149 * one's conditioning will be handled by crc32() internally.
152 efi_crc32(const unsigned char *buf
, unsigned int size
)
154 uint32_t crc
= crc32(0, Z_NULL
, 0);
156 crc
= crc32(crc
, buf
, size
);
162 read_disk_info(int fd
, diskaddr_t
*capacity
, uint_t
*lbsize
)
165 unsigned long long capacity_size
;
167 if (ioctl(fd
, BLKSSZGET
, §or_size
) < 0)
170 if (ioctl(fd
, BLKGETSIZE64
, &capacity_size
) < 0)
173 *lbsize
= (uint_t
)sector_size
;
174 *capacity
= (diskaddr_t
)(capacity_size
/ sector_size
);
180 * Return back the device name associated with the file descriptor. The
181 * caller is responsible for freeing the memory associated with the
185 efi_get_devname(int fd
)
190 * The libefi API only provides the open fd and not the file path.
191 * To handle this realpath(3) is used to resolve the block device
192 * name from /proc/self/fd/<fd>.
194 (void) snprintf(path
, sizeof (path
), "/proc/self/fd/%d", fd
);
195 return (realpath(path
, NULL
));
199 efi_get_info(int fd
, struct dk_cinfo
*dki_info
)
204 memset(dki_info
, 0, sizeof (*dki_info
));
207 * The simplest way to get the partition number under linux is
208 * to parse it out of the /dev/<disk><partition> block device name.
209 * The kernel creates this using the partition number when it
210 * populates /dev/ so it may be trusted. The tricky bit here is
211 * that the naming convention is based on the block device type.
212 * So we need to take this in to account when parsing out the
213 * partition information. Aside from the partition number we collect
214 * some additional device info.
216 dev_path
= efi_get_devname(fd
);
217 if (dev_path
== NULL
)
220 if ((strncmp(dev_path
, "/dev/sd", 7) == 0)) {
221 strcpy(dki_info
->dki_cname
, "sd");
222 dki_info
->dki_ctype
= DKC_SCSI_CCS
;
223 rval
= sscanf(dev_path
, "/dev/%[a-zA-Z]%hu",
225 &dki_info
->dki_partition
);
226 } else if ((strncmp(dev_path
, "/dev/hd", 7) == 0)) {
227 strcpy(dki_info
->dki_cname
, "hd");
228 dki_info
->dki_ctype
= DKC_DIRECT
;
229 rval
= sscanf(dev_path
, "/dev/%[a-zA-Z]%hu",
231 &dki_info
->dki_partition
);
232 } else if ((strncmp(dev_path
, "/dev/md", 7) == 0)) {
233 strcpy(dki_info
->dki_cname
, "pseudo");
234 dki_info
->dki_ctype
= DKC_MD
;
235 strcpy(dki_info
->dki_dname
, "md");
236 rval
= sscanf(dev_path
, "/dev/md%[0-9]p%hu",
237 dki_info
->dki_dname
+ 2,
238 &dki_info
->dki_partition
);
239 } else if ((strncmp(dev_path
, "/dev/vd", 7) == 0)) {
240 strcpy(dki_info
->dki_cname
, "vd");
241 dki_info
->dki_ctype
= DKC_MD
;
242 rval
= sscanf(dev_path
, "/dev/%[a-zA-Z]%hu",
244 &dki_info
->dki_partition
);
245 } else if ((strncmp(dev_path
, "/dev/xvd", 8) == 0)) {
246 strcpy(dki_info
->dki_cname
, "xvd");
247 dki_info
->dki_ctype
= DKC_MD
;
248 rval
= sscanf(dev_path
, "/dev/%[a-zA-Z]%hu",
250 &dki_info
->dki_partition
);
251 } else if ((strncmp(dev_path
, "/dev/zd", 7) == 0)) {
252 strcpy(dki_info
->dki_cname
, "zd");
253 dki_info
->dki_ctype
= DKC_MD
;
254 strcpy(dki_info
->dki_dname
, "zd");
255 rval
= sscanf(dev_path
, "/dev/zd%[0-9]p%hu",
256 dki_info
->dki_dname
+ 2,
257 &dki_info
->dki_partition
);
258 } else if ((strncmp(dev_path
, "/dev/dm-", 8) == 0)) {
259 strcpy(dki_info
->dki_cname
, "pseudo");
260 dki_info
->dki_ctype
= DKC_VBD
;
261 strcpy(dki_info
->dki_dname
, "dm-");
262 rval
= sscanf(dev_path
, "/dev/dm-%[0-9]p%hu",
263 dki_info
->dki_dname
+ 3,
264 &dki_info
->dki_partition
);
265 } else if ((strncmp(dev_path
, "/dev/ram", 8) == 0)) {
266 strcpy(dki_info
->dki_cname
, "pseudo");
267 dki_info
->dki_ctype
= DKC_PCMCIA_MEM
;
268 strcpy(dki_info
->dki_dname
, "ram");
269 rval
= sscanf(dev_path
, "/dev/ram%[0-9]p%hu",
270 dki_info
->dki_dname
+ 3,
271 &dki_info
->dki_partition
);
272 } else if ((strncmp(dev_path
, "/dev/loop", 9) == 0)) {
273 strcpy(dki_info
->dki_cname
, "pseudo");
274 dki_info
->dki_ctype
= DKC_VBD
;
275 strcpy(dki_info
->dki_dname
, "loop");
276 rval
= sscanf(dev_path
, "/dev/loop%[0-9]p%hu",
277 dki_info
->dki_dname
+ 4,
278 &dki_info
->dki_partition
);
279 } else if ((strncmp(dev_path
, "/dev/nvme", 9) == 0)) {
280 strcpy(dki_info
->dki_cname
, "nvme");
281 dki_info
->dki_ctype
= DKC_SCSI_CCS
;
282 strcpy(dki_info
->dki_dname
, "nvme");
283 (void) sscanf(dev_path
, "/dev/nvme%[0-9]",
284 dki_info
->dki_dname
+ 4);
285 size_t controller_length
= strlen(
286 dki_info
->dki_dname
);
287 strcpy(dki_info
->dki_dname
+ controller_length
,
289 rval
= sscanf(dev_path
,
290 "/dev/nvme%*[0-9]n%[0-9]p%hu",
291 dki_info
->dki_dname
+ controller_length
+ 1,
292 &dki_info
->dki_partition
);
294 strcpy(dki_info
->dki_dname
, "unknown");
295 strcpy(dki_info
->dki_cname
, "unknown");
296 dki_info
->dki_ctype
= DKC_UNKNOWN
;
304 dki_info
->dki_partition
= 0;
312 (void) fprintf(stderr
, "DKIOCINFO errno 0x%x\n", errno
);
325 * the number of blocks the EFI label takes up (round up to nearest
328 #define NBLOCKS(p, l) (1 + ((((p) * (int)sizeof (efi_gpe_t)) + \
330 /* number of partitions -- limited by what we can malloc */
331 #define MAX_PARTS ((4294967295UL - sizeof (struct dk_gpt)) / \
332 sizeof (struct dk_part))
335 efi_alloc_and_init(int fd
, uint32_t nparts
, struct dk_gpt
**vtoc
)
337 diskaddr_t capacity
= 0;
343 struct dk_cinfo dki_info
;
345 if (read_disk_info(fd
, &capacity
, &lbsize
) != 0)
348 if (efi_get_info(fd
, &dki_info
) != 0)
351 if (dki_info
.dki_partition
!= 0)
354 if ((dki_info
.dki_ctype
== DKC_PCMCIA_MEM
) ||
355 (dki_info
.dki_ctype
== DKC_VBD
) ||
356 (dki_info
.dki_ctype
== DKC_UNKNOWN
))
359 nblocks
= NBLOCKS(nparts
, lbsize
);
360 if ((nblocks
* lbsize
) < EFI_MIN_ARRAY_SIZE
+ lbsize
) {
361 /* 16K plus one block for the GPT */
362 nblocks
= EFI_MIN_ARRAY_SIZE
/ lbsize
+ 1;
365 if (nparts
> MAX_PARTS
) {
367 (void) fprintf(stderr
,
368 "the maximum number of partitions supported is %lu\n",
374 length
= sizeof (struct dk_gpt
) +
375 sizeof (struct dk_part
) * (nparts
- 1);
377 vptr
= calloc(1, length
);
383 vptr
->efi_version
= EFI_VERSION_CURRENT
;
384 vptr
->efi_lbasize
= lbsize
;
385 vptr
->efi_nparts
= nparts
;
387 * add one block here for the PMBR; on disks with a 512 byte
388 * block size and 128 or fewer partitions, efi_first_u_lba
389 * should work out to "34"
391 vptr
->efi_first_u_lba
= nblocks
+ 1;
392 vptr
->efi_last_lba
= capacity
- 1;
393 vptr
->efi_altern_lba
= capacity
-1;
394 vptr
->efi_last_u_lba
= vptr
->efi_last_lba
- nblocks
;
396 (void) uuid_generate((uchar_t
*)&uuid
);
397 UUID_LE_CONVERT(vptr
->efi_disk_uguid
, uuid
);
402 * Read EFI - return partition number upon success.
405 efi_alloc_and_read(int fd
, struct dk_gpt
**vtoc
)
412 /* figure out the number of entries that would fit into 16K */
413 nparts
= EFI_MIN_ARRAY_SIZE
/ sizeof (efi_gpe_t
);
414 length
= (int) sizeof (struct dk_gpt
) +
415 (int) sizeof (struct dk_part
) * (nparts
- 1);
416 vptr
= calloc(1, length
);
421 vptr
->efi_nparts
= nparts
;
422 rval
= efi_read(fd
, vptr
);
424 if ((rval
== VT_EINVAL
) && vptr
->efi_nparts
> nparts
) {
426 length
= (int) sizeof (struct dk_gpt
) +
427 (int) sizeof (struct dk_part
) * (vptr
->efi_nparts
- 1);
428 nparts
= vptr
->efi_nparts
;
429 if ((tmp
= realloc(vptr
, length
)) == NULL
) {
430 /* cppcheck-suppress doubleFree */
436 rval
= efi_read(fd
, vptr
);
442 (void) fprintf(stderr
,
443 "read of EFI table failed, rval=%d\n", rval
);
455 efi_ioctl(int fd
, int cmd
, dk_efi_t
*dk_ioc
)
457 void *data
= dk_ioc
->dki_data
;
463 * When the IO is not being performed in kernel as an ioctl we need
464 * to know the sector size so we can seek to the proper byte offset.
466 if (read_disk_info(fd
, &capacity
, &lbsize
) == -1) {
468 fprintf(stderr
, "unable to read disk info: %d", errno
);
478 (void) fprintf(stderr
, "DKIOCGETEFI assuming "
479 "LBA %d bytes\n", DEV_BSIZE
);
484 error
= lseek(fd
, dk_ioc
->dki_lba
* lbsize
, SEEK_SET
);
487 (void) fprintf(stderr
, "DKIOCGETEFI lseek "
488 "error: %d\n", errno
);
492 error
= read(fd
, data
, dk_ioc
->dki_length
);
495 (void) fprintf(stderr
, "DKIOCGETEFI read "
496 "error: %d\n", errno
);
500 if (error
!= dk_ioc
->dki_length
) {
502 (void) fprintf(stderr
, "DKIOCGETEFI short "
503 "read of %d bytes\n", error
);
513 (void) fprintf(stderr
, "DKIOCSETEFI unknown "
519 error
= lseek(fd
, dk_ioc
->dki_lba
* lbsize
, SEEK_SET
);
522 (void) fprintf(stderr
, "DKIOCSETEFI lseek "
523 "error: %d\n", errno
);
527 error
= write(fd
, data
, dk_ioc
->dki_length
);
530 (void) fprintf(stderr
, "DKIOCSETEFI write "
531 "error: %d\n", errno
);
535 if (error
!= dk_ioc
->dki_length
) {
537 (void) fprintf(stderr
, "DKIOCSETEFI short "
538 "write of %d bytes\n", error
);
543 /* Sync the new EFI table to disk */
548 /* Ensure any local disk cache is also flushed */
549 if (ioctl(fd
, BLKFLSBUF
, 0) == -1)
557 (void) fprintf(stderr
, "unsupported ioctl()\n");
572 /* Notify the kernel a devices partition table has been updated */
573 while ((error
= ioctl(fd
, BLKRRPART
)) != 0) {
574 if ((--retry
== 0) || (errno
!= EBUSY
)) {
575 (void) fprintf(stderr
, "the kernel failed to rescan "
576 "the partition table: %d\n", errno
);
586 check_label(int fd
, dk_efi_t
*dk_ioc
)
591 if (efi_ioctl(fd
, DKIOCGETEFI
, dk_ioc
) == -1) {
599 efi
= dk_ioc
->dki_data
;
600 if (efi
->efi_gpt_Signature
!= LE_64(EFI_SIGNATURE
)) {
602 (void) fprintf(stderr
,
603 "Bad EFI signature: 0x%llx != 0x%llx\n",
604 (long long)efi
->efi_gpt_Signature
,
605 (long long)LE_64(EFI_SIGNATURE
));
610 * check CRC of the header; the size of the header should
611 * never be larger than one block
613 crc
= efi
->efi_gpt_HeaderCRC32
;
614 efi
->efi_gpt_HeaderCRC32
= 0;
615 len_t headerSize
= (len_t
)LE_32(efi
->efi_gpt_HeaderSize
);
617 if (headerSize
< EFI_MIN_LABEL_SIZE
|| headerSize
> EFI_LABEL_SIZE
) {
619 (void) fprintf(stderr
,
620 "Invalid EFI HeaderSize %llu. Assuming %d.\n",
621 headerSize
, EFI_MIN_LABEL_SIZE
);
624 if ((headerSize
> dk_ioc
->dki_length
) ||
625 crc
!= LE_32(efi_crc32((unsigned char *)efi
, headerSize
))) {
627 (void) fprintf(stderr
,
628 "Bad EFI CRC: 0x%x != 0x%x\n",
629 crc
, LE_32(efi_crc32((unsigned char *)efi
,
638 efi_read(int fd
, struct dk_gpt
*vtoc
)
645 diskaddr_t capacity
= 0;
647 struct dk_minfo disk_info
;
650 efi_gpe_t
*efi_parts
;
651 struct dk_cinfo dki_info
;
652 uint32_t user_length
;
653 boolean_t legacy_label
= B_FALSE
;
656 * get the partition number for this file descriptor.
658 if ((rval
= efi_get_info(fd
, &dki_info
)) != 0)
661 if ((strncmp(dki_info
.dki_cname
, "pseudo", 7) == 0) &&
662 (strncmp(dki_info
.dki_dname
, "md", 3) == 0)) {
664 } else if ((strncmp(dki_info
.dki_cname
, "vdc", 4) == 0) &&
665 (strncmp(dki_info
.dki_dname
, "vdc", 4) == 0)) {
667 * The controller and drive name "vdc" (virtual disk client)
668 * indicates a LDoms virtual disk.
673 /* get the LBA size */
674 if (read_disk_info(fd
, &capacity
, &lbsize
) == -1) {
676 (void) fprintf(stderr
,
677 "unable to read disk info: %d",
683 disk_info
.dki_lbsize
= lbsize
;
684 disk_info
.dki_capacity
= capacity
;
686 if (disk_info
.dki_lbsize
== 0) {
688 (void) fprintf(stderr
,
689 "efi_read: assuming LBA 512 bytes\n");
691 disk_info
.dki_lbsize
= DEV_BSIZE
;
694 * Read the EFI GPT to figure out how many partitions we need
698 if (NBLOCKS(vtoc
->efi_nparts
, disk_info
.dki_lbsize
) < 34) {
699 label_len
= EFI_MIN_ARRAY_SIZE
+ disk_info
.dki_lbsize
;
701 label_len
= vtoc
->efi_nparts
* (int) sizeof (efi_gpe_t
) +
702 disk_info
.dki_lbsize
;
703 if (label_len
% disk_info
.dki_lbsize
) {
704 /* pad to physical sector size */
705 label_len
+= disk_info
.dki_lbsize
;
706 label_len
&= ~(disk_info
.dki_lbsize
- 1);
710 if (posix_memalign((void **)&dk_ioc
.dki_data
,
711 disk_info
.dki_lbsize
, label_len
))
714 memset(dk_ioc
.dki_data
, 0, label_len
);
715 dk_ioc
.dki_length
= disk_info
.dki_lbsize
;
716 user_length
= vtoc
->efi_nparts
;
717 efi
= dk_ioc
.dki_data
;
719 dk_ioc
.dki_length
= label_len
;
720 if (efi_ioctl(fd
, DKIOCGETEFI
, &dk_ioc
) == -1) {
728 } else if ((rval
= check_label(fd
, &dk_ioc
)) == VT_EINVAL
) {
730 * No valid label here; try the alternate. Note that here
731 * we just read GPT header and save it into dk_ioc.data,
732 * Later, we will read GUID partition entry array if we
733 * can get valid GPT header.
737 * This is a workaround for legacy systems. In the past, the
738 * last sector of SCSI disk was invisible on x86 platform. At
739 * that time, backup label was saved on the next to the last
740 * sector. It is possible for users to move a disk from previous
741 * solaris system to present system. Here, we attempt to search
742 * legacy backup EFI label first.
744 dk_ioc
.dki_lba
= disk_info
.dki_capacity
- 2;
745 dk_ioc
.dki_length
= disk_info
.dki_lbsize
;
746 rval
= check_label(fd
, &dk_ioc
);
747 if (rval
== VT_EINVAL
) {
749 * we didn't find legacy backup EFI label, try to
750 * search backup EFI label in the last block.
752 dk_ioc
.dki_lba
= disk_info
.dki_capacity
- 1;
753 dk_ioc
.dki_length
= disk_info
.dki_lbsize
;
754 rval
= check_label(fd
, &dk_ioc
);
756 legacy_label
= B_TRUE
;
758 (void) fprintf(stderr
,
759 "efi_read: primary label corrupt; "
760 "using EFI backup label located on"
761 " the last block\n");
764 if ((efi_debug
) && (rval
== 0))
765 (void) fprintf(stderr
, "efi_read: primary label"
766 " corrupt; using legacy EFI backup label "
767 " located on the next to last block\n");
771 dk_ioc
.dki_lba
= LE_64(efi
->efi_gpt_PartitionEntryLBA
);
772 vtoc
->efi_flags
|= EFI_GPT_PRIMARY_CORRUPT
;
774 LE_32(efi
->efi_gpt_NumberOfPartitionEntries
);
776 * Partition tables are between backup GPT header
777 * table and ParitionEntryLBA (the starting LBA of
778 * the GUID partition entries array). Now that we
779 * already got valid GPT header and saved it in
780 * dk_ioc.dki_data, we try to get GUID partition
784 dk_ioc
.dki_data
= (efi_gpt_t
*)((char *)dk_ioc
.dki_data
785 + disk_info
.dki_lbsize
);
787 dk_ioc
.dki_length
= disk_info
.dki_capacity
- 1 -
790 dk_ioc
.dki_length
= disk_info
.dki_capacity
- 2 -
792 dk_ioc
.dki_length
*= disk_info
.dki_lbsize
;
793 if (dk_ioc
.dki_length
>
794 ((len_t
)label_len
- sizeof (*dk_ioc
.dki_data
))) {
798 * read GUID partition entry array
800 rval
= efi_ioctl(fd
, DKIOCGETEFI
, &dk_ioc
);
804 } else if (rval
== 0) {
806 dk_ioc
.dki_lba
= LE_64(efi
->efi_gpt_PartitionEntryLBA
);
808 dk_ioc
.dki_data
= (efi_gpt_t
*)((char *)dk_ioc
.dki_data
809 + disk_info
.dki_lbsize
);
810 dk_ioc
.dki_length
= label_len
- disk_info
.dki_lbsize
;
811 rval
= efi_ioctl(fd
, DKIOCGETEFI
, &dk_ioc
);
813 } else if (vdc_flag
&& rval
== VT_ERROR
&& errno
== EINVAL
) {
815 * When the device is a LDoms virtual disk, the DKIOCGETEFI
816 * ioctl can fail with EINVAL if the virtual disk backend
817 * is a ZFS volume serviced by a domain running an old version
818 * of Solaris. This is because the DKIOCGETEFI ioctl was
819 * initially incorrectly implemented for a ZFS volume and it
820 * expected the GPT and GPE to be retrieved with a single ioctl.
821 * So we try to read the GPT and the GPE using that old style
825 dk_ioc
.dki_length
= label_len
;
826 rval
= check_label(fd
, &dk_ioc
);
834 /* LINTED -- always longlong aligned */
835 efi_parts
= (efi_gpe_t
*)(((char *)efi
) + disk_info
.dki_lbsize
);
838 * Assemble this into a "dk_gpt" struct for easier
839 * digestibility by applications.
841 vtoc
->efi_version
= LE_32(efi
->efi_gpt_Revision
);
842 vtoc
->efi_nparts
= LE_32(efi
->efi_gpt_NumberOfPartitionEntries
);
843 vtoc
->efi_part_size
= LE_32(efi
->efi_gpt_SizeOfPartitionEntry
);
844 vtoc
->efi_lbasize
= disk_info
.dki_lbsize
;
845 vtoc
->efi_last_lba
= disk_info
.dki_capacity
- 1;
846 vtoc
->efi_first_u_lba
= LE_64(efi
->efi_gpt_FirstUsableLBA
);
847 vtoc
->efi_last_u_lba
= LE_64(efi
->efi_gpt_LastUsableLBA
);
848 vtoc
->efi_altern_lba
= LE_64(efi
->efi_gpt_AlternateLBA
);
849 UUID_LE_CONVERT(vtoc
->efi_disk_uguid
, efi
->efi_gpt_DiskGUID
);
852 * If the array the user passed in is too small, set the length
853 * to what it needs to be and return
855 if (user_length
< vtoc
->efi_nparts
) {
859 for (i
= 0; i
< vtoc
->efi_nparts
; i
++) {
861 UUID_LE_CONVERT(vtoc
->efi_parts
[i
].p_guid
,
862 efi_parts
[i
].efi_gpe_PartitionTypeGUID
);
865 j
< sizeof (conversion_array
)
866 / sizeof (struct uuid_to_ptag
); j
++) {
868 if (memcmp(&vtoc
->efi_parts
[i
].p_guid
,
869 &conversion_array
[j
].uuid
,
870 sizeof (struct uuid
)) == 0) {
871 vtoc
->efi_parts
[i
].p_tag
= j
;
875 if (vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
)
877 vtoc
->efi_parts
[i
].p_flag
=
878 LE_16(efi_parts
[i
].efi_gpe_Attributes
.PartitionAttrs
);
879 vtoc
->efi_parts
[i
].p_start
=
880 LE_64(efi_parts
[i
].efi_gpe_StartingLBA
);
881 vtoc
->efi_parts
[i
].p_size
=
882 LE_64(efi_parts
[i
].efi_gpe_EndingLBA
) -
883 vtoc
->efi_parts
[i
].p_start
+ 1;
884 for (j
= 0; j
< EFI_PART_NAME_LEN
; j
++) {
885 vtoc
->efi_parts
[i
].p_name
[j
] =
887 efi_parts
[i
].efi_gpe_PartitionName
[j
]);
890 UUID_LE_CONVERT(vtoc
->efi_parts
[i
].p_uguid
,
891 efi_parts
[i
].efi_gpe_UniquePartitionGUID
);
895 return (dki_info
.dki_partition
);
898 /* writes a "protective" MBR */
900 write_pmbr(int fd
, struct dk_gpt
*vtoc
)
905 diskaddr_t size_in_lba
;
909 len
= (vtoc
->efi_lbasize
== 0) ? sizeof (mb
) : vtoc
->efi_lbasize
;
910 if (posix_memalign((void **)&buf
, len
, len
))
914 * Preserve any boot code and disk signature if the first block is
919 dk_ioc
.dki_length
= len
;
920 /* LINTED -- always longlong aligned */
921 dk_ioc
.dki_data
= (efi_gpt_t
*)buf
;
922 if (efi_ioctl(fd
, DKIOCGETEFI
, &dk_ioc
) == -1) {
923 memset(&mb
, 0, sizeof (mb
));
924 mb
.signature
= LE_16(MBB_MAGIC
);
926 (void) memcpy(&mb
, buf
, sizeof (mb
));
927 if (mb
.signature
!= LE_16(MBB_MAGIC
)) {
928 memset(&mb
, 0, sizeof (mb
));
929 mb
.signature
= LE_16(MBB_MAGIC
);
933 memset(&mb
.parts
, 0, sizeof (mb
.parts
));
934 cp
= (uchar_t
*)&mb
.parts
[0];
935 /* bootable or not */
937 /* beginning CHS; 0xffffff if not representable */
943 /* ending CHS; 0xffffff if not representable */
947 /* starting LBA: 1 (little endian format) by EFI definition */
952 /* ending LBA: last block on the disk (little endian format) */
953 size_in_lba
= vtoc
->efi_last_lba
;
954 if (size_in_lba
< 0xffffffff) {
955 *cp
++ = (size_in_lba
& 0x000000ff);
956 *cp
++ = (size_in_lba
& 0x0000ff00) >> 8;
957 *cp
++ = (size_in_lba
& 0x00ff0000) >> 16;
958 *cp
++ = (size_in_lba
& 0xff000000) >> 24;
966 (void) memcpy(buf
, &mb
, sizeof (mb
));
967 /* LINTED -- always longlong aligned */
968 dk_ioc
.dki_data
= (efi_gpt_t
*)buf
;
970 dk_ioc
.dki_length
= len
;
971 if (efi_ioctl(fd
, DKIOCSETEFI
, &dk_ioc
) == -1) {
986 /* make sure the user specified something reasonable */
988 check_input(struct dk_gpt
*vtoc
)
992 diskaddr_t istart
, jstart
, isize
, jsize
, endsect
;
995 * Sanity-check the input (make sure no partitions overlap)
997 for (i
= 0; i
< vtoc
->efi_nparts
; i
++) {
998 /* It can't be unassigned and have an actual size */
999 if ((vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
) &&
1000 (vtoc
->efi_parts
[i
].p_size
!= 0)) {
1002 (void) fprintf(stderr
, "partition %d is "
1003 "\"unassigned\" but has a size of %llu",
1004 i
, vtoc
->efi_parts
[i
].p_size
);
1008 if (vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
) {
1009 if (uuid_is_null((uchar_t
*)&vtoc
->efi_parts
[i
].p_guid
))
1011 /* we have encountered an unknown uuid */
1012 vtoc
->efi_parts
[i
].p_tag
= 0xff;
1014 if (vtoc
->efi_parts
[i
].p_tag
== V_RESERVED
) {
1015 if (resv_part
!= -1) {
1017 (void) fprintf(stderr
, "found "
1018 "duplicate reserved partition "
1025 if ((vtoc
->efi_parts
[i
].p_start
< vtoc
->efi_first_u_lba
) ||
1026 (vtoc
->efi_parts
[i
].p_start
> vtoc
->efi_last_u_lba
)) {
1028 (void) fprintf(stderr
,
1029 "Partition %d starts at %llu. ",
1031 vtoc
->efi_parts
[i
].p_start
);
1032 (void) fprintf(stderr
,
1033 "It must be between %llu and %llu.\n",
1034 vtoc
->efi_first_u_lba
,
1035 vtoc
->efi_last_u_lba
);
1039 if ((vtoc
->efi_parts
[i
].p_start
+
1040 vtoc
->efi_parts
[i
].p_size
<
1041 vtoc
->efi_first_u_lba
) ||
1042 (vtoc
->efi_parts
[i
].p_start
+
1043 vtoc
->efi_parts
[i
].p_size
>
1044 vtoc
->efi_last_u_lba
+ 1)) {
1046 (void) fprintf(stderr
,
1047 "Partition %d ends at %llu. ",
1049 vtoc
->efi_parts
[i
].p_start
+
1050 vtoc
->efi_parts
[i
].p_size
);
1051 (void) fprintf(stderr
,
1052 "It must be between %llu and %llu.\n",
1053 vtoc
->efi_first_u_lba
,
1054 vtoc
->efi_last_u_lba
);
1059 for (j
= 0; j
< vtoc
->efi_nparts
; j
++) {
1060 isize
= vtoc
->efi_parts
[i
].p_size
;
1061 jsize
= vtoc
->efi_parts
[j
].p_size
;
1062 istart
= vtoc
->efi_parts
[i
].p_start
;
1063 jstart
= vtoc
->efi_parts
[j
].p_start
;
1064 if ((i
!= j
) && (isize
!= 0) && (jsize
!= 0)) {
1065 endsect
= jstart
+ jsize
-1;
1066 if ((jstart
<= istart
) &&
1067 (istart
<= endsect
)) {
1069 (void) fprintf(stderr
,
1070 "Partition %d overlaps "
1071 "partition %d.", i
, j
);
1078 /* just a warning for now */
1079 if ((resv_part
== -1) && efi_debug
) {
1080 (void) fprintf(stderr
,
1081 "no reserved partition found\n");
1087 call_blkpg_ioctl(int fd
, int command
, diskaddr_t start
,
1088 diskaddr_t size
, uint_t pno
)
1090 struct blkpg_ioctl_arg ioctl_arg
;
1091 struct blkpg_partition linux_part
;
1092 memset(&linux_part
, 0, sizeof (linux_part
));
1094 char *path
= efi_get_devname(fd
);
1096 (void) fprintf(stderr
, "failed to retrieve device name\n");
1100 linux_part
.start
= start
;
1101 linux_part
.length
= size
;
1102 linux_part
.pno
= pno
;
1103 snprintf(linux_part
.devname
, BLKPG_DEVNAMELTH
- 1, "%s%u", path
, pno
);
1104 linux_part
.devname
[BLKPG_DEVNAMELTH
- 1] = '\0';
1107 ioctl_arg
.op
= command
;
1108 ioctl_arg
.flags
= 0;
1109 ioctl_arg
.datalen
= sizeof (struct blkpg_partition
);
1110 ioctl_arg
.data
= &linux_part
;
1112 return (ioctl(fd
, BLKPG
, &ioctl_arg
));
1116 * add all the unallocated space to the current label
1119 efi_use_whole_disk(int fd
)
1121 struct dk_gpt
*efi_label
= NULL
;
1124 uint_t resv_index
= 0, data_index
= 0;
1125 diskaddr_t resv_start
= 0, data_start
= 0;
1126 diskaddr_t data_size
, limit
, difference
;
1127 boolean_t sync_needed
= B_FALSE
;
1130 rval
= efi_alloc_and_read(fd
, &efi_label
);
1132 if (efi_label
!= NULL
)
1133 efi_free(efi_label
);
1138 * Find the last physically non-zero partition.
1139 * This should be the reserved partition.
1141 for (i
= 0; i
< efi_label
->efi_nparts
; i
++) {
1142 if (resv_start
< efi_label
->efi_parts
[i
].p_start
) {
1143 resv_start
= efi_label
->efi_parts
[i
].p_start
;
1149 * Find the last physically non-zero partition before that.
1150 * This is the data partition.
1152 for (i
= 0; i
< resv_index
; i
++) {
1153 if (data_start
< efi_label
->efi_parts
[i
].p_start
) {
1154 data_start
= efi_label
->efi_parts
[i
].p_start
;
1158 data_size
= efi_label
->efi_parts
[data_index
].p_size
;
1161 * See the "efi_alloc_and_init" function for more information
1162 * about where this "nblocks" value comes from.
1164 nblocks
= efi_label
->efi_first_u_lba
- 1;
1167 * Determine if the EFI label is out of sync. We check that:
1169 * 1. the data partition ends at the limit we set, and
1170 * 2. the reserved partition starts at the limit we set.
1172 * If either of these conditions is not met, then we need to
1173 * resync the EFI label.
1175 * The limit is the last usable LBA, determined by the last LBA
1176 * and the first usable LBA fields on the EFI label of the disk
1177 * (see the lines directly above). Additionally, we factor in
1178 * EFI_MIN_RESV_SIZE (per its use in "zpool_label_disk") and
1179 * P2ALIGN it to ensure the partition boundaries are aligned
1180 * (for performance reasons). The alignment should match the
1181 * alignment used by the "zpool_label_disk" function.
1183 limit
= P2ALIGN(efi_label
->efi_last_lba
- nblocks
- EFI_MIN_RESV_SIZE
,
1184 PARTITION_END_ALIGNMENT
);
1185 if (data_start
+ data_size
!= limit
|| resv_start
!= limit
)
1186 sync_needed
= B_TRUE
;
1188 if (efi_debug
&& sync_needed
)
1189 (void) fprintf(stderr
, "efi_use_whole_disk: sync needed\n");
1192 * If alter_lba is 1, we are using the backup label.
1193 * Since we can locate the backup label by disk capacity,
1194 * there must be no unallocated space.
1196 if ((efi_label
->efi_altern_lba
== 1) || (efi_label
->efi_altern_lba
1197 >= efi_label
->efi_last_lba
&& !sync_needed
)) {
1199 (void) fprintf(stderr
,
1200 "efi_use_whole_disk: requested space not found\n");
1202 efi_free(efi_label
);
1207 * Verify that we've found the reserved partition by checking
1208 * that it looks the way it did when we created it in zpool_label_disk.
1209 * If we've found the incorrect partition, then we know that this
1210 * device was reformatted and no longer is solely used by ZFS.
1212 if ((efi_label
->efi_parts
[resv_index
].p_size
!= EFI_MIN_RESV_SIZE
) ||
1213 (efi_label
->efi_parts
[resv_index
].p_tag
!= V_RESERVED
) ||
1214 (resv_index
!= 8)) {
1216 (void) fprintf(stderr
,
1217 "efi_use_whole_disk: wholedisk not available\n");
1219 efi_free(efi_label
);
1223 if (data_start
+ data_size
!= resv_start
) {
1225 (void) fprintf(stderr
,
1226 "efi_use_whole_disk: "
1227 "data_start (%lli) + "
1228 "data_size (%lli) != "
1229 "resv_start (%lli)\n",
1230 data_start
, data_size
, resv_start
);
1236 if (limit
< resv_start
) {
1238 (void) fprintf(stderr
,
1239 "efi_use_whole_disk: "
1240 "limit (%lli) < resv_start (%lli)\n",
1247 difference
= limit
- resv_start
;
1250 (void) fprintf(stderr
,
1251 "efi_use_whole_disk: difference is %lli\n", difference
);
1254 * Move the reserved partition. There is currently no data in
1255 * here except fabricated devids (which get generated via
1256 * efi_write()). So there is no need to copy data.
1258 efi_label
->efi_parts
[data_index
].p_size
+= difference
;
1259 efi_label
->efi_parts
[resv_index
].p_start
+= difference
;
1260 efi_label
->efi_last_u_lba
= efi_label
->efi_last_lba
- nblocks
;
1263 * Rescanning the partition table in the kernel can result
1264 * in the device links to be removed (see comment in vdev_disk_open).
1265 * If BLKPG_RESIZE_PARTITION is available, then we can resize
1266 * the partition table online and avoid having to remove the device
1267 * links used by the pool. This provides a very deterministic
1268 * approach to resizing devices and does not require any
1269 * loops waiting for devices to reappear.
1271 #ifdef BLKPG_RESIZE_PARTITION
1273 * Delete the reserved partition since we're about to expand
1274 * the data partition and it would overlap with the reserved
1276 * NOTE: The starting index for the ioctl is 1 while for the
1277 * EFI partitions it's 0. For that reason we have to add one
1278 * whenever we make an ioctl call.
1280 rval
= call_blkpg_ioctl(fd
, BLKPG_DEL_PARTITION
, 0, 0, resv_index
+ 1);
1285 * Expand the data partition
1287 rval
= call_blkpg_ioctl(fd
, BLKPG_RESIZE_PARTITION
,
1288 efi_label
->efi_parts
[data_index
].p_start
* efi_label
->efi_lbasize
,
1289 efi_label
->efi_parts
[data_index
].p_size
* efi_label
->efi_lbasize
,
1292 (void) fprintf(stderr
, "Unable to resize data "
1293 "partition: %d\n", rval
);
1295 * Since we failed to resize, we need to reset the start
1296 * of the reserve partition and re-create it.
1298 efi_label
->efi_parts
[resv_index
].p_start
-= difference
;
1302 * Re-add the reserved partition. If we've expanded the data partition
1303 * then we'll move the reserve partition to the end of the data
1304 * partition. Otherwise, we'll recreate the partition in its original
1305 * location. Note that we do this as best-effort and ignore any
1306 * errors that may arise here. This will ensure that we finish writing
1309 (void) call_blkpg_ioctl(fd
, BLKPG_ADD_PARTITION
,
1310 efi_label
->efi_parts
[resv_index
].p_start
* efi_label
->efi_lbasize
,
1311 efi_label
->efi_parts
[resv_index
].p_size
* efi_label
->efi_lbasize
,
1316 * We're now ready to write the EFI label.
1319 rval
= efi_write(fd
, efi_label
);
1320 if (rval
< 0 && efi_debug
) {
1321 (void) fprintf(stderr
, "efi_use_whole_disk:fail "
1322 "to write label, rval=%d\n", rval
);
1327 efi_free(efi_label
);
1332 * write EFI label and backup label
1335 efi_write(int fd
, struct dk_gpt
*vtoc
)
1339 efi_gpe_t
*efi_parts
;
1341 struct dk_cinfo dki_info
;
1345 diskaddr_t lba_backup_gpt_hdr
;
1347 if ((rval
= efi_get_info(fd
, &dki_info
)) != 0)
1350 /* check if we are dealing with a metadevice */
1351 if ((strncmp(dki_info
.dki_cname
, "pseudo", 7) == 0) &&
1352 (strncmp(dki_info
.dki_dname
, "md", 3) == 0)) {
1356 if (check_input(vtoc
)) {
1358 * not valid; if it's a metadevice just pass it down
1359 * because SVM will do its own checking
1367 if (NBLOCKS(vtoc
->efi_nparts
, vtoc
->efi_lbasize
) < 34) {
1368 dk_ioc
.dki_length
= EFI_MIN_ARRAY_SIZE
+ vtoc
->efi_lbasize
;
1370 dk_ioc
.dki_length
= NBLOCKS(vtoc
->efi_nparts
,
1371 vtoc
->efi_lbasize
) *
1376 * the number of blocks occupied by GUID partition entry array
1378 nblocks
= dk_ioc
.dki_length
/ vtoc
->efi_lbasize
- 1;
1381 * Backup GPT header is located on the block after GUID
1382 * partition entry array. Here, we calculate the address
1383 * for backup GPT header.
1385 lba_backup_gpt_hdr
= vtoc
->efi_last_u_lba
+ 1 + nblocks
;
1386 if (posix_memalign((void **)&dk_ioc
.dki_data
,
1387 vtoc
->efi_lbasize
, dk_ioc
.dki_length
))
1390 memset(dk_ioc
.dki_data
, 0, dk_ioc
.dki_length
);
1391 efi
= dk_ioc
.dki_data
;
1393 /* stuff user's input into EFI struct */
1394 efi
->efi_gpt_Signature
= LE_64(EFI_SIGNATURE
);
1395 efi
->efi_gpt_Revision
= LE_32(vtoc
->efi_version
); /* 0x02000100 */
1396 efi
->efi_gpt_HeaderSize
= LE_32(sizeof (struct efi_gpt
) - LEN_EFI_PAD
);
1397 efi
->efi_gpt_Reserved1
= 0;
1398 efi
->efi_gpt_MyLBA
= LE_64(1ULL);
1399 efi
->efi_gpt_AlternateLBA
= LE_64(lba_backup_gpt_hdr
);
1400 efi
->efi_gpt_FirstUsableLBA
= LE_64(vtoc
->efi_first_u_lba
);
1401 efi
->efi_gpt_LastUsableLBA
= LE_64(vtoc
->efi_last_u_lba
);
1402 efi
->efi_gpt_PartitionEntryLBA
= LE_64(2ULL);
1403 efi
->efi_gpt_NumberOfPartitionEntries
= LE_32(vtoc
->efi_nparts
);
1404 efi
->efi_gpt_SizeOfPartitionEntry
= LE_32(sizeof (struct efi_gpe
));
1405 UUID_LE_CONVERT(efi
->efi_gpt_DiskGUID
, vtoc
->efi_disk_uguid
);
1407 /* LINTED -- always longlong aligned */
1408 efi_parts
= (efi_gpe_t
*)((char *)dk_ioc
.dki_data
+ vtoc
->efi_lbasize
);
1410 for (i
= 0; i
< vtoc
->efi_nparts
; i
++) {
1412 j
< sizeof (conversion_array
) /
1413 sizeof (struct uuid_to_ptag
); j
++) {
1415 if (vtoc
->efi_parts
[i
].p_tag
== j
) {
1417 efi_parts
[i
].efi_gpe_PartitionTypeGUID
,
1418 conversion_array
[j
].uuid
);
1423 if (j
== sizeof (conversion_array
) /
1424 sizeof (struct uuid_to_ptag
)) {
1426 * If we didn't have a matching uuid match, bail here.
1427 * Don't write a label with unknown uuid.
1430 (void) fprintf(stderr
,
1431 "Unknown uuid for p_tag %d\n",
1432 vtoc
->efi_parts
[i
].p_tag
);
1437 /* Zero's should be written for empty partitions */
1438 if (vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
)
1441 efi_parts
[i
].efi_gpe_StartingLBA
=
1442 LE_64(vtoc
->efi_parts
[i
].p_start
);
1443 efi_parts
[i
].efi_gpe_EndingLBA
=
1444 LE_64(vtoc
->efi_parts
[i
].p_start
+
1445 vtoc
->efi_parts
[i
].p_size
- 1);
1446 efi_parts
[i
].efi_gpe_Attributes
.PartitionAttrs
=
1447 LE_16(vtoc
->efi_parts
[i
].p_flag
);
1448 for (j
= 0; j
< EFI_PART_NAME_LEN
; j
++) {
1449 efi_parts
[i
].efi_gpe_PartitionName
[j
] =
1450 LE_16((ushort_t
)vtoc
->efi_parts
[i
].p_name
[j
]);
1452 if ((vtoc
->efi_parts
[i
].p_tag
!= V_UNASSIGNED
) &&
1453 uuid_is_null((uchar_t
*)&vtoc
->efi_parts
[i
].p_uguid
)) {
1454 (void) uuid_generate((uchar_t
*)
1455 &vtoc
->efi_parts
[i
].p_uguid
);
1457 memcpy(&efi_parts
[i
].efi_gpe_UniquePartitionGUID
,
1458 &vtoc
->efi_parts
[i
].p_uguid
,
1461 efi
->efi_gpt_PartitionEntryArrayCRC32
=
1462 LE_32(efi_crc32((unsigned char *)efi_parts
,
1463 vtoc
->efi_nparts
* (int)sizeof (struct efi_gpe
)));
1464 efi
->efi_gpt_HeaderCRC32
=
1465 LE_32(efi_crc32((unsigned char *)efi
,
1466 LE_32(efi
->efi_gpt_HeaderSize
)));
1468 if (efi_ioctl(fd
, DKIOCSETEFI
, &dk_ioc
) == -1) {
1469 free(dk_ioc
.dki_data
);
1479 /* if it's a metadevice we're done */
1481 free(dk_ioc
.dki_data
);
1485 /* write backup partition array */
1486 dk_ioc
.dki_lba
= vtoc
->efi_last_u_lba
+ 1;
1487 dk_ioc
.dki_length
-= vtoc
->efi_lbasize
;
1489 dk_ioc
.dki_data
= (efi_gpt_t
*)((char *)dk_ioc
.dki_data
+
1492 if (efi_ioctl(fd
, DKIOCSETEFI
, &dk_ioc
) == -1) {
1494 * we wrote the primary label okay, so don't fail
1497 (void) fprintf(stderr
,
1498 "write of backup partitions to block %llu "
1499 "failed, errno %d\n",
1500 vtoc
->efi_last_u_lba
+ 1,
1505 * now swap MyLBA and AlternateLBA fields and write backup
1506 * partition table header
1508 dk_ioc
.dki_lba
= lba_backup_gpt_hdr
;
1509 dk_ioc
.dki_length
= vtoc
->efi_lbasize
;
1511 dk_ioc
.dki_data
= (efi_gpt_t
*)((char *)dk_ioc
.dki_data
-
1513 efi
->efi_gpt_AlternateLBA
= LE_64(1ULL);
1514 efi
->efi_gpt_MyLBA
= LE_64(lba_backup_gpt_hdr
);
1515 efi
->efi_gpt_PartitionEntryLBA
= LE_64(vtoc
->efi_last_u_lba
+ 1);
1516 efi
->efi_gpt_HeaderCRC32
= 0;
1517 efi
->efi_gpt_HeaderCRC32
=
1518 LE_32(efi_crc32((unsigned char *)dk_ioc
.dki_data
,
1519 LE_32(efi
->efi_gpt_HeaderSize
)));
1521 if (efi_ioctl(fd
, DKIOCSETEFI
, &dk_ioc
) == -1) {
1523 (void) fprintf(stderr
,
1524 "write of backup header to block %llu failed, "
1530 /* write the PMBR */
1531 (void) write_pmbr(fd
, vtoc
);
1532 free(dk_ioc
.dki_data
);
1538 efi_free(struct dk_gpt
*ptr
)
1544 efi_err_check(struct dk_gpt
*vtoc
)
1548 diskaddr_t istart
, jstart
, isize
, jsize
, endsect
;
1552 * make sure no partitions overlap
1554 for (i
= 0; i
< vtoc
->efi_nparts
; i
++) {
1555 /* It can't be unassigned and have an actual size */
1556 if ((vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
) &&
1557 (vtoc
->efi_parts
[i
].p_size
!= 0)) {
1558 (void) fprintf(stderr
,
1559 "partition %d is \"unassigned\" but has a size "
1560 "of %llu\n", i
, vtoc
->efi_parts
[i
].p_size
);
1562 if (vtoc
->efi_parts
[i
].p_tag
== V_UNASSIGNED
) {
1565 if (vtoc
->efi_parts
[i
].p_tag
== V_RESERVED
) {
1566 if (resv_part
!= -1) {
1567 (void) fprintf(stderr
,
1568 "found duplicate reserved partition at "
1572 if (vtoc
->efi_parts
[i
].p_size
!= EFI_MIN_RESV_SIZE
)
1573 (void) fprintf(stderr
,
1574 "Warning: reserved partition size must "
1575 "be %d sectors\n", EFI_MIN_RESV_SIZE
);
1577 if ((vtoc
->efi_parts
[i
].p_start
< vtoc
->efi_first_u_lba
) ||
1578 (vtoc
->efi_parts
[i
].p_start
> vtoc
->efi_last_u_lba
)) {
1579 (void) fprintf(stderr
,
1580 "Partition %d starts at %llu\n",
1582 vtoc
->efi_parts
[i
].p_start
);
1583 (void) fprintf(stderr
,
1584 "It must be between %llu and %llu.\n",
1585 vtoc
->efi_first_u_lba
,
1586 vtoc
->efi_last_u_lba
);
1588 if ((vtoc
->efi_parts
[i
].p_start
+
1589 vtoc
->efi_parts
[i
].p_size
<
1590 vtoc
->efi_first_u_lba
) ||
1591 (vtoc
->efi_parts
[i
].p_start
+
1592 vtoc
->efi_parts
[i
].p_size
>
1593 vtoc
->efi_last_u_lba
+ 1)) {
1594 (void) fprintf(stderr
,
1595 "Partition %d ends at %llu\n",
1597 vtoc
->efi_parts
[i
].p_start
+
1598 vtoc
->efi_parts
[i
].p_size
);
1599 (void) fprintf(stderr
,
1600 "It must be between %llu and %llu.\n",
1601 vtoc
->efi_first_u_lba
,
1602 vtoc
->efi_last_u_lba
);
1605 for (j
= 0; j
< vtoc
->efi_nparts
; j
++) {
1606 isize
= vtoc
->efi_parts
[i
].p_size
;
1607 jsize
= vtoc
->efi_parts
[j
].p_size
;
1608 istart
= vtoc
->efi_parts
[i
].p_start
;
1609 jstart
= vtoc
->efi_parts
[j
].p_start
;
1610 if ((i
!= j
) && (isize
!= 0) && (jsize
!= 0)) {
1611 endsect
= jstart
+ jsize
-1;
1612 if ((jstart
<= istart
) &&
1613 (istart
<= endsect
)) {
1615 (void) fprintf(stderr
,
1616 "label error: EFI Labels do not "
1617 "support overlapping partitions\n");
1619 (void) fprintf(stderr
,
1620 "Partition %d overlaps partition "
1627 /* make sure there is a reserved partition */
1628 if (resv_part
== -1) {
1629 (void) fprintf(stderr
,
1630 "no reserved partition found\n");