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