summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2019-03-15 17:34:12 +0000
committerJohn Levon <john.levon@joyent.com>2019-04-23 09:49:06 -0700
commitfd7977362aae2eaa5dcb89671159f4fd82f22ca1 (patch)
tree2d4c3b3c8e0480c575ccf91e3054d637d207d7ca
parent995a963f85d39c82ddd55378042f53b3a58c2519 (diff)
downloadillumos-joyent-fd7977362aae2eaa5dcb89671159f4fd82f22ca1.tar.gz
10570 Need workaround to EFI boot on AMI BIOS
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Andy Stormont <astormont@racktopsystems.com> Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r--usr/src/lib/libefi/common/rdwr_efi.c26
-rw-r--r--usr/src/uts/common/fs/zfs/zvol.c5
-rw-r--r--usr/src/uts/common/io/cmlb.c3
-rw-r--r--usr/src/uts/common/sys/efi_partition.h14
-rw-r--r--usr/src/uts/sun4v/io/vds.c5
5 files changed, 33 insertions, 20 deletions
diff --git a/usr/src/lib/libefi/common/rdwr_efi.c b/usr/src/lib/libefi/common/rdwr_efi.c
index e0d866e3c4..0e87baeca3 100644
--- a/usr/src/lib/libefi/common/rdwr_efi.c
+++ b/usr/src/lib/libefi/common/rdwr_efi.c
@@ -24,7 +24,7 @@
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright 2014 Toomas Soome <tsoome@me.com>
* Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
- * Copyright (c) 2018, Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
*/
#include <stdio.h>
@@ -341,9 +341,8 @@ check_label(int fd, dk_efi_t *dk_ioc)
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,
+ LE_32(efi->efi_gpt_HeaderSize))));
return (VT_EINVAL);
}
@@ -715,7 +714,7 @@ write_pmbr(int fd, struct dk_gpt *vtoc)
hardware_workarounds(&slot, &active);
len = (vtoc->efi_lbasize == 0) ? sizeof (mb) : vtoc->efi_lbasize;
- buf = calloc(len, 1);
+ buf = calloc(1, len);
/*
* Preserve any boot code and disk signature if the first block is
@@ -741,10 +740,10 @@ write_pmbr(int fd, struct dk_gpt *vtoc)
cp = (uchar_t *)&mb.parts[slot * sizeof (struct ipart)];
/* bootable or not */
*cp++ = active ? ACTIVE : NOTACTIVE;
- /* beginning CHS; 0xffffff if not representable */
- *cp++ = 0xff;
- *cp++ = 0xff;
- *cp++ = 0xff;
+ /* beginning CHS; same as starting LBA (but one-based) */
+ *cp++ = 0x0;
+ *cp++ = 0x2;
+ *cp++ = 0x0;
/* OS type */
*cp++ = EFI_PMBR;
/* ending CHS; 0xffffff if not representable */
@@ -1029,7 +1028,7 @@ efi_write(int fd, struct dk_gpt *vtoc)
/* 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(EFI_HEADER_SIZE);
efi->efi_gpt_Reserved1 = 0;
efi->efi_gpt_MyLBA = LE_64(1ULL);
efi->efi_gpt_AlternateLBA = LE_64(lba_backup_gpt_hdr);
@@ -1094,8 +1093,8 @@ efi_write(int fd, struct dk_gpt *vtoc)
efi->efi_gpt_PartitionEntryArrayCRC32 =
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)));
+ efi->efi_gpt_HeaderCRC32 = LE_32(efi_crc32((unsigned char *)efi,
+ EFI_HEADER_SIZE));
if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
free(dk_ioc.dki_data);
@@ -1142,8 +1141,7 @@ efi_write(int fd, struct dk_gpt *vtoc)
efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1);
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_crc32((unsigned char *)dk_ioc.dki_data, EFI_HEADER_SIZE));
if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
if (efi_debug) {
diff --git a/usr/src/uts/common/fs/zfs/zvol.c b/usr/src/uts/common/fs/zfs/zvol.c
index 3566984ab4..10ea804f8d 100644
--- a/usr/src/uts/common/fs/zfs/zvol.c
+++ b/usr/src/uts/common/fs/zfs/zvol.c
@@ -27,6 +27,7 @@
* Copyright (c) 2012, 2017 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
+ * Copyright (c) 2019, Joyent, Inc.
*/
/*
@@ -1509,7 +1510,7 @@ zvol_getefi(void *arg, int flag, uint64_t vs, uint8_t bs)
gpt.efi_gpt_Signature = LE_64(EFI_SIGNATURE);
gpt.efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
- gpt.efi_gpt_HeaderSize = LE_32(sizeof (gpt));
+ gpt.efi_gpt_HeaderSize = LE_32(EFI_HEADER_SIZE);
gpt.efi_gpt_MyLBA = LE_64(1ULL);
gpt.efi_gpt_FirstUsableLBA = LE_64(34ULL);
gpt.efi_gpt_LastUsableLBA = LE_64((vs >> bs) - 1);
@@ -1519,7 +1520,7 @@ zvol_getefi(void *arg, int flag, uint64_t vs, uint8_t bs)
LE_32(sizeof (efi_gpe_t));
CRC32(crc, &gpe, sizeof (gpe), -1U, crc32_table);
gpt.efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc);
- CRC32(crc, &gpt, sizeof (gpt), -1U, crc32_table);
+ CRC32(crc, &gpt, EFI_HEADER_SIZE, -1U, crc32_table);
gpt.efi_gpt_HeaderCRC32 = LE_32(~crc);
if (ddi_copyout(&gpt, ptr, MIN(sizeof (gpt), length),
flag))
diff --git a/usr/src/uts/common/io/cmlb.c b/usr/src/uts/common/io/cmlb.c
index 49e4e1a39d..6275948465 100644
--- a/usr/src/uts/common/io/cmlb.c
+++ b/usr/src/uts/common/io/cmlb.c
@@ -24,6 +24,7 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2016 Toomas Soome <tsoome@me.com>
+ * Copyright (c) 2019, Joyent, Inc.
*/
/*
@@ -2747,7 +2748,7 @@ cmlb_validate_efi(efi_gpt_t *labp)
{
if (labp->efi_gpt_Signature != EFI_SIGNATURE)
return (EINVAL);
- /* at least 96 bytes in this version of the spec. */
+ /* at least 92 bytes in this version of the spec. */
if (sizeof (efi_gpt_t) - sizeof (labp->efi_gpt_Reserved2) >
labp->efi_gpt_HeaderSize)
return (EINVAL);
diff --git a/usr/src/uts/common/sys/efi_partition.h b/usr/src/uts/common/sys/efi_partition.h
index 5fa101cbb7..065f65f802 100644
--- a/usr/src/uts/common/sys/efi_partition.h
+++ b/usr/src/uts/common/sys/efi_partition.h
@@ -22,12 +22,14 @@
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright 2014 Toomas Soome <tsoome@me.com>
+ * Copyright (c) 2019, Joyent, Inc.
*/
#ifndef _SYS_EFI_PARTITION_H
#define _SYS_EFI_PARTITION_H
#include <sys/uuid.h>
+#include <sys/stddef.h>
#ifdef __cplusplus
extern "C" {
@@ -46,6 +48,16 @@ extern "C" {
#define EFI_SIGNATURE 0x5452415020494645ULL
+/*
+ * Although the EFI spec is clear that sizeof (efi_gpt_t) is a valid value
+ * (512), at least one EFI system (AMI v4.6.4.1) incorrectly expects this to be
+ * exactly the size of the structure defined in the spec, that is, 92.
+ *
+ * As the reserved section is never used, the modified value works fine
+ * everywhere else.
+ */
+#define EFI_HEADER_SIZE (offsetof(efi_gpt_t, efi_gpt_Reserved2))
+
/* EFI Guid Partition Table Header -- little endian on-disk format */
typedef struct efi_gpt {
uint64_t efi_gpt_Signature;
@@ -222,7 +234,7 @@ typedef struct dk_efi {
diskaddr_t dki_lba; /* starting block */
len_t dki_length; /* length in bytes */
union {
- efi_gpt_t *_dki_data;
+ efi_gpt_t *_dki_data;
uint64_t _dki_data_64;
} dki_un;
#define dki_data dki_un._dki_data
diff --git a/usr/src/uts/sun4v/io/vds.c b/usr/src/uts/sun4v/io/vds.c
index dee390142b..15d263a1b9 100644
--- a/usr/src/uts/sun4v/io/vds.c
+++ b/usr/src/uts/sun4v/io/vds.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Joyent, Inc.
*/
/*
@@ -5832,7 +5833,7 @@ vd_setup_partition_efi(vd_t *vd)
gpt->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
gpt->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
- gpt->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t));
+ gpt->efi_gpt_HeaderSize = LE_32(EFI_HEADER_SIZE);
gpt->efi_gpt_FirstUsableLBA = LE_64(first_u_lba);
gpt->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
gpt->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t));
@@ -5869,7 +5870,7 @@ vd_setup_partition_efi(vd_t *vd)
CRC32(crc, gpe, sizeof (efi_gpe_t) * VD_MAXPART, -1U, crc32_table);
gpt->efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc);
- CRC32(crc, gpt, sizeof (efi_gpt_t), -1U, crc32_table);
+ CRC32(crc, gpt, EFI_HEADER_SIZE, -1U, crc32_table);
gpt->efi_gpt_HeaderCRC32 = LE_32(~crc);
return (0);