Skip to content
This repository has been archived by the owner on Nov 7, 2019. It is now read-only.

Commit

Permalink
10570 Need workaround to EFI boot on AMI BIOS
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
John Levon committed Apr 23, 2019
1 parent 995a963 commit fd79773
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 20 deletions.
26 changes: 12 additions & 14 deletions usr/src/lib/libefi/common/rdwr_efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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
Expand All @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
5 changes: 3 additions & 2 deletions usr/src/uts/common/fs/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/

/*
Expand Down Expand Up @@ -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);
Expand All @@ -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))
Expand Down
3 changes: 2 additions & 1 deletion usr/src/uts/common/io/cmlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/

/*
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 13 additions & 1 deletion usr/src/uts/common/sys/efi_partition.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions usr/src/uts/sun4v/io/vds.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Joyent, Inc.
*/

/*
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit fd79773

Please sign in to comment.