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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 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 (cachefs) is never used */ 59 { EFI_RESERVED }, 60 { EFI_SYSTEM }, 61 { EFI_LEGACY_MBR }, 62 { EFI_RESV3 }, 63 { EFI_RESV4 }, 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 }; 71 72 /* 73 * Default vtoc information for non-SVr4 partitions 74 */ 75 struct dk_map2 default_vtoc_map[NDKMAP] = { 76 { V_ROOT, 0 }, /* a - 0 */ 77 { V_SWAP, V_UNMNT }, /* b - 1 */ 78 { V_BACKUP, V_UNMNT }, /* c - 2 */ 79 { V_UNASSIGNED, 0 }, /* d - 3 */ 80 { V_UNASSIGNED, 0 }, /* e - 4 */ 81 { V_UNASSIGNED, 0 }, /* f - 5 */ 82 { V_USR, 0 }, /* g - 6 */ 83 { V_UNASSIGNED, 0 }, /* h - 7 */ 84 85 #if defined(_SUNOS_VTOC_16) 86 87 #if defined(i386) || defined(__amd64) 88 { V_BOOT, V_UNMNT }, /* i - 8 */ 89 { V_ALTSCTR, 0 }, /* j - 9 */ 90 91 #else 92 #error No VTOC format defined. 93 #endif /* defined(i386) */ 94 95 { V_UNASSIGNED, 0 }, /* k - 10 */ 96 { V_UNASSIGNED, 0 }, /* l - 11 */ 97 { V_UNASSIGNED, 0 }, /* m - 12 */ 98 { V_UNASSIGNED, 0 }, /* n - 13 */ 99 { V_UNASSIGNED, 0 }, /* o - 14 */ 100 { V_UNASSIGNED, 0 }, /* p - 15 */ 101 #endif /* defined(_SUNOS_VTOC_16) */ 102 }; 103 104 /* 105 * This is the size of the reserved partition. 106 * Valid in case of EFI labels. 107 */ 108 #define EFI_MIN_RESV_SIZE (16 * 1024) 109 110 #ifdef DEBUG 111 int efi_debug = 1; 112 #else 113 int efi_debug = 0; 114 #endif 115 116 extern unsigned int efi_crc32(const unsigned char *, unsigned int); 117 static int efi_read(int, struct dk_gpt *); 118 119 static int 120 read_disk_info(int fd, diskaddr_t *capacity, uint_t *lbsize) 121 { 122 struct dk_minfo disk_info; 123 124 if ((ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info)) == -1) 125 return (errno); 126 *capacity = disk_info.dki_capacity; 127 *lbsize = disk_info.dki_lbsize; 128 return (0); 129 } 130 131 /* 132 * the number of blocks the EFI label takes up (round up to nearest 133 * block) 134 */ 135 #define NBLOCKS(p, l) (1 + ((((p) * (int)sizeof (efi_gpe_t)) + \ 136 ((l) - 1)) / (l))) 137 /* number of partitions -- limited by what we can malloc */ 138 #define MAX_PARTS ((4294967295UL - sizeof (struct dk_gpt)) / \ 139 sizeof (struct dk_part)) 140 141 int 142 efi_alloc_and_init(int fd, uint32_t nparts, struct dk_gpt **vtoc) 143 { 144 diskaddr_t capacity; 145 uint_t lbsize; 146 uint_t nblocks; 147 size_t length; 148 struct dk_gpt *vptr; 149 struct uuid uuid; 150 151 if (read_disk_info(fd, &capacity, &lbsize) != 0) { 152 if (efi_debug) 153 (void) fprintf(stderr, 154 "couldn't read disk information\n"); 155 return (-1); 156 } 157 158 nblocks = NBLOCKS(nparts, lbsize); 159 if ((nblocks * lbsize) < EFI_MIN_ARRAY_SIZE + lbsize) { 160 /* 16K plus one block for the GPT */ 161 nblocks = EFI_MIN_ARRAY_SIZE / lbsize + 1; 162 } 163 164 if (nparts > MAX_PARTS) { 165 if (efi_debug) { 166 (void) fprintf(stderr, 167 "the maximum number of partitions supported is %lu\n", 168 MAX_PARTS); 169 } 170 return (-1); 171 } 172 173 length = sizeof (struct dk_gpt) + 174 sizeof (struct dk_part) * (nparts - 1); 175 176 if ((*vtoc = calloc(length, 1)) == NULL) 177 return (-1); 178 179 vptr = *vtoc; 180 181 vptr->efi_version = EFI_VERSION_CURRENT; 182 vptr->efi_lbasize = lbsize; 183 vptr->efi_nparts = nparts; 184 /* 185 * add one block here for the PMBR; on disks with a 512 byte 186 * block size and 128 or fewer partitions, efi_first_u_lba 187 * should work out to "34" 188 */ 189 vptr->efi_first_u_lba = nblocks + 1; 190 vptr->efi_last_lba = capacity - 1; 191 vptr->efi_last_u_lba = vptr->efi_last_lba - nblocks; 192 (void) uuid_generate((uchar_t *)&uuid); 193 UUID_LE_CONVERT(vptr->efi_disk_uguid, uuid); 194 return (0); 195 } 196 197 /* 198 * Read EFI - return partition number upon success. 199 */ 200 int 201 efi_alloc_and_read(int fd, struct dk_gpt **vtoc) 202 { 203 int rval; 204 uint32_t nparts; 205 int length; 206 207 /* figure out the number of entries that would fit into 16K */ 208 nparts = EFI_MIN_ARRAY_SIZE / sizeof (efi_gpe_t); 209 length = (int) sizeof (struct dk_gpt) + 210 (int) sizeof (struct dk_part) * (nparts - 1); 211 if ((*vtoc = calloc(length, 1)) == NULL) 212 return (VT_ERROR); 213 214 (*vtoc)->efi_nparts = nparts; 215 rval = efi_read(fd, *vtoc); 216 217 if ((rval == VT_EINVAL) && (*vtoc)->efi_nparts > nparts) { 218 void *tmp; 219 length = (int) sizeof (struct dk_gpt) + 220 (int) sizeof (struct dk_part) * 221 ((*vtoc)->efi_nparts - 1); 222 nparts = (*vtoc)->efi_nparts; 223 if ((tmp = realloc(*vtoc, length)) == NULL) { 224 free (*vtoc); 225 *vtoc = NULL; 226 return (VT_ERROR); 227 } else { 228 *vtoc = tmp; 229 rval = efi_read(fd, *vtoc); 230 } 231 } 232 233 if (rval < 0) { 234 if (efi_debug) { 235 (void) fprintf(stderr, 236 "read of EFI table failed, rval=%d\n", rval); 237 } 238 free (*vtoc); 239 *vtoc = NULL; 240 } 241 242 return (rval); 243 } 244 245 static int 246 efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc) 247 { 248 void *data = dk_ioc->dki_data; 249 int error; 250 251 dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data; 252 error = ioctl(fd, cmd, (void *)dk_ioc); 253 dk_ioc->dki_data = data; 254 255 return (error); 256 } 257 258 static int 259 check_label(int fd, dk_efi_t *dk_ioc) 260 { 261 efi_gpt_t *efi; 262 uint_t crc; 263 264 if (efi_ioctl(fd, DKIOCGETEFI, dk_ioc) == -1) { 265 switch (errno) { 266 case EIO: 267 return (VT_EIO); 268 default: 269 return (VT_ERROR); 270 } 271 } 272 efi = dk_ioc->dki_data; 273 if (efi->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) { 274 if (efi_debug) 275 (void) fprintf(stderr, 276 "Bad EFI signature: 0x%llx != 0x%llx\n", 277 (long long)efi->efi_gpt_Signature, 278 (long long)LE_64(EFI_SIGNATURE)); 279 return (VT_EINVAL); 280 } 281 282 /* 283 * check CRC of the header; the size of the header should 284 * never be larger than one block 285 */ 286 crc = efi->efi_gpt_HeaderCRC32; 287 efi->efi_gpt_HeaderCRC32 = 0; 288 289 if (((len_t)LE_32(efi->efi_gpt_HeaderSize) > dk_ioc->dki_length) || 290 crc != LE_32(efi_crc32((unsigned char *)efi, 291 LE_32(efi->efi_gpt_HeaderSize)))) { 292 if (efi_debug) 293 (void) fprintf(stderr, 294 "Bad EFI CRC: 0x%x != 0x%x\n", 295 crc, 296 LE_32(efi_crc32((unsigned char *)efi, 297 sizeof (struct efi_gpt)))); 298 return (VT_EINVAL); 299 } 300 301 return (0); 302 } 303 304 static int 305 efi_read(int fd, struct dk_gpt *vtoc) 306 { 307 int i, j; 308 int label_len; 309 int rval = 0; 310 int md_flag = 0; 311 struct dk_minfo disk_info; 312 dk_efi_t dk_ioc; 313 efi_gpt_t *efi; 314 efi_gpe_t *efi_parts; 315 struct dk_cinfo dki_info; 316 uint32_t user_length; 317 318 /* 319 * get the partition number for this file descriptor. 320 */ 321 if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) { 322 if (efi_debug) 323 (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno); 324 switch (errno) { 325 case EIO: 326 return (VT_EIO); 327 case EINVAL: 328 return (VT_EINVAL); 329 default: 330 return (VT_ERROR); 331 } 332 } 333 if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) && 334 (strncmp(dki_info.dki_dname, "md", 3) == 0)) { 335 md_flag++; 336 } 337 /* get the LBA size */ 338 if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) { 339 if (efi_debug) { 340 (void) fprintf(stderr, 341 "assuming LBA 512 bytes %d\n", 342 errno); 343 } 344 disk_info.dki_lbsize = DEV_BSIZE; 345 } 346 if (disk_info.dki_lbsize == 0) { 347 if (efi_debug) { 348 (void) fprintf(stderr, 349 "efi_read: assuming LBA 512 bytes\n"); 350 } 351 disk_info.dki_lbsize = DEV_BSIZE; 352 } 353 /* 354 * Read the EFI GPT to figure out how many partitions we need 355 * to deal with. 356 */ 357 dk_ioc.dki_lba = 1; 358 if (NBLOCKS(vtoc->efi_nparts, disk_info.dki_lbsize) < 34) { 359 label_len = EFI_MIN_ARRAY_SIZE + disk_info.dki_lbsize; 360 } else { 361 label_len = vtoc->efi_nparts * (int) sizeof (efi_gpe_t) + 362 disk_info.dki_lbsize; 363 if (label_len % disk_info.dki_lbsize) { 364 /* pad to physical sector size */ 365 label_len += disk_info.dki_lbsize; 366 label_len &= ~(disk_info.dki_lbsize - 1); 367 } 368 } 369 370 if ((dk_ioc.dki_data = calloc(label_len, 1)) == NULL) 371 return (VT_ERROR); 372 373 dk_ioc.dki_length = label_len; 374 user_length = vtoc->efi_nparts; 375 efi = dk_ioc.dki_data; 376 if (md_flag) { 377 if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) { 378 switch (errno) { 379 case EIO: 380 return (VT_EIO); 381 default: 382 return (VT_ERROR); 383 } 384 } 385 } else if ((rval = check_label(fd, &dk_ioc)) == VT_EINVAL) { 386 /* no valid label here; try the alternate */ 387 dk_ioc.dki_lba = disk_info.dki_capacity - 1; 388 dk_ioc.dki_length = disk_info.dki_lbsize; 389 rval = check_label(fd, &dk_ioc); 390 if (rval != 0) { 391 /* 392 * Refer to bug6342431. This is a workaround for 393 * legacy. 394 * 395 * In the past, the last sector of SCSI disk was 396 * invisible on x86 platform. At that time, backup 397 * label was saved on the next to the last sector. 398 * It is possible for users to move a disk from 399 * previous solaris system to present system. 400 */ 401 dk_ioc.dki_lba = disk_info.dki_capacity - 2; 402 dk_ioc.dki_length = disk_info.dki_lbsize; 403 rval = check_label(fd, &dk_ioc); 404 if (efi_debug && (rval == 0)) { 405 (void) fprintf(stderr, 406 "efi_read: primary label corrupt; " 407 "using legacy EFI backup label\n"); 408 } 409 } 410 411 if (rval == 0) { 412 if (efi_debug) { 413 (void) fprintf(stderr, 414 "efi_read: primary label corrupt; " 415 "using backup\n"); 416 } 417 dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA); 418 vtoc->efi_flags |= EFI_GPT_PRIMARY_CORRUPT; 419 vtoc->efi_nparts = 420 LE_32(efi->efi_gpt_NumberOfPartitionEntries); 421 /* 422 * partitions are between last usable LBA and 423 * backup partition header 424 */ 425 dk_ioc.dki_data++; 426 dk_ioc.dki_length = disk_info.dki_capacity - 427 dk_ioc.dki_lba - 1; 428 dk_ioc.dki_length *= disk_info.dki_lbsize; 429 if (dk_ioc.dki_length > (len_t)label_len) { 430 rval = VT_EINVAL; 431 } else { 432 rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc); 433 } 434 } 435 } 436 if (rval < 0) { 437 free(efi); 438 return (rval); 439 } 440 441 /* partitions start in the next block */ 442 /* LINTED -- always longlong aligned */ 443 efi_parts = (efi_gpe_t *)(((char *)efi) + disk_info.dki_lbsize); 444 445 /* 446 * Assemble this into a "dk_gpt" struct for easier 447 * digestibility by applications. 448 */ 449 vtoc->efi_version = LE_32(efi->efi_gpt_Revision); 450 vtoc->efi_nparts = LE_32(efi->efi_gpt_NumberOfPartitionEntries); 451 vtoc->efi_part_size = LE_32(efi->efi_gpt_SizeOfPartitionEntry); 452 vtoc->efi_lbasize = disk_info.dki_lbsize; 453 vtoc->efi_last_lba = disk_info.dki_capacity - 1; 454 vtoc->efi_first_u_lba = LE_64(efi->efi_gpt_FirstUsableLBA); 455 vtoc->efi_last_u_lba = LE_64(efi->efi_gpt_LastUsableLBA); 456 UUID_LE_CONVERT(vtoc->efi_disk_uguid, efi->efi_gpt_DiskGUID); 457 458 /* 459 * If the array the user passed in is too small, set the length 460 * to what it needs to be and return 461 */ 462 if (user_length < vtoc->efi_nparts) { 463 return (VT_EINVAL); 464 } 465 466 for (i = 0; i < vtoc->efi_nparts; i++) { 467 468 UUID_LE_CONVERT(vtoc->efi_parts[i].p_guid, 469 efi_parts[i].efi_gpe_PartitionTypeGUID); 470 471 for (j = 0; 472 j < sizeof (conversion_array) / sizeof (struct uuid_to_ptag); 473 j++) { 474 475 if (bcmp(&vtoc->efi_parts[i].p_guid, 476 &conversion_array[j].uuid, 477 sizeof (struct uuid)) == 0) { 478 vtoc->efi_parts[i].p_tag = j; 479 break; 480 } 481 } 482 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) 483 continue; 484 vtoc->efi_parts[i].p_flag = 485 LE_16(efi_parts[i].efi_gpe_Attributes.PartitionAttrs); 486 vtoc->efi_parts[i].p_start = 487 LE_64(efi_parts[i].efi_gpe_StartingLBA); 488 vtoc->efi_parts[i].p_size = 489 LE_64(efi_parts[i].efi_gpe_EndingLBA) - 490 vtoc->efi_parts[i].p_start + 1; 491 for (j = 0; j < EFI_PART_NAME_LEN; j++) { 492 vtoc->efi_parts[i].p_name[j] = 493 (uchar_t)LE_16(efi_parts[i].efi_gpe_PartitionName[j]); 494 } 495 496 UUID_LE_CONVERT(vtoc->efi_parts[i].p_uguid, 497 efi_parts[i].efi_gpe_UniquePartitionGUID); 498 } 499 free(efi); 500 501 return (dki_info.dki_partition); 502 } 503 504 /* writes a "protective" MBR */ 505 static int 506 write_pmbr(int fd, struct dk_gpt *vtoc) 507 { 508 dk_efi_t dk_ioc; 509 struct mboot mb; 510 uchar_t *cp; 511 diskaddr_t size_in_lba; 512 513 mb.signature = LE_16(MBB_MAGIC); 514 bzero(&mb.parts, sizeof (mb.parts)); 515 cp = (uchar_t *)&mb.parts[0]; 516 /* bootable or not */ 517 *cp++ = 0; 518 /* beginning CHS; 0xffffff if not representable */ 519 *cp++ = 0xff; 520 *cp++ = 0xff; 521 *cp++ = 0xff; 522 /* OS type */ 523 *cp++ = EFI_PMBR; 524 /* ending CHS; 0xffffff if not representable */ 525 *cp++ = 0xff; 526 *cp++ = 0xff; 527 *cp++ = 0xff; 528 /* starting LBA: 1 (little endian format) by EFI definition */ 529 *cp++ = 0x01; 530 *cp++ = 0x00; 531 *cp++ = 0x00; 532 *cp++ = 0x00; 533 /* ending LBA: last block on the disk (little endian format) */ 534 size_in_lba = vtoc->efi_last_lba; 535 if (size_in_lba < 0xffffffff) { 536 *cp++ = (size_in_lba & 0x000000ff); 537 *cp++ = (size_in_lba & 0x0000ff00) >> 8; 538 *cp++ = (size_in_lba & 0x00ff0000) >> 16; 539 *cp++ = (size_in_lba & 0xff000000) >> 24; 540 } else { 541 *cp++ = 0xff; 542 *cp++ = 0xff; 543 *cp++ = 0xff; 544 *cp++ = 0xff; 545 } 546 /* LINTED -- always longlong aligned */ 547 dk_ioc.dki_data = (efi_gpt_t *)&mb; 548 dk_ioc.dki_lba = 0; 549 dk_ioc.dki_length = sizeof (mb); 550 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 551 switch (errno) { 552 case EIO: 553 return (VT_EIO); 554 case EINVAL: 555 return (VT_EINVAL); 556 default: 557 return (VT_ERROR); 558 } 559 } 560 return (0); 561 } 562 563 /* make sure the user specified something reasonable */ 564 static int 565 check_input(struct dk_gpt *vtoc) 566 { 567 int resv_part = -1; 568 int i, j; 569 diskaddr_t istart, jstart, isize, jsize, endsect; 570 571 /* 572 * Sanity-check the input (make sure no partitions overlap) 573 */ 574 for (i = 0; i < vtoc->efi_nparts; i++) { 575 /* It can't be unassigned and have an actual size */ 576 if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) && 577 (vtoc->efi_parts[i].p_size != 0)) { 578 if (efi_debug) { 579 (void) fprintf(stderr, 580 "partition %d is \"unassigned\" but has a size of %llu", 581 i, 582 vtoc->efi_parts[i].p_size); 583 } 584 return (VT_EINVAL); 585 } 586 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) { 587 continue; 588 } 589 if (vtoc->efi_parts[i].p_tag == V_RESERVED) { 590 if (resv_part != -1) { 591 if (efi_debug) { 592 (void) fprintf(stderr, 593 "found duplicate reserved partition at %d\n", 594 i); 595 } 596 return (VT_EINVAL); 597 } 598 resv_part = i; 599 } 600 if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) || 601 (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) { 602 if (efi_debug) { 603 (void) fprintf(stderr, 604 "Partition %d starts at %llu. ", 605 i, 606 vtoc->efi_parts[i].p_start); 607 (void) fprintf(stderr, 608 "It must be between %llu and %llu.\n", 609 vtoc->efi_first_u_lba, 610 vtoc->efi_last_u_lba); 611 } 612 return (VT_EINVAL); 613 } 614 if ((vtoc->efi_parts[i].p_start + 615 vtoc->efi_parts[i].p_size < 616 vtoc->efi_first_u_lba) || 617 (vtoc->efi_parts[i].p_start + 618 vtoc->efi_parts[i].p_size > 619 vtoc->efi_last_u_lba + 1)) { 620 if (efi_debug) { 621 (void) fprintf(stderr, 622 "Partition %d ends at %llu. ", 623 i, 624 vtoc->efi_parts[i].p_start + 625 vtoc->efi_parts[i].p_size); 626 (void) fprintf(stderr, 627 "It must be between %llu and %llu.\n", 628 vtoc->efi_first_u_lba, 629 vtoc->efi_last_u_lba); 630 } 631 return (VT_EINVAL); 632 } 633 634 for (j = 0; j < vtoc->efi_nparts; j++) { 635 isize = vtoc->efi_parts[i].p_size; 636 jsize = vtoc->efi_parts[j].p_size; 637 istart = vtoc->efi_parts[i].p_start; 638 jstart = vtoc->efi_parts[j].p_start; 639 if ((i != j) && (isize != 0) && (jsize != 0)) { 640 endsect = jstart + jsize -1; 641 if ((jstart <= istart) && 642 (istart <= endsect)) { 643 if (efi_debug) { 644 (void) fprintf(stderr, 645 "Partition %d overlaps partition %d.", 646 i, j); 647 } 648 return (VT_EINVAL); 649 } 650 } 651 } 652 } 653 /* just a warning for now */ 654 if ((resv_part == -1) && efi_debug) { 655 (void) fprintf(stderr, 656 "no reserved partition found\n"); 657 } 658 return (0); 659 } 660 661 /* 662 * write EFI label and backup label 663 */ 664 int 665 efi_write(int fd, struct dk_gpt *vtoc) 666 { 667 dk_efi_t dk_ioc; 668 efi_gpt_t *efi; 669 efi_gpe_t *efi_parts; 670 int i, j; 671 struct dk_cinfo dki_info; 672 int md_flag = 0; 673 674 if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) { 675 if (efi_debug) 676 (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno); 677 switch (errno) { 678 case EIO: 679 return (VT_EIO); 680 case EINVAL: 681 return (VT_EINVAL); 682 default: 683 return (VT_ERROR); 684 } 685 } 686 687 /* check if we are dealing wih a metadevice */ 688 if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) && 689 (strncmp(dki_info.dki_dname, "md", 3) == 0)) { 690 md_flag = 1; 691 } 692 693 if (check_input(vtoc)) { 694 /* 695 * not valid; if it's a metadevice just pass it down 696 * because SVM will do its own checking 697 */ 698 if (md_flag == 0) { 699 return (VT_EINVAL); 700 } 701 } 702 703 dk_ioc.dki_lba = 1; 704 if (NBLOCKS(vtoc->efi_nparts, vtoc->efi_lbasize) < 34) { 705 dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + vtoc->efi_lbasize; 706 } else { 707 dk_ioc.dki_length = NBLOCKS(vtoc->efi_nparts, 708 vtoc->efi_lbasize) * 709 vtoc->efi_lbasize; 710 } 711 712 if ((dk_ioc.dki_data = calloc(dk_ioc.dki_length, 1)) == NULL) 713 return (VT_ERROR); 714 715 efi = dk_ioc.dki_data; 716 717 /* stuff user's input into EFI struct */ 718 efi->efi_gpt_Signature = LE_64(EFI_SIGNATURE); 719 efi->efi_gpt_Revision = LE_32(vtoc->efi_version); /* 0x02000100 */ 720 efi->efi_gpt_HeaderSize = LE_32(sizeof (struct efi_gpt)); 721 efi->efi_gpt_Reserved1 = 0; 722 efi->efi_gpt_MyLBA = LE_64(1ULL); 723 efi->efi_gpt_AlternateLBA = LE_64(vtoc->efi_last_lba); 724 efi->efi_gpt_FirstUsableLBA = LE_64(vtoc->efi_first_u_lba); 725 efi->efi_gpt_LastUsableLBA = LE_64(vtoc->efi_last_u_lba); 726 efi->efi_gpt_PartitionEntryLBA = LE_64(2ULL); 727 efi->efi_gpt_NumberOfPartitionEntries = LE_32(vtoc->efi_nparts); 728 efi->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (struct efi_gpe)); 729 UUID_LE_CONVERT(efi->efi_gpt_DiskGUID, vtoc->efi_disk_uguid); 730 731 /* LINTED -- always longlong aligned */ 732 efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + sizeof (efi_gpt_t)); 733 734 for (i = 0; i < vtoc->efi_nparts; i++) { 735 for (j = 0; 736 j < sizeof (conversion_array) / sizeof (struct uuid_to_ptag); 737 j++) { 738 739 if (vtoc->efi_parts[i].p_tag == j) { 740 UUID_LE_CONVERT( 741 efi_parts[i].efi_gpe_PartitionTypeGUID, 742 conversion_array[j].uuid); 743 } 744 } 745 efi_parts[i].efi_gpe_StartingLBA = 746 LE_64(vtoc->efi_parts[i].p_start); 747 efi_parts[i].efi_gpe_EndingLBA = 748 LE_64(vtoc->efi_parts[i].p_start + 749 vtoc->efi_parts[i].p_size - 1); 750 efi_parts[i].efi_gpe_Attributes.PartitionAttrs = 751 LE_16(vtoc->efi_parts[i].p_flag); 752 for (j = 0; j < EFI_PART_NAME_LEN; j++) { 753 efi_parts[i].efi_gpe_PartitionName[j] = 754 LE_16((ushort_t)vtoc->efi_parts[i].p_name[j]); 755 } 756 if ((vtoc->efi_parts[i].p_tag != V_UNASSIGNED) && 757 uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_uguid)) { 758 (void) uuid_generate((uchar_t *) 759 &vtoc->efi_parts[i].p_uguid); 760 } 761 bcopy(&vtoc->efi_parts[i].p_uguid, 762 &efi_parts[i].efi_gpe_UniquePartitionGUID, 763 sizeof (uuid_t)); 764 } 765 efi->efi_gpt_PartitionEntryArrayCRC32 = 766 LE_32(efi_crc32((unsigned char *)efi_parts, 767 vtoc->efi_nparts * (int)sizeof (struct efi_gpe))); 768 efi->efi_gpt_HeaderCRC32 = 769 LE_32(efi_crc32((unsigned char *)efi, sizeof (struct efi_gpt))); 770 771 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 772 free(dk_ioc.dki_data); 773 switch (errno) { 774 case EIO: 775 return (VT_EIO); 776 case EINVAL: 777 return (VT_EINVAL); 778 default: 779 return (VT_ERROR); 780 } 781 } 782 /* if it's a metadevice we're done */ 783 if (md_flag) { 784 free(dk_ioc.dki_data); 785 return (0); 786 } 787 /* write backup partition array */ 788 dk_ioc.dki_lba = vtoc->efi_last_u_lba + 1; 789 dk_ioc.dki_length -= vtoc->efi_lbasize; 790 dk_ioc.dki_data++; 791 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 792 /* 793 * we wrote the primary label okay, so don't fail 794 */ 795 if (efi_debug) { 796 (void) fprintf(stderr, 797 "write of backup partitions to block %llu " 798 "failed, errno %d\n", 799 vtoc->efi_last_u_lba + 1, 800 errno); 801 } 802 } 803 /* 804 * now swap MyLBA and AlternateLBA fields and write backup 805 * partition table header 806 */ 807 dk_ioc.dki_lba = vtoc->efi_last_lba; 808 dk_ioc.dki_length = vtoc->efi_lbasize; 809 dk_ioc.dki_data--; 810 efi->efi_gpt_AlternateLBA = LE_64(1ULL); 811 efi->efi_gpt_MyLBA = LE_64(vtoc->efi_last_lba); 812 efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1); 813 efi->efi_gpt_HeaderCRC32 = 0; 814 efi->efi_gpt_HeaderCRC32 = 815 LE_32(efi_crc32((unsigned char *)dk_ioc.dki_data, 816 sizeof (struct efi_gpt))); 817 818 if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 819 if (efi_debug) { 820 (void) fprintf(stderr, 821 "write of backup header to block %llu failed, " 822 "errno %d\n", 823 vtoc->efi_last_lba, 824 errno); 825 } 826 } 827 /* write the PMBR */ 828 (void) write_pmbr(fd, vtoc); 829 if (ioctl(fd, MHIOCREREGISTERDEVID) == -1) { 830 if (efi_debug) { 831 (void) fprintf(stderr, 832 "MHIOCREREGISTERDEVID failed %d\n", 833 errno); 834 } 835 } 836 free(dk_ioc.dki_data); 837 return (0); 838 } 839 840 void 841 efi_free(struct dk_gpt *ptr) 842 { 843 free(ptr); 844 } 845 846 /* 847 * Input: File descriptor 848 * Output: 1 if disk is >1TB OR has an EFI label, 0 otherwise. 849 */ 850 int 851 efi_type(int fd) 852 { 853 struct vtoc vtoc; 854 855 if (ioctl(fd, DKIOCGVTOC, &vtoc) == -1) { 856 if (errno == ENOTSUP) { 857 return (1); 858 } 859 } 860 return (0); 861 } 862 863 void 864 efi_err_check(struct dk_gpt *vtoc) 865 { 866 int resv_part = -1; 867 int i, j; 868 diskaddr_t istart, jstart, isize, jsize, endsect; 869 int overlap = 0; 870 871 /* 872 * make sure no partitions overlap 873 */ 874 for (i = 0; i < vtoc->efi_nparts; i++) { 875 /* It can't be unassigned and have an actual size */ 876 if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) && 877 (vtoc->efi_parts[i].p_size != 0)) { 878 (void) fprintf(stderr, 879 "partition %d is \"unassigned\" but has a size " 880 "of %llu\n", i, vtoc->efi_parts[i].p_size); 881 } 882 if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) { 883 continue; 884 } 885 if (vtoc->efi_parts[i].p_tag == V_RESERVED) { 886 if (resv_part != -1) { 887 (void) fprintf(stderr, 888 "found duplicate reserved partition at " 889 "%d\n", i); 890 } 891 resv_part = i; 892 if (vtoc->efi_parts[i].p_size != EFI_MIN_RESV_SIZE) 893 (void) fprintf(stderr, 894 "Warning: reserved partition size must " 895 "be %d sectors\n", EFI_MIN_RESV_SIZE); 896 } 897 if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) || 898 (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) { 899 (void) fprintf(stderr, 900 "Partition %d starts at %llu\n", 901 i, 902 vtoc->efi_parts[i].p_start); 903 (void) fprintf(stderr, 904 "It must be between %llu and %llu.\n", 905 vtoc->efi_first_u_lba, 906 vtoc->efi_last_u_lba); 907 } 908 if ((vtoc->efi_parts[i].p_start + 909 vtoc->efi_parts[i].p_size < 910 vtoc->efi_first_u_lba) || 911 (vtoc->efi_parts[i].p_start + 912 vtoc->efi_parts[i].p_size > 913 vtoc->efi_last_u_lba + 1)) { 914 (void) fprintf(stderr, 915 "Partition %d ends at %llu\n", 916 i, 917 vtoc->efi_parts[i].p_start + 918 vtoc->efi_parts[i].p_size); 919 (void) fprintf(stderr, 920 "It must be between %llu and %llu.\n", 921 vtoc->efi_first_u_lba, 922 vtoc->efi_last_u_lba); 923 } 924 925 for (j = 0; j < vtoc->efi_nparts; j++) { 926 isize = vtoc->efi_parts[i].p_size; 927 jsize = vtoc->efi_parts[j].p_size; 928 istart = vtoc->efi_parts[i].p_start; 929 jstart = vtoc->efi_parts[j].p_start; 930 if ((i != j) && (isize != 0) && (jsize != 0)) { 931 endsect = jstart + jsize -1; 932 if ((jstart <= istart) && 933 (istart <= endsect)) { 934 if (!overlap) { 935 (void) fprintf(stderr, 936 "label error: EFI Labels do not " 937 "support overlapping partitions\n"); 938 } 939 (void) fprintf(stderr, 940 "Partition %d overlaps partition " 941 "%d.\n", i, j); 942 overlap = 1; 943 } 944 } 945 } 946 } 947 /* make sure there is a reserved partition */ 948 if (resv_part == -1) { 949 (void) fprintf(stderr, 950 "no reserved partition found\n"); 951 } 952 } 953 954 /* 955 * We need to get information necessary to construct a *new* efi 956 * label type 957 */ 958 int 959 efi_auto_sense(int fd, struct dk_gpt **vtoc) 960 { 961 962 int i; 963 964 /* 965 * Now build the default partition table 966 */ 967 if (efi_alloc_and_init(fd, EFI_NUMPAR, vtoc) != 0) { 968 if (efi_debug) { 969 (void) fprintf(stderr, "efi_alloc_and_init failed.\n"); 970 } 971 return (-1); 972 } 973 974 for (i = 0; i < min((*vtoc)->efi_nparts, V_NUMPAR); i++) { 975 (*vtoc)->efi_parts[i].p_tag = default_vtoc_map[i].p_tag; 976 (*vtoc)->efi_parts[i].p_flag = default_vtoc_map[i].p_flag; 977 (*vtoc)->efi_parts[i].p_start = 0; 978 (*vtoc)->efi_parts[i].p_size = 0; 979 } 980 /* 981 * Make constants first 982 * and variable partitions later 983 */ 984 985 /* root partition - s0 128 MB */ 986 (*vtoc)->efi_parts[0].p_start = 34; 987 (*vtoc)->efi_parts[0].p_size = 262144; 988 989 /* partition - s1 128 MB */ 990 (*vtoc)->efi_parts[1].p_start = 262178; 991 (*vtoc)->efi_parts[1].p_size = 262144; 992 993 /* partition -s2 is NOT the Backup disk */ 994 (*vtoc)->efi_parts[2].p_tag = V_UNASSIGNED; 995 996 /* partition -s6 /usr partition - HOG */ 997 (*vtoc)->efi_parts[6].p_start = 524322; 998 (*vtoc)->efi_parts[6].p_size = (*vtoc)->efi_last_u_lba - 524322 999 - (1024 * 16); 1000 1001 /* efi reserved partition - s9 16K */ 1002 (*vtoc)->efi_parts[8].p_start = (*vtoc)->efi_last_u_lba - (1024 * 16); 1003 (*vtoc)->efi_parts[8].p_size = (1024 * 16); 1004 (*vtoc)->efi_parts[8].p_tag = V_RESERVED; 1005 return (0); 1006 } 1007