diff options
author | John Levon <john.levon@joyent.com> | 2019-03-15 17:34:12 +0000 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2019-04-23 09:49:06 -0700 |
commit | fd7977362aae2eaa5dcb89671159f4fd82f22ca1 (patch) | |
tree | 2d4c3b3c8e0480c575ccf91e3054d637d207d7ca | |
parent | 995a963f85d39c82ddd55378042f53b3a58c2519 (diff) | |
download | illumos-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.c | 26 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zvol.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/io/cmlb.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/efi_partition.h | 14 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/vds.c | 5 |
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); |