summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2019-04-01 10:05:45 +0000
committerJohn Levon <john.levon@joyent.com>2019-04-08 08:43:36 +0000
commitfa83485c3551a3fd3848f1535acb98b30c6595a2 (patch)
treed1ab84da58bdbfaf128c634c000feebb17422123 /usr/src/uts/common
parent9a8207fa35a4a0b13b30000d6ead058c47c0ccc3 (diff)
downloadillumos-joyent-fa83485c3551a3fd3848f1535acb98b30c6595a2.tar.gz
OS-7260 SmartOS should support booting with loader
OS-7271 proto.boot should include loader instead of grub OS-7332 RICHMOND-16 mitigation ensnares stock loaders OS-7584 MDB module for disk labelling would be useful OS-7585 Need workaround to EFI boot on AMI BIOS OS-7595 Triton-specific extensions to Loader Portions contributed by: Rob Johnston <rob.johnston@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/fs/zfs/zvol.c6
-rw-r--r--usr/src/uts/common/io/cmlb.c3
-rw-r--r--usr/src/uts/common/io/lofi.c72
-rw-r--r--usr/src/uts/common/sys/efi_partition.h14
4 files changed, 86 insertions, 9 deletions
diff --git a/usr/src/uts/common/fs/zfs/zvol.c b/usr/src/uts/common/fs/zfs/zvol.c
index 196c98c602..33bac61d21 100644
--- a/usr/src/uts/common/fs/zfs/zvol.c
+++ b/usr/src/uts/common/fs/zfs/zvol.c
@@ -26,7 +26,7 @@
* Copyright 2017 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, 2017 by Delphix. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
- * Copyright 2018 Joyent, Inc.
+ * Copyright (c) 2019, Joyent, Inc.
*/
/*
@@ -1622,7 +1622,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);
@@ -1632,7 +1632,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 17eca53288..417010c8e9 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/io/lofi.c b/usr/src/uts/common/io/lofi.c
index e8d82a6688..5032452543 100644
--- a/usr/src/uts/common/io/lofi.c
+++ b/usr/src/uts/common/io/lofi.c
@@ -168,6 +168,8 @@
#include <sys/scsi/scsi.h> /* for DTYPE_DIRECT */
#include <sys/scsi/impl/uscsi.h>
#include <sys/sysevent/dev.h>
+#include <sys/efi_partition.h>
+#include <sys/note.h>
#include <LzmaDec.h>
#define NBLOCKS_PROP_NAME "Nblocks"
@@ -1741,26 +1743,58 @@ lofi_strategy(struct buf *bp)
return (0);
}
-/*ARGSUSED2*/
static int
lofi_read(dev_t dev, struct uio *uio, struct cred *credp)
{
+ _NOTE(ARGUNUSED(credp));
+
if (getminor(dev) == 0)
return (EINVAL);
UIO_CHECK(uio);
return (physio(lofi_strategy, NULL, dev, B_READ, minphys, uio));
}
-/*ARGSUSED2*/
static int
lofi_write(dev_t dev, struct uio *uio, struct cred *credp)
{
+ _NOTE(ARGUNUSED(credp));
+
if (getminor(dev) == 0)
return (EINVAL);
UIO_CHECK(uio);
return (physio(lofi_strategy, NULL, dev, B_WRITE, minphys, uio));
}
+static int
+lofi_urw(struct lofi_state *lsp, uint16_t fmode, diskaddr_t off, size_t size,
+ intptr_t arg, int flag, cred_t *credp)
+{
+ struct uio uio;
+ iovec_t iov;
+
+ /*
+ * 1024 * 1024 apes cmlb_tg_max_efi_xfer as a reasonable max.
+ */
+ if (size == 0 || size > 1024 * 1024 ||
+ (size % (1 << lsp->ls_lbshift)) != 0)
+ return (EINVAL);
+
+ iov.iov_base = (void *)arg;
+ iov.iov_len = size;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_loffset = off;
+ uio.uio_segflg = (flag & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE;
+ uio.uio_llimit = MAXOFFSET_T;
+ uio.uio_resid = size;
+ uio.uio_fmode = fmode;
+ uio.uio_extflg = 0;
+
+ return (fmode == FREAD ?
+ lofi_read(lsp->ls_dev, &uio, credp) :
+ lofi_write(lsp->ls_dev, &uio, credp));
+}
+
/*ARGSUSED2*/
static int
lofi_aread(dev_t dev, struct aio_req *aio, struct cred *credp)
@@ -3185,10 +3219,11 @@ static int
lofi_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp,
int *rvalp)
{
- int error;
+ int error;
enum dkio_state dkstate;
struct lofi_state *lsp;
- int id;
+ dk_efi_t user_efi;
+ int id;
id = LOFI_MINOR2ID(getminor(dev));
@@ -3438,6 +3473,35 @@ lofi_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp,
#endif /* _MULTI_DATAMODEL */
return (0);
}
+
+ case DKIOCGMBOOT:
+ return (lofi_urw(lsp, FREAD, 0, 1 << lsp->ls_lbshift,
+ arg, flag, credp));
+
+ case DKIOCSMBOOT:
+ return (lofi_urw(lsp, FWRITE, 0, 1 << lsp->ls_lbshift,
+ arg, flag, credp));
+
+ case DKIOCGETEFI:
+ if (ddi_copyin((void *)arg, &user_efi,
+ sizeof (dk_efi_t), flag) != 0)
+ return (EFAULT);
+
+ return (lofi_urw(lsp, FREAD,
+ user_efi.dki_lba * (1 << lsp->ls_lbshift),
+ user_efi.dki_length, (intptr_t)user_efi.dki_data,
+ flag, credp));
+
+ case DKIOCSETEFI:
+ if (ddi_copyin((void *)arg, &user_efi,
+ sizeof (dk_efi_t), flag) != 0)
+ return (EFAULT);
+
+ return (lofi_urw(lsp, FWRITE,
+ user_efi.dki_lba * (1 << lsp->ls_lbshift),
+ user_efi.dki_length, (intptr_t)user_efi.dki_data,
+ flag, credp));
+
default:
#ifdef DEBUG
cmn_err(CE_WARN, "lofi_ioctl: %d is not implemented\n", cmd);
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