#if defined(_SUNOS_VTOC_16)
-#if defined(i386) || defined(__amd64)
+#if defined(i386) || defined(__amd64) || defined(__arm) || defined(__powerpc)
{ V_BOOT, V_UNMNT }, /* i - 8 */
{ V_ALTSCTR, 0 }, /* j - 9 */
rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9]p%hu",
dki_info->dki_dname,
&dki_info->dki_partition);
+ } else if ((strncmp(dev_path, "/dev/vd", 7) == 0)) {
+ strcpy(dki_info->dki_cname, "vd");
+ dki_info->dki_ctype = DKC_MD;
+ rval = sscanf(dev_path, "/dev/%[a-zA-Z]%hu",
+ dki_info->dki_dname,
+ &dki_info->dki_partition);
} else if ((strncmp(dev_path, "/dev/dm-", 8) == 0)) {
strcpy(dki_info->dki_cname, "pseudo");
dki_info->dki_ctype = DKC_VBD;
return (error);
}
-#if defined(__linux__)
-static int
-efi_rescan(int fd)
+int efi_rescan(int fd)
{
+#if defined(__linux__)
int retry = 5;
int error;
return (-1);
}
}
+#endif
return (0);
}
-#endif
static int
check_label(int fd, dk_efi_t *dk_ioc)
*/
crc = efi->efi_gpt_HeaderCRC32;
efi->efi_gpt_HeaderCRC32 = 0;
+ len_t headerSize = (len_t)LE_32(efi->efi_gpt_HeaderSize);
- if (((len_t)LE_32(efi->efi_gpt_HeaderSize) > dk_ioc->dki_length) ||
- crc != LE_32(efi_crc32((unsigned char *)efi,
- LE_32(efi->efi_gpt_HeaderSize)))) {
+ if(headerSize < EFI_MIN_LABEL_SIZE || headerSize > EFI_LABEL_SIZE) {
+ if (efi_debug)
+ (void) fprintf(stderr,
+ "Invalid EFI HeaderSize %llu. Assuming %d.\n",
+ headerSize, EFI_MIN_LABEL_SIZE);
+ }
+
+ if ((headerSize > dk_ioc->dki_length) ||
+ crc != LE_32(efi_crc32((unsigned char *)efi, headerSize))) {
if (efi_debug)
(void) fprintf(stderr,
"Bad EFI CRC: 0x%x != 0x%x\n",
- crc,
- LE_32(efi_crc32((unsigned char *)efi,
- sizeof (struct efi_gpt))));
+ crc, LE_32(efi_crc32((unsigned char *)efi,
+ headerSize)));
return (VT_EINVAL);
}
struct dk_gpt *efi_label;
int rval;
int i;
- uint_t phy_last_slice = 0;
- diskaddr_t pl_start = 0;
- diskaddr_t pl_size;
+ uint_t resv_index = 0, data_index = 0;
+ diskaddr_t resv_start = 0, data_start = 0;
+ diskaddr_t difference;
rval = efi_alloc_and_read(fd, &efi_label);
if (rval < 0) {
return (rval);
}
- /* find the last physically non-zero partition */
- for (i = 0; i < efi_label->efi_nparts - 2; i ++) {
- if (pl_start < efi_label->efi_parts[i].p_start) {
- pl_start = efi_label->efi_parts[i].p_start;
- phy_last_slice = i;
- }
- }
- pl_size = efi_label->efi_parts[phy_last_slice].p_size;
-
/*
* If alter_lba is 1, we are using the backup label.
* Since we can locate the backup label by disk capacity,
return (VT_ENOSPC);
}
+ difference = efi_label->efi_last_lba - efi_label->efi_altern_lba;
+
/*
- * If there is space between the last physically non-zero partition
- * and the reserved partition, just add the unallocated space to this
- * area. Otherwise, the unallocated space is added to the last
- * physically non-zero partition.
+ * Find the last physically non-zero partition.
+ * This is the reserved partition.
*/
- if (pl_start + pl_size - 1 == efi_label->efi_last_u_lba -
- EFI_MIN_RESV_SIZE) {
- efi_label->efi_parts[phy_last_slice].p_size +=
- efi_label->efi_last_lba - efi_label->efi_altern_lba;
+ for (i = 0; i < efi_label->efi_nparts; i ++) {
+ if (resv_start < efi_label->efi_parts[i].p_start) {
+ resv_start = efi_label->efi_parts[i].p_start;
+ resv_index = i;
+ }
+ }
+
+ /*
+ * Find the last physically non-zero partition before that.
+ * This is the data partition.
+ */
+ for (i = 0; i < resv_index; i ++) {
+ if (data_start < efi_label->efi_parts[i].p_start) {
+ data_start = efi_label->efi_parts[i].p_start;
+ data_index = i;
+ }
}
/*
* here except fabricated devids (which get generated via
* efi_write()). So there is no need to copy data.
*/
- efi_label->efi_parts[efi_label->efi_nparts - 1].p_start +=
- efi_label->efi_last_lba - efi_label->efi_altern_lba;
- efi_label->efi_last_u_lba += efi_label->efi_last_lba
- - efi_label->efi_altern_lba;
+ efi_label->efi_parts[data_index].p_size += difference;
+ efi_label->efi_parts[resv_index].p_start += difference;
+ efi_label->efi_last_u_lba += difference;
rval = efi_write(fd, efi_label);
if (rval < 0) {
/* stuff user's input into EFI struct */
efi->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
efi->efi_gpt_Revision = LE_32(vtoc->efi_version); /* 0x02000100 */
- efi->efi_gpt_HeaderSize = LE_32(sizeof (struct efi_gpt));
+ efi->efi_gpt_HeaderSize = LE_32(sizeof (struct efi_gpt) - LEN_EFI_PAD);
efi->efi_gpt_Reserved1 = 0;
efi->efi_gpt_MyLBA = LE_64(1ULL);
efi->efi_gpt_AlternateLBA = LE_64(lba_backup_gpt_hdr);
LE_32(efi_crc32((unsigned char *)efi_parts,
vtoc->efi_nparts * (int)sizeof (struct efi_gpe)));
efi->efi_gpt_HeaderCRC32 =
- LE_32(efi_crc32((unsigned char *)efi, sizeof (struct efi_gpt)));
+ LE_32(efi_crc32((unsigned char *)efi,
+ LE_32(efi->efi_gpt_HeaderSize)));
if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
free(dk_ioc.dki_data);
efi->efi_gpt_HeaderCRC32 = 0;
efi->efi_gpt_HeaderCRC32 =
LE_32(efi_crc32((unsigned char *)dk_ioc.dki_data,
- sizeof (struct efi_gpt)));
+ LE_32(efi->efi_gpt_HeaderSize)));
if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
if (efi_debug) {
(void) write_pmbr(fd, vtoc);
free(dk_ioc.dki_data);
-#if defined(__linux__)
- rval = efi_rescan(fd);
- if (rval)
- return (VT_ERROR);
-#endif
-
return (0);
}