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 /*
  23  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2014 Toomas Soome <tsoome@me.com>
  26  */
  27 
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <errno.h>
  31 #include <strings.h>
  32 #include <unistd.h>
  33 #include <uuid/uuid.h>
  34 #include <libintl.h>
  35 #include <sys/types.h>
  36 #include <sys/dkio.h>
  37 #include <sys/vtoc.h>
  38 #include <sys/mhd.h>
  39 #include <sys/param.h>
  40 #include <sys/dktp/fdisk.h>
  41 #include <sys/efi_partition.h>
  42 #include <sys/byteorder.h>
  43 #include <sys/ddi.h>
  44 
  45 static struct uuid_to_ptag {
  46         struct uuid     uuid;
  47 } conversion_array[] = {
  48         { EFI_UNUSED },
  49         { EFI_BOOT },
  50         { EFI_ROOT },
  51         { EFI_SWAP },
  52         { EFI_USR },
  53         { EFI_BACKUP },
  54         { 0 },                  /* STAND is never used */
  55         { EFI_VAR },
  56         { EFI_HOME },
  57         { EFI_ALTSCTR },
  58         { 0 },                  /* CACHE is never used */
  59         { EFI_RESERVED },
  60         { EFI_SYSTEM },
  61         { EFI_LEGACY_MBR },
  62         { EFI_SYMC_PUB },
  63         { EFI_SYMC_CDS },
  64         { EFI_MSFT_RESV },
  65         { EFI_DELL_BASIC },
  66         { EFI_DELL_RAID },
  67         { EFI_DELL_SWAP },
  68         { EFI_DELL_LVM },
  69         { EFI_DELL_RESV },
  70         { EFI_AAPL_HFS },
  71         { EFI_AAPL_UFS },
  72         { EFI_BIOS_BOOT },
  73         { EFI_FREEBSD_BOOT },
  74         { EFI_FREEBSD_SWAP },
  75         { EFI_FREEBSD_UFS },
  76         { EFI_FREEBSD_VINUM },
  77         { EFI_FREEBSD_ZFS }
  78 };
  79 
  80 /*
  81  * Default vtoc information for non-SVr4 partitions
  82  */
  83 struct dk_map2  default_vtoc_map[NDKMAP] = {
  84         {       V_ROOT,         0       },              /* a - 0 */
  85         {       V_SWAP,         V_UNMNT },              /* b - 1 */
  86         {       V_BACKUP,       V_UNMNT },              /* c - 2 */
  87         {       V_UNASSIGNED,   0       },              /* d - 3 */
  88         {       V_UNASSIGNED,   0       },              /* e - 4 */
  89         {       V_UNASSIGNED,   0       },              /* f - 5 */
  90         {       V_USR,          0       },              /* g - 6 */
  91         {       V_UNASSIGNED,   0       },              /* h - 7 */
  92 
  93 #if defined(_SUNOS_VTOC_16)
  94 
  95 #if defined(i386) || defined(__amd64)
  96         {       V_BOOT,         V_UNMNT },              /* i - 8 */
  97         {       V_ALTSCTR,      0       },              /* j - 9 */
  98 
  99 #else
 100 #error No VTOC format defined.
 101 #endif                  /* defined(i386) */
 102 
 103         {       V_UNASSIGNED,   0       },              /* k - 10 */
 104         {       V_UNASSIGNED,   0       },              /* l - 11 */
 105         {       V_UNASSIGNED,   0       },              /* m - 12 */
 106         {       V_UNASSIGNED,   0       },              /* n - 13 */
 107         {       V_UNASSIGNED,   0       },              /* o - 14 */
 108         {       V_UNASSIGNED,   0       },              /* p - 15 */
 109 #endif                  /* defined(_SUNOS_VTOC_16) */
 110 };
 111 
 112 #ifdef DEBUG
 113 int efi_debug = 1;
 114 #else
 115 int efi_debug = 0;
 116 #endif
 117 
 118 extern unsigned int     efi_crc32(const unsigned char *, unsigned int);
 119 static int              efi_read(int, struct dk_gpt *);
 120 
 121 static int
 122 read_disk_info(int fd, diskaddr_t *capacity, uint_t *lbsize)
 123 {
 124         struct dk_minfo         disk_info;
 125 
 126         if ((ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info)) == -1)
 127                 return (errno);
 128         *capacity = disk_info.dki_capacity;
 129         *lbsize = disk_info.dki_lbsize;
 130         return (0);
 131 }
 132 
 133 /*
 134  * the number of blocks the EFI label takes up (round up to nearest
 135  * block)
 136  */
 137 #define NBLOCKS(p, l)   (1 + ((((p) * (int)sizeof (efi_gpe_t))  + \
 138                                 ((l) - 1)) / (l)))
 139 /* number of partitions -- limited by what we can malloc */
 140 #define MAX_PARTS       ((4294967295UL - sizeof (struct dk_gpt)) / \
 141                             sizeof (struct dk_part))
 142 
 143 int
 144 efi_alloc_and_init(int fd, uint32_t nparts, struct dk_gpt **vtoc)
 145 {
 146         diskaddr_t      capacity;
 147         uint_t          lbsize;
 148         uint_t          nblocks;
 149         size_t          length;
 150         struct dk_gpt   *vptr;
 151         struct uuid     uuid;
 152 
 153         if (read_disk_info(fd, &capacity, &lbsize) != 0) {
 154                 if (efi_debug)
 155                         (void) fprintf(stderr,
 156                             "couldn't read disk information\n");
 157                 return (-1);
 158         }
 159 
 160         nblocks = NBLOCKS(nparts, lbsize);
 161         if ((nblocks * lbsize) < EFI_MIN_ARRAY_SIZE + lbsize) {
 162                 /* 16K plus one block for the GPT */
 163                 nblocks = EFI_MIN_ARRAY_SIZE / lbsize + 1;
 164         }
 165 
 166         if (nparts > MAX_PARTS) {
 167                 if (efi_debug) {
 168                         (void) fprintf(stderr,
 169                         "the maximum number of partitions supported is %lu\n",
 170                             MAX_PARTS);
 171                 }
 172                 return (-1);
 173         }
 174 
 175         length = sizeof (struct dk_gpt) +
 176             sizeof (struct dk_part) * (nparts - 1);
 177 
 178         if ((*vtoc = calloc(length, 1)) == NULL)
 179                 return (-1);
 180 
 181         vptr = *vtoc;
 182 
 183         vptr->efi_version = EFI_VERSION_CURRENT;
 184         vptr->efi_lbasize = lbsize;
 185         vptr->efi_nparts = nparts;
 186         /*
 187          * add one block here for the PMBR; on disks with a 512 byte
 188          * block size and 128 or fewer partitions, efi_first_u_lba
 189          * should work out to "34"
 190          */
 191         vptr->efi_first_u_lba = nblocks + 1;
 192         vptr->efi_last_lba = capacity - 1;
 193         vptr->efi_altern_lba = capacity -1;
 194         vptr->efi_last_u_lba = vptr->efi_last_lba - nblocks;
 195 
 196         (void) uuid_generate((uchar_t *)&uuid);
 197         UUID_LE_CONVERT(vptr->efi_disk_uguid, uuid);
 198         return (0);
 199 }
 200 
 201 /*
 202  * Read EFI - return partition number upon success.
 203  */
 204 int
 205 efi_alloc_and_read(int fd, struct dk_gpt **vtoc)
 206 {
 207         int                     rval;
 208         uint32_t                nparts;
 209         int                     length;
 210         struct mboot            *mbr;
 211         struct ipart            *ipart;
 212         diskaddr_t              capacity;
 213         uint_t                  lbsize;
 214         int                     i;
 215 
 216         if (read_disk_info(fd, &capacity, &lbsize) != 0)
 217                 return (VT_ERROR);
 218 
 219         if ((mbr = calloc(lbsize, 1)) == NULL)
 220                 return (VT_ERROR);
 221 
 222         if ((ioctl(fd, DKIOCGMBOOT, (caddr_t)mbr)) == -1) {
 223                 free(mbr);
 224                 return (VT_ERROR);
 225         }
 226 
 227         if (mbr->signature != MBB_MAGIC) {
 228                 free(mbr);
 229                 return (VT_EINVAL);
 230         }
 231         ipart = (struct ipart *)(uintptr_t)mbr->parts;
 232 
 233         /* Check if we have partition with ID EFI_PMBR */
 234         for (i = 0; i < FD_NUMPART; i++) {
 235                 if (ipart[i].systid == EFI_PMBR)
 236                         break;
 237         }
 238         free(mbr);
 239         if (i == FD_NUMPART)
 240                 return (VT_EINVAL);
 241 
 242         /* figure out the number of entries that would fit into 16K */
 243         nparts = EFI_MIN_ARRAY_SIZE / sizeof (efi_gpe_t);
 244         length = (int) sizeof (struct dk_gpt) +
 245             (int) sizeof (struct dk_part) * (nparts - 1);
 246         if ((*vtoc = calloc(length, 1)) == NULL)
 247                 return (VT_ERROR);
 248 
 249         (*vtoc)->efi_nparts = nparts;
 250         rval = efi_read(fd, *vtoc);
 251 
 252         if ((rval == VT_EINVAL) && (*vtoc)->efi_nparts > nparts) {
 253                 void *tmp;
 254                 length = (int) sizeof (struct dk_gpt) +
 255                     (int) sizeof (struct dk_part) *
 256                     ((*vtoc)->efi_nparts - 1);
 257                 nparts = (*vtoc)->efi_nparts;
 258                 if ((tmp = realloc(*vtoc, length)) == NULL) {
 259                         free (*vtoc);
 260                         *vtoc = NULL;
 261                         return (VT_ERROR);
 262                 } else {
 263                         *vtoc = tmp;
 264                         rval = efi_read(fd, *vtoc);
 265                 }
 266         }
 267 
 268         if (rval < 0) {
 269                 if (efi_debug) {
 270                         (void) fprintf(stderr,
 271                             "read of EFI table failed, rval=%d\n", rval);
 272                 }
 273                 free (*vtoc);
 274                 *vtoc = NULL;
 275         }
 276 
 277         return (rval);
 278 }
 279 
 280 static int
 281 efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
 282 {
 283         void *data = dk_ioc->dki_data;
 284         int error;
 285 
 286         dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data;
 287         error = ioctl(fd, cmd, (void *)dk_ioc);
 288         dk_ioc->dki_data = data;
 289 
 290         return (error);
 291 }
 292 
 293 static int
 294 check_label(int fd, dk_efi_t *dk_ioc)
 295 {
 296         efi_gpt_t               *efi;
 297         uint_t                  crc;
 298 
 299         if (efi_ioctl(fd, DKIOCGETEFI, dk_ioc) == -1) {
 300                 switch (errno) {
 301                 case EIO:
 302                         return (VT_EIO);
 303                 default:
 304                         return (VT_ERROR);
 305                 }
 306         }
 307         efi = dk_ioc->dki_data;
 308         if (efi->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) {
 309                 if (efi_debug)
 310                         (void) fprintf(stderr,
 311                             "Bad EFI signature: 0x%llx != 0x%llx\n",
 312                             (long long)efi->efi_gpt_Signature,
 313                             (long long)LE_64(EFI_SIGNATURE));
 314                 return (VT_EINVAL);
 315         }
 316 
 317         /*
 318          * check CRC of the header; the size of the header should
 319          * never be larger than one block
 320          */
 321         crc = efi->efi_gpt_HeaderCRC32;
 322         efi->efi_gpt_HeaderCRC32 = 0;
 323 
 324         if (((len_t)LE_32(efi->efi_gpt_HeaderSize) > dk_ioc->dki_length) ||
 325             crc != LE_32(efi_crc32((unsigned char *)efi,
 326             LE_32(efi->efi_gpt_HeaderSize)))) {
 327                 if (efi_debug)
 328                         (void) fprintf(stderr,
 329                             "Bad EFI CRC: 0x%x != 0x%x\n",
 330                             crc,
 331                             LE_32(efi_crc32((unsigned char *)efi,
 332                             sizeof (struct efi_gpt))));
 333                 return (VT_EINVAL);
 334         }
 335 
 336         return (0);
 337 }
 338 
 339 static int
 340 efi_read(int fd, struct dk_gpt *vtoc)
 341 {
 342         int                     i, j;
 343         int                     label_len;
 344         int                     rval = 0;
 345         int                     vdc_flag = 0;
 346         struct dk_minfo         disk_info;
 347         dk_efi_t                dk_ioc;
 348         efi_gpt_t               *efi;
 349         efi_gpe_t               *efi_parts;
 350         struct dk_cinfo         dki_info;
 351         uint32_t                user_length;
 352         boolean_t               legacy_label = B_FALSE;
 353 
 354         /*
 355          * get the partition number for this file descriptor.
 356          */
 357         if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
 358                 if (efi_debug) {
 359                         (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno);
 360                 }
 361                 switch (errno) {
 362                 case EIO:
 363                         return (VT_EIO);
 364                 case EINVAL:
 365                         return (VT_EINVAL);
 366                 default:
 367                         return (VT_ERROR);
 368                 }
 369         }
 370 
 371         if ((strncmp(dki_info.dki_cname, "vdc", 4) == 0) &&
 372             (strncmp(dki_info.dki_dname, "vdc", 4) == 0)) {
 373                 /*
 374                  * The controller and drive name "vdc" (virtual disk client)
 375                  * indicates a LDoms virtual disk.
 376                  */
 377                 vdc_flag++;
 378         }
 379 
 380         /* get the LBA size */
 381         if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
 382                 if (efi_debug) {
 383                         (void) fprintf(stderr,
 384                             "assuming LBA 512 bytes %d\n",
 385                             errno);
 386                 }
 387                 disk_info.dki_lbsize = DEV_BSIZE;
 388         }
 389         if (disk_info.dki_lbsize == 0) {
 390                 if (efi_debug) {
 391                         (void) fprintf(stderr,
 392                             "efi_read: assuming LBA 512 bytes\n");
 393                 }
 394                 disk_info.dki_lbsize = DEV_BSIZE;
 395         }
 396         /*
 397          * Read the EFI GPT to figure out how many partitions we need
 398          * to deal with.
 399          */
 400         dk_ioc.dki_lba = 1;
 401         if (NBLOCKS(vtoc->efi_nparts, disk_info.dki_lbsize) < 34) {
 402                 label_len = EFI_MIN_ARRAY_SIZE + disk_info.dki_lbsize;
 403         } else {
 404                 label_len = vtoc->efi_nparts * (int) sizeof (efi_gpe_t) +
 405                     disk_info.dki_lbsize;
 406                 if (label_len % disk_info.dki_lbsize) {
 407                         /* pad to physical sector size */
 408                         label_len += disk_info.dki_lbsize;
 409                         label_len &= ~(disk_info.dki_lbsize - 1);
 410                 }
 411         }
 412 
 413         if ((dk_ioc.dki_data = calloc(label_len, 1)) == NULL)
 414                 return (VT_ERROR);
 415 
 416         dk_ioc.dki_length = disk_info.dki_lbsize;
 417         user_length = vtoc->efi_nparts;
 418         efi = dk_ioc.dki_data;
 419         if ((rval = check_label(fd, &dk_ioc)) == VT_EINVAL) {
 420                 /*
 421                  * No valid label here; try the alternate. Note that here
 422                  * we just read GPT header and save it into dk_ioc.data,
 423                  * Later, we will read GUID partition entry array if we
 424                  * can get valid GPT header.
 425                  */
 426 
 427                 /*
 428                  * This is a workaround for legacy systems. In the past, the
 429                  * last sector of SCSI disk was invisible on x86 platform. At
 430                  * that time, backup label was saved on the next to the last
 431                  * sector. It is possible for users to move a disk from previous
 432                  * solaris system to present system. Here, we attempt to search
 433                  * legacy backup EFI label first.
 434                  */
 435                 dk_ioc.dki_lba = disk_info.dki_capacity - 2;
 436                 dk_ioc.dki_length = disk_info.dki_lbsize;
 437                 rval = check_label(fd, &dk_ioc);
 438                 if (rval == VT_EINVAL) {
 439                         /*
 440                          * we didn't find legacy backup EFI label, try to
 441                          * search backup EFI label in the last block.
 442                          */
 443                         dk_ioc.dki_lba = disk_info.dki_capacity - 1;
 444                         dk_ioc.dki_length = disk_info.dki_lbsize;
 445                         rval = check_label(fd, &dk_ioc);
 446                         if (rval == 0) {
 447                                 legacy_label = B_TRUE;
 448                                 if (efi_debug)
 449                                         (void) fprintf(stderr,
 450                                             "efi_read: primary label corrupt; "
 451                                             "using EFI backup label located on"
 452                                             " the last block\n");
 453                         }
 454                 } else {
 455                         if ((efi_debug) && (rval == 0))
 456                                 (void) fprintf(stderr, "efi_read: primary label"
 457                                     " corrupt; using legacy EFI backup label "
 458                                     " located on the next to last block\n");
 459                 }
 460 
 461                 if (rval == 0) {
 462                         dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA);
 463                         vtoc->efi_flags |= EFI_GPT_PRIMARY_CORRUPT;
 464                         vtoc->efi_nparts =
 465                             LE_32(efi->efi_gpt_NumberOfPartitionEntries);
 466                         /*
 467                          * Partition tables are between backup GPT header
 468                          * table and ParitionEntryLBA (the starting LBA of
 469                          * the GUID partition entries array). Now that we
 470                          * already got valid GPT header and saved it in
 471                          * dk_ioc.dki_data, we try to get GUID partition
 472                          * entry array here.
 473                          */
 474                         /* LINTED */
 475                         dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data
 476                             + disk_info.dki_lbsize);
 477                         if (legacy_label)
 478                                 dk_ioc.dki_length = disk_info.dki_capacity - 1 -
 479                                     dk_ioc.dki_lba;
 480                         else
 481                                 dk_ioc.dki_length = disk_info.dki_capacity - 2 -
 482                                     dk_ioc.dki_lba;
 483                         dk_ioc.dki_length *= disk_info.dki_lbsize;
 484                         if (dk_ioc.dki_length >
 485                             ((len_t)label_len - sizeof (*dk_ioc.dki_data))) {
 486                                 rval = VT_EINVAL;
 487                         } else {
 488                                 /*
 489                                  * read GUID partition entry array
 490                                  */
 491                                 rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc);
 492                         }
 493                 }
 494 
 495         } else if (rval == 0) {
 496 
 497                 dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA);
 498                 /* LINTED */
 499                 dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data
 500                     + disk_info.dki_lbsize);
 501                 dk_ioc.dki_length = label_len - disk_info.dki_lbsize;
 502                 rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc);
 503 
 504         } else if (vdc_flag && rval == VT_ERROR && errno == EINVAL) {
 505                 /*
 506                  * When the device is a LDoms virtual disk, the DKIOCGETEFI
 507                  * ioctl can fail with EINVAL if the virtual disk backend
 508                  * is a ZFS volume serviced by a domain running an old version
 509                  * of Solaris. This is because the DKIOCGETEFI ioctl was
 510                  * initially incorrectly implemented for a ZFS volume and it
 511                  * expected the GPT and GPE to be retrieved with a single ioctl.
 512                  * So we try to read the GPT and the GPE using that old style
 513                  * ioctl.
 514                  */
 515                 dk_ioc.dki_lba = 1;
 516                 dk_ioc.dki_length = label_len;
 517                 rval = check_label(fd, &dk_ioc);
 518         }
 519 
 520         if (rval < 0) {
 521                 free(efi);
 522                 return (rval);
 523         }
 524 
 525         /* LINTED -- always longlong aligned */
 526         efi_parts = (efi_gpe_t *)(((char *)efi) + disk_info.dki_lbsize);
 527 
 528         /*
 529          * Assemble this into a "dk_gpt" struct for easier
 530          * digestibility by applications.
 531          */
 532         vtoc->efi_version = LE_32(efi->efi_gpt_Revision);
 533         vtoc->efi_nparts = LE_32(efi->efi_gpt_NumberOfPartitionEntries);
 534         vtoc->efi_part_size = LE_32(efi->efi_gpt_SizeOfPartitionEntry);
 535         vtoc->efi_lbasize = disk_info.dki_lbsize;
 536         vtoc->efi_last_lba = disk_info.dki_capacity - 1;
 537         vtoc->efi_first_u_lba = LE_64(efi->efi_gpt_FirstUsableLBA);
 538         vtoc->efi_last_u_lba = LE_64(efi->efi_gpt_LastUsableLBA);
 539         vtoc->efi_altern_lba = LE_64(efi->efi_gpt_AlternateLBA);
 540         UUID_LE_CONVERT(vtoc->efi_disk_uguid, efi->efi_gpt_DiskGUID);
 541 
 542         /*
 543          * If the array the user passed in is too small, set the length
 544          * to what it needs to be and return
 545          */
 546         if (user_length < vtoc->efi_nparts) {
 547                 return (VT_EINVAL);
 548         }
 549 
 550         for (i = 0; i < vtoc->efi_nparts; i++) {
 551 
 552                 UUID_LE_CONVERT(vtoc->efi_parts[i].p_guid,
 553                     efi_parts[i].efi_gpe_PartitionTypeGUID);
 554 
 555                 for (j = 0;
 556                     j < sizeof (conversion_array)
 557                     / sizeof (struct uuid_to_ptag); j++) {
 558 
 559                         if (bcmp(&vtoc->efi_parts[i].p_guid,
 560                             &conversion_array[j].uuid,
 561                             sizeof (struct uuid)) == 0) {
 562                                 vtoc->efi_parts[i].p_tag = j;
 563                                 break;
 564                         }
 565                 }
 566                 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED)
 567                         continue;
 568                 vtoc->efi_parts[i].p_flag =
 569                     LE_16(efi_parts[i].efi_gpe_Attributes.PartitionAttrs);
 570                 vtoc->efi_parts[i].p_start =
 571                     LE_64(efi_parts[i].efi_gpe_StartingLBA);
 572                 vtoc->efi_parts[i].p_size =
 573                     LE_64(efi_parts[i].efi_gpe_EndingLBA) -
 574                     vtoc->efi_parts[i].p_start + 1;
 575                 for (j = 0; j < EFI_PART_NAME_LEN; j++) {
 576                         vtoc->efi_parts[i].p_name[j] =
 577                             (uchar_t)LE_16(
 578                             efi_parts[i].efi_gpe_PartitionName[j]);
 579                 }
 580 
 581                 UUID_LE_CONVERT(vtoc->efi_parts[i].p_uguid,
 582                     efi_parts[i].efi_gpe_UniquePartitionGUID);
 583         }
 584         free(efi);
 585 
 586         return (dki_info.dki_partition);
 587 }
 588 
 589 /* writes a "protective" MBR */
 590 static int
 591 write_pmbr(int fd, struct dk_gpt *vtoc)
 592 {
 593         dk_efi_t        dk_ioc;
 594         struct mboot    mb;
 595         uchar_t         *cp;
 596         diskaddr_t      size_in_lba;
 597         uchar_t         *buf;
 598         int             len;
 599 
 600         len = (vtoc->efi_lbasize == 0) ? sizeof (mb) : vtoc->efi_lbasize;
 601         buf = calloc(len, 1);
 602 
 603         /*
 604          * Preserve any boot code and disk signature if the first block is
 605          * already an MBR.
 606          */
 607         dk_ioc.dki_lba = 0;
 608         dk_ioc.dki_length = len;
 609         /* LINTED -- always longlong aligned */
 610         dk_ioc.dki_data = (efi_gpt_t *)buf;
 611         if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) {
 612                 (void) memcpy(&mb, buf, sizeof (mb));
 613                 bzero(&mb, sizeof (mb));
 614                 mb.signature = LE_16(MBB_MAGIC);
 615         } else {
 616                 (void) memcpy(&mb, buf, sizeof (mb));
 617                 if (mb.signature != LE_16(MBB_MAGIC)) {
 618                         bzero(&mb, sizeof (mb));
 619                         mb.signature = LE_16(MBB_MAGIC);
 620                 }
 621         }
 622 
 623         bzero(&mb.parts, sizeof (mb.parts));
 624         cp = (uchar_t *)&mb.parts[0];
 625         /* bootable or not */
 626         *cp++ = 0;
 627         /* beginning CHS; 0xffffff if not representable */
 628         *cp++ = 0xff;
 629         *cp++ = 0xff;
 630         *cp++ = 0xff;
 631         /* OS type */
 632         *cp++ = EFI_PMBR;
 633         /* ending CHS; 0xffffff if not representable */
 634         *cp++ = 0xff;
 635         *cp++ = 0xff;
 636         *cp++ = 0xff;
 637         /* starting LBA: 1 (little endian format) by EFI definition */
 638         *cp++ = 0x01;
 639         *cp++ = 0x00;
 640         *cp++ = 0x00;
 641         *cp++ = 0x00;
 642         /* ending LBA: last block on the disk (little endian format) */
 643         size_in_lba = vtoc->efi_last_lba;
 644         if (size_in_lba < 0xffffffff) {
 645                 *cp++ = (size_in_lba & 0x000000ff);
 646                 *cp++ = (size_in_lba & 0x0000ff00) >> 8;
 647                 *cp++ = (size_in_lba & 0x00ff0000) >> 16;
 648                 *cp++ = (size_in_lba & 0xff000000) >> 24;
 649         } else {
 650                 *cp++ = 0xff;
 651                 *cp++ = 0xff;
 652                 *cp++ = 0xff;
 653                 *cp++ = 0xff;
 654         }
 655 
 656         (void) memcpy(buf, &mb, sizeof (mb));
 657         /* LINTED -- always longlong aligned */
 658         dk_ioc.dki_data = (efi_gpt_t *)buf;
 659         dk_ioc.dki_lba = 0;
 660         dk_ioc.dki_length = len;
 661         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
 662                 free(buf);
 663                 switch (errno) {
 664                 case EIO:
 665                         return (VT_EIO);
 666                 case EINVAL:
 667                         return (VT_EINVAL);
 668                 default:
 669                         return (VT_ERROR);
 670                 }
 671         }
 672         free(buf);
 673         return (0);
 674 }
 675 
 676 /* make sure the user specified something reasonable */
 677 static int
 678 check_input(struct dk_gpt *vtoc)
 679 {
 680         int                     resv_part = -1;
 681         int                     i, j;
 682         diskaddr_t              istart, jstart, isize, jsize, endsect;
 683 
 684         /*
 685          * Sanity-check the input (make sure no partitions overlap)
 686          */
 687         for (i = 0; i < vtoc->efi_nparts; i++) {
 688                 /* It can't be unassigned and have an actual size */
 689                 if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) &&
 690                     (vtoc->efi_parts[i].p_size != 0)) {
 691                         if (efi_debug) {
 692                                 (void) fprintf(stderr,
 693 "partition %d is \"unassigned\" but has a size of %llu",
 694                                     i,
 695                                     vtoc->efi_parts[i].p_size);
 696                         }
 697                         return (VT_EINVAL);
 698                 }
 699                 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) {
 700                         if (uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_guid))
 701                                 continue;
 702                         /* we have encountered an unknown uuid */
 703                         vtoc->efi_parts[i].p_tag = 0xff;
 704                 }
 705                 if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
 706                         if (resv_part != -1) {
 707                                 if (efi_debug) {
 708                                         (void) fprintf(stderr,
 709 "found duplicate reserved partition at %d\n",
 710                                             i);
 711                                 }
 712                                 return (VT_EINVAL);
 713                         }
 714                         resv_part = i;
 715                 }
 716                 if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) ||
 717                     (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) {
 718                         if (efi_debug) {
 719                                 (void) fprintf(stderr,
 720                                     "Partition %d starts at %llu.  ",
 721                                     i,
 722                                     vtoc->efi_parts[i].p_start);
 723                                 (void) fprintf(stderr,
 724                                     "It must be between %llu and %llu.\n",
 725                                     vtoc->efi_first_u_lba,
 726                                     vtoc->efi_last_u_lba);
 727                         }
 728                         return (VT_EINVAL);
 729                 }
 730                 if ((vtoc->efi_parts[i].p_start +
 731                     vtoc->efi_parts[i].p_size <
 732                     vtoc->efi_first_u_lba) ||
 733                     (vtoc->efi_parts[i].p_start +
 734                     vtoc->efi_parts[i].p_size >
 735                     vtoc->efi_last_u_lba + 1)) {
 736                         if (efi_debug) {
 737                                 (void) fprintf(stderr,
 738                                     "Partition %d ends at %llu.  ",
 739                                     i,
 740                                     vtoc->efi_parts[i].p_start +
 741                                     vtoc->efi_parts[i].p_size);
 742                                 (void) fprintf(stderr,
 743                                     "It must be between %llu and %llu.\n",
 744                                     vtoc->efi_first_u_lba,
 745                                     vtoc->efi_last_u_lba);
 746                         }
 747                         return (VT_EINVAL);
 748                 }
 749 
 750                 for (j = 0; j < vtoc->efi_nparts; j++) {
 751                         isize = vtoc->efi_parts[i].p_size;
 752                         jsize = vtoc->efi_parts[j].p_size;
 753                         istart = vtoc->efi_parts[i].p_start;
 754                         jstart = vtoc->efi_parts[j].p_start;
 755                         if ((i != j) && (isize != 0) && (jsize != 0)) {
 756                                 endsect = jstart + jsize -1;
 757                                 if ((jstart <= istart) &&
 758                                     (istart <= endsect)) {
 759                                         if (efi_debug) {
 760                                                 (void) fprintf(stderr,
 761 "Partition %d overlaps partition %d.",
 762                                                     i, j);
 763                                         }
 764                                         return (VT_EINVAL);
 765                                 }
 766                         }
 767                 }
 768         }
 769         /* just a warning for now */
 770         if ((resv_part == -1) && efi_debug) {
 771                 (void) fprintf(stderr,
 772                     "no reserved partition found\n");
 773         }
 774         return (0);
 775 }
 776 
 777 /*
 778  * add all the unallocated space to the current label
 779  */
 780 int
 781 efi_use_whole_disk(int fd)
 782 {
 783         struct dk_gpt           *efi_label;
 784         int                     rval;
 785         int                     i;
 786         uint_t                  phy_last_slice = 0;
 787         diskaddr_t              pl_start = 0;
 788         diskaddr_t              pl_size;
 789 
 790         rval = efi_alloc_and_read(fd, &efi_label);
 791         if (rval < 0) {
 792                 return (rval);
 793         }
 794 
 795         /* find the last physically non-zero partition */
 796         for (i = 0; i < efi_label->efi_nparts - 2; i ++) {
 797                 if (pl_start < efi_label->efi_parts[i].p_start) {
 798                         pl_start = efi_label->efi_parts[i].p_start;
 799                         phy_last_slice = i;
 800                 }
 801         }
 802         pl_size = efi_label->efi_parts[phy_last_slice].p_size;
 803 
 804         /*
 805          * If alter_lba is 1, we are using the backup label.
 806          * Since we can locate the backup label by disk capacity,
 807          * there must be no unallocated space.
 808          */
 809         if ((efi_label->efi_altern_lba == 1) || (efi_label->efi_altern_lba
 810             >= efi_label->efi_last_lba)) {
 811                 if (efi_debug) {
 812                         (void) fprintf(stderr,
 813                             "efi_use_whole_disk: requested space not found\n");
 814                 }
 815                 efi_free(efi_label);
 816                 return (VT_ENOSPC);
 817         }
 818 
 819         /*
 820          * If there is space between the last physically non-zero partition
 821          * and the reserved partition, just add the unallocated space to this
 822          * area. Otherwise, the unallocated space is added to the last
 823          * physically non-zero partition.
 824          */
 825         if (pl_start + pl_size - 1 == efi_label->efi_last_u_lba -
 826             EFI_MIN_RESV_SIZE) {
 827                 efi_label->efi_parts[phy_last_slice].p_size +=
 828                     efi_label->efi_last_lba - efi_label->efi_altern_lba;
 829         }
 830 
 831         /*
 832          * Move the reserved partition. There is currently no data in
 833          * here except fabricated devids (which get generated via
 834          * efi_write()). So there is no need to copy data.
 835          */
 836         efi_label->efi_parts[efi_label->efi_nparts - 1].p_start +=
 837             efi_label->efi_last_lba - efi_label->efi_altern_lba;
 838         efi_label->efi_last_u_lba += efi_label->efi_last_lba
 839             - efi_label->efi_altern_lba;
 840 
 841         rval = efi_write(fd, efi_label);
 842         if (rval < 0) {
 843                 if (efi_debug) {
 844                         (void) fprintf(stderr,
 845                             "efi_use_whole_disk:fail to write label, rval=%d\n",
 846                             rval);
 847                 }
 848                 efi_free(efi_label);
 849                 return (rval);
 850         }
 851 
 852         efi_free(efi_label);
 853         return (0);
 854 }
 855 
 856 
 857 /*
 858  * write EFI label and backup label
 859  */
 860 int
 861 efi_write(int fd, struct dk_gpt *vtoc)
 862 {
 863         dk_efi_t                dk_ioc;
 864         efi_gpt_t               *efi;
 865         efi_gpe_t               *efi_parts;
 866         int                     i, j;
 867         struct dk_cinfo         dki_info;
 868         int                     nblocks;
 869         diskaddr_t              lba_backup_gpt_hdr;
 870 
 871         if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
 872                 if (efi_debug)
 873                         (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno);
 874                 switch (errno) {
 875                 case EIO:
 876                         return (VT_EIO);
 877                 case EINVAL:
 878                         return (VT_EINVAL);
 879                 default:
 880                         return (VT_ERROR);
 881                 }
 882         }
 883 
 884         if (check_input(vtoc))
 885                 return (VT_EINVAL);
 886 
 887         dk_ioc.dki_lba = 1;
 888         if (NBLOCKS(vtoc->efi_nparts, vtoc->efi_lbasize) < 34) {
 889                 dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + vtoc->efi_lbasize;
 890         } else {
 891                 dk_ioc.dki_length = NBLOCKS(vtoc->efi_nparts,
 892                     vtoc->efi_lbasize) *
 893                     vtoc->efi_lbasize;
 894         }
 895 
 896         /*
 897          * the number of blocks occupied by GUID partition entry array
 898          */
 899         nblocks = dk_ioc.dki_length / vtoc->efi_lbasize - 1;
 900 
 901         /*
 902          * Backup GPT header is located on the block after GUID
 903          * partition entry array. Here, we calculate the address
 904          * for backup GPT header.
 905          */
 906         lba_backup_gpt_hdr = vtoc->efi_last_u_lba + 1 + nblocks;
 907         if ((dk_ioc.dki_data = calloc(dk_ioc.dki_length, 1)) == NULL)
 908                 return (VT_ERROR);
 909 
 910         efi = dk_ioc.dki_data;
 911 
 912         /* stuff user's input into EFI struct */
 913         efi->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
 914         efi->efi_gpt_Revision = LE_32(vtoc->efi_version); /* 0x02000100 */
 915         efi->efi_gpt_HeaderSize = LE_32(sizeof (struct efi_gpt));
 916         efi->efi_gpt_Reserved1 = 0;
 917         efi->efi_gpt_MyLBA = LE_64(1ULL);
 918         efi->efi_gpt_AlternateLBA = LE_64(lba_backup_gpt_hdr);
 919         efi->efi_gpt_FirstUsableLBA = LE_64(vtoc->efi_first_u_lba);
 920         efi->efi_gpt_LastUsableLBA = LE_64(vtoc->efi_last_u_lba);
 921         efi->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
 922         efi->efi_gpt_NumberOfPartitionEntries = LE_32(vtoc->efi_nparts);
 923         efi->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (struct efi_gpe));
 924         UUID_LE_CONVERT(efi->efi_gpt_DiskGUID, vtoc->efi_disk_uguid);
 925 
 926         /* LINTED -- always longlong aligned */
 927         efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + vtoc->efi_lbasize);
 928 
 929         for (i = 0; i < vtoc->efi_nparts; i++) {
 930                 for (j = 0;
 931                     j < sizeof (conversion_array) /
 932                     sizeof (struct uuid_to_ptag); j++) {
 933 
 934                         if (vtoc->efi_parts[i].p_tag == j) {
 935                                 UUID_LE_CONVERT(
 936                                     efi_parts[i].efi_gpe_PartitionTypeGUID,
 937                                     conversion_array[j].uuid);
 938                                 break;
 939                         }
 940                 }
 941 
 942                 if (j == sizeof (conversion_array) /
 943                     sizeof (struct uuid_to_ptag)) {
 944                         /*
 945                          * If we didn't have a matching uuid match, bail here.
 946                          * Don't write a label with unknown uuid.
 947                          */
 948                         if (efi_debug) {
 949                                 (void) fprintf(stderr,
 950                                     "Unknown uuid for p_tag %d\n",
 951                                     vtoc->efi_parts[i].p_tag);
 952                         }
 953                         return (VT_EINVAL);
 954                 }
 955 
 956                 efi_parts[i].efi_gpe_StartingLBA =
 957                     LE_64(vtoc->efi_parts[i].p_start);
 958                 efi_parts[i].efi_gpe_EndingLBA =
 959                     LE_64(vtoc->efi_parts[i].p_start +
 960                     vtoc->efi_parts[i].p_size - 1);
 961                 efi_parts[i].efi_gpe_Attributes.PartitionAttrs =
 962                     LE_16(vtoc->efi_parts[i].p_flag);
 963                 for (j = 0; j < EFI_PART_NAME_LEN; j++) {
 964                         efi_parts[i].efi_gpe_PartitionName[j] =
 965                             LE_16((ushort_t)vtoc->efi_parts[i].p_name[j]);
 966                 }
 967                 if ((vtoc->efi_parts[i].p_tag != V_UNASSIGNED) &&
 968                     uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_uguid)) {
 969                         (void) uuid_generate((uchar_t *)
 970                             &vtoc->efi_parts[i].p_uguid);
 971                 }
 972                 bcopy(&vtoc->efi_parts[i].p_uguid,
 973                     &efi_parts[i].efi_gpe_UniquePartitionGUID,
 974                     sizeof (uuid_t));
 975         }
 976         efi->efi_gpt_PartitionEntryArrayCRC32 =
 977             LE_32(efi_crc32((unsigned char *)efi_parts,
 978             vtoc->efi_nparts * (int)sizeof (struct efi_gpe)));
 979         efi->efi_gpt_HeaderCRC32 =
 980             LE_32(efi_crc32((unsigned char *)efi, sizeof (struct efi_gpt)));
 981 
 982         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
 983                 free(dk_ioc.dki_data);
 984                 switch (errno) {
 985                 case EIO:
 986                         return (VT_EIO);
 987                 case EINVAL:
 988                         return (VT_EINVAL);
 989                 default:
 990                         return (VT_ERROR);
 991                 }
 992         }
 993 
 994         /* write backup partition array */
 995         dk_ioc.dki_lba = vtoc->efi_last_u_lba + 1;
 996         dk_ioc.dki_length -= vtoc->efi_lbasize;
 997         /* LINTED */
 998         dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data +
 999             vtoc->efi_lbasize);
1000 
1001         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1002                 /*
1003                  * we wrote the primary label okay, so don't fail
1004                  */
1005                 if (efi_debug) {
1006                         (void) fprintf(stderr,
1007                             "write of backup partitions to block %llu "
1008                             "failed, errno %d\n",
1009                             vtoc->efi_last_u_lba + 1,
1010                             errno);
1011                 }
1012         }
1013         /*
1014          * now swap MyLBA and AlternateLBA fields and write backup
1015          * partition table header
1016          */
1017         dk_ioc.dki_lba = lba_backup_gpt_hdr;
1018         dk_ioc.dki_length = vtoc->efi_lbasize;
1019         /* LINTED */
1020         dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data -
1021             vtoc->efi_lbasize);
1022         efi->efi_gpt_AlternateLBA = LE_64(1ULL);
1023         efi->efi_gpt_MyLBA = LE_64(lba_backup_gpt_hdr);
1024         efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1);
1025         efi->efi_gpt_HeaderCRC32 = 0;
1026         efi->efi_gpt_HeaderCRC32 =
1027             LE_32(efi_crc32((unsigned char *)dk_ioc.dki_data,
1028             sizeof (struct efi_gpt)));
1029 
1030         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1031                 if (efi_debug) {
1032                         (void) fprintf(stderr,
1033                             "write of backup header to block %llu failed, "
1034                             "errno %d\n",
1035                             lba_backup_gpt_hdr,
1036                             errno);
1037                 }
1038         }
1039         /* write the PMBR */
1040         (void) write_pmbr(fd, vtoc);
1041         free(dk_ioc.dki_data);
1042         return (0);
1043 }
1044 
1045 void
1046 efi_free(struct dk_gpt *ptr)
1047 {
1048         free(ptr);
1049 }
1050 
1051 /*
1052  * Input: File descriptor
1053  * Output: 1 if disk has an EFI label, or > 2TB with no VTOC or legacy MBR.
1054  * Otherwise 0.
1055  */
1056 int
1057 efi_type(int fd)
1058 {
1059         struct vtoc vtoc;
1060         struct extvtoc extvtoc;
1061 
1062         if (ioctl(fd, DKIOCGEXTVTOC, &extvtoc) == -1) {
1063                 if (errno == ENOTSUP)
1064                         return (1);
1065                 else if (errno == ENOTTY) {
1066                         if (ioctl(fd, DKIOCGVTOC, &vtoc) == -1)
1067                                 if (errno == ENOTSUP)
1068                                         return (1);
1069                 }
1070         }
1071         return (0);
1072 }
1073 
1074 void
1075 efi_err_check(struct dk_gpt *vtoc)
1076 {
1077         int                     resv_part = -1;
1078         int                     i, j;
1079         diskaddr_t              istart, jstart, isize, jsize, endsect;
1080         int                     overlap = 0;
1081 
1082         /*
1083          * make sure no partitions overlap
1084          */
1085         for (i = 0; i < vtoc->efi_nparts; i++) {
1086                 /* It can't be unassigned and have an actual size */
1087                 if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) &&
1088                     (vtoc->efi_parts[i].p_size != 0)) {
1089                         (void) fprintf(stderr,
1090                             "partition %d is \"unassigned\" but has a size "
1091                             "of %llu\n", i, vtoc->efi_parts[i].p_size);
1092                 }
1093                 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) {
1094                         continue;
1095                 }
1096                 if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
1097                         if (resv_part != -1) {
1098                                 (void) fprintf(stderr,
1099                                     "found duplicate reserved partition at "
1100                                     "%d\n", i);
1101                         }
1102                         resv_part = i;
1103                         if (vtoc->efi_parts[i].p_size != EFI_MIN_RESV_SIZE)
1104                                 (void) fprintf(stderr,
1105                                     "Warning: reserved partition size must "
1106                                     "be %d sectors\n", EFI_MIN_RESV_SIZE);
1107                 }
1108                 if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) ||
1109                     (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) {
1110                         (void) fprintf(stderr,
1111                             "Partition %d starts at %llu\n",
1112                             i,
1113                             vtoc->efi_parts[i].p_start);
1114                         (void) fprintf(stderr,
1115                             "It must be between %llu and %llu.\n",
1116                             vtoc->efi_first_u_lba,
1117                             vtoc->efi_last_u_lba);
1118                 }
1119                 if ((vtoc->efi_parts[i].p_start +
1120                     vtoc->efi_parts[i].p_size <
1121                     vtoc->efi_first_u_lba) ||
1122                     (vtoc->efi_parts[i].p_start +
1123                     vtoc->efi_parts[i].p_size >
1124                     vtoc->efi_last_u_lba + 1)) {
1125                         (void) fprintf(stderr,
1126                             "Partition %d ends at %llu\n",
1127                             i,
1128                             vtoc->efi_parts[i].p_start +
1129                             vtoc->efi_parts[i].p_size);
1130                         (void) fprintf(stderr,
1131                             "It must be between %llu and %llu.\n",
1132                             vtoc->efi_first_u_lba,
1133                             vtoc->efi_last_u_lba);
1134                 }
1135 
1136                 for (j = 0; j < vtoc->efi_nparts; j++) {
1137                         isize = vtoc->efi_parts[i].p_size;
1138                         jsize = vtoc->efi_parts[j].p_size;
1139                         istart = vtoc->efi_parts[i].p_start;
1140                         jstart = vtoc->efi_parts[j].p_start;
1141                         if ((i != j) && (isize != 0) && (jsize != 0)) {
1142                                 endsect = jstart + jsize -1;
1143                                 if ((jstart <= istart) &&
1144                                     (istart <= endsect)) {
1145                                         if (!overlap) {
1146                                         (void) fprintf(stderr,
1147                                             "label error: EFI Labels do not "
1148                                             "support overlapping partitions\n");
1149                                         }
1150                                         (void) fprintf(stderr,
1151                                             "Partition %d overlaps partition "
1152                                             "%d.\n", i, j);
1153                                         overlap = 1;
1154                                 }
1155                         }
1156                 }
1157         }
1158         /* make sure there is a reserved partition */
1159         if (resv_part == -1) {
1160                 (void) fprintf(stderr,
1161                     "no reserved partition found\n");
1162         }
1163 }
1164 
1165 /*
1166  * We need to get information necessary to construct a *new* efi
1167  * label type
1168  */
1169 int
1170 efi_auto_sense(int fd, struct dk_gpt **vtoc)
1171 {
1172 
1173         int     i;
1174 
1175         /*
1176          * Now build the default partition table
1177          */
1178         if (efi_alloc_and_init(fd, EFI_NUMPAR, vtoc) != 0) {
1179                 if (efi_debug) {
1180                         (void) fprintf(stderr, "efi_alloc_and_init failed.\n");
1181                 }
1182                 return (-1);
1183         }
1184 
1185         for (i = 0; i < min((*vtoc)->efi_nparts, V_NUMPAR); i++) {
1186                 (*vtoc)->efi_parts[i].p_tag = default_vtoc_map[i].p_tag;
1187                 (*vtoc)->efi_parts[i].p_flag = default_vtoc_map[i].p_flag;
1188                 (*vtoc)->efi_parts[i].p_start = 0;
1189                 (*vtoc)->efi_parts[i].p_size = 0;
1190         }
1191         /*
1192          * Make constants first
1193          * and variable partitions later
1194          */
1195 
1196         /* root partition - s0 128 MB */
1197         (*vtoc)->efi_parts[0].p_start = 34;
1198         (*vtoc)->efi_parts[0].p_size = 262144;
1199 
1200         /* partition - s1  128 MB */
1201         (*vtoc)->efi_parts[1].p_start = 262178;
1202         (*vtoc)->efi_parts[1].p_size = 262144;
1203 
1204         /* partition -s2 is NOT the Backup disk */
1205         (*vtoc)->efi_parts[2].p_tag = V_UNASSIGNED;
1206 
1207         /* partition -s6 /usr partition - HOG */
1208         (*vtoc)->efi_parts[6].p_start = 524322;
1209         (*vtoc)->efi_parts[6].p_size = (*vtoc)->efi_last_u_lba - 524322
1210             - (1024 * 16);
1211 
1212         /* efi reserved partition - s9 16K */
1213         (*vtoc)->efi_parts[8].p_start = (*vtoc)->efi_last_u_lba - (1024 * 16);
1214         (*vtoc)->efi_parts[8].p_size = (1024 * 16);
1215         (*vtoc)->efi_parts[8].p_tag = V_RESERVED;
1216         return (0);
1217 }