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