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