diff options
author | John Levon <john.levon@joyent.com> | 2019-04-01 10:05:45 +0000 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2019-04-08 08:43:36 +0000 |
commit | fa83485c3551a3fd3848f1535acb98b30c6595a2 (patch) | |
tree | d1ab84da58bdbfaf128c634c000feebb17422123 /usr/src/uts/common | |
parent | 9a8207fa35a4a0b13b30000d6ead058c47c0ccc3 (diff) | |
download | illumos-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.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/io/cmlb.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/io/lofi.c | 72 | ||||
-rw-r--r-- | usr/src/uts/common/sys/efi_partition.h | 14 |
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 |