Skip to contentSkip to conversation

SED OPAL Library

PATCH Superseded Scott Bauer 6 participants 28 messages Dec 29, 2016 – Jan 30, 2017

Subsystems (3)

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v4 cover SED OPAL Library

5) Removed dependency on the file struct. We also do not add a new entry into the block structures. We enter through the drivers block ioctl handler, which will test if it's a sed ioctl. If it is, we pass a previously allocated sed_context structure, cmd and arg, into the sed-ioctl.c which will dispatch it into the opal core.

6) The NVMe patch changed a bit:
The sed_context is now per-namespace for two reasons. First The spec says we have to send a namespace ID for the security commands, even if TCG spec currently ignores them. Second, there is public review for a modification to the spec where the namespace ID will be vitally important:
https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_Storage_Feature_Set_Namespaces_phase_1b_v1_00_r1_19_public-review.pdf

7) To facilitate the above public review changes, and potentially future changes the Opal core now exposes a new method which in-kernel users can call:
is_opal_supported().
The method is not exposed to userland, but will be used for drivers who wish to see if their controller supports Opal. The function can save the entire disovery0 payload which the driver can then parse to find out more info.

8) The NVMe driver now calls the new function above to see if the controller supports opal. If it does not we free the structures. The current implementation does not save the discovery0 payload. When the public review spec is finalized and someone ships devices with multiple namespace multiple LR support they can modify the code to save the payload and parse it to figure out what NS/LR mode they're going to be operating in.

===============================================================================
This Patch series implements a large portion of the Opal protocol for self encrypting devices. The driver has the capability of storing a locking range's password. The password can then be replayed during a resume from previous suspend-to-RAM.

The driver also supports logic to bring the device out of a factory default-inactive state into a functional Opal state.

The following logic is supported in order to bring the tper into a working state:

1) Taking Ownership of the drive (Setting the Admin CPIN).
2) Activating the Locking SP (In Single User Mode or Normal Mode).
3) Setting up Locking Ranges (Single User or Normal Mode).
4) Adding users to Locking Ranges (Normal Mode Only).
5) Locking or Unlocking Locking Ranges (Single User Mode or Normal Mode).
6) Reverting the TPer (Restore to factory default).
7) Setting LR/User passwords (Single User Mode or Normal Mode).
8) Enabling/disabling Shadow MBR.
9) Enabling Users in the LockingSP (Normal Mode Only).
10) Saving Password for resume from suspend.
11) Erase and Secure erasing locking ranges.

Scott Bauer (6):
Include: Uapi: Add user ABI for Sed/Opal
block: Add Sed-opal library
block: add ioctl interface for interfacing with Opal library
block: Add Opal Files to Makefile & add config option to Kconfig
nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls
Maintainers: Add maintainer info for SED/Opal library

 MAINTAINERS                   |   11 +
 block/Kconfig                 |    6 +
 block/Makefile                |    1 +
 block/opal_proto.h            |  588 ++++++++++
 block/sed-ioctl.c             |  164 +++
 block/sed-opal.c              | 2392 +++++++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/Kconfig     |    7 +
 drivers/nvme/host/core.c      |   78 ++
 drivers/nvme/host/nvme.h      |    9 +-
 drivers/nvme/host/pci.c       |    4 +
 include/linux/sed-opal.h      |   59 +
 include/linux/sed.h           |   80 ++
 include/uapi/linux/sed-opal.h |  107 ++
 13 files changed, 3505 insertions(+), 1 deletion(-)
 create mode 100644 block/opal_proto.h
 create mode 100644 block/sed-ioctl.c
 create mode 100644 block/sed-opal.c
 create mode 100644 include/linux/sed-opal.h
 create mode 100644 include/linux/sed.h
 create mode 100644 include/uapi/linux/sed-opal.h
#1 lore raw

PATCH v4 1/6 Include: Uapi: Add user ABI for Sed/Opal

Signed-off-by Scott Bauer <scott.bauer at intel.com>
Signed-off-by Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 include/uapi/linux/sed-opal.h | 107 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)
 create mode 100644 include/uapi/linux/sed-opal.h
include/uapi/linux/sed-opal.h new file +107 -0
new file mode 100644
index 0000000..c06077a
@@ -0,0 +1,107 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _UAPI_SED_OPAL_H
+#define _UAPI_SED_OPAL_H
+
+#include <linux/types.h>
+
+#define OPAL_KEY_MAX 256
+
+enum opal_mbr {
+	OPAL_MBR_ENABLE,
+	OPAL_MBR_DISABLE,
+};
+
+enum opal_user {
+	OPAL_ADMIN1,
+	OPAL_USER1,
+	OPAL_USER2,
+	OPAL_USER3,
+	OPAL_USER4,
+	OPAL_USER5,
+	OPAL_USER6,
+	OPAL_USER7,
+	OPAL_USER8,
+	OPAL_USER9,
+};
+
+enum opal_lock_state {
+	OPAL_RO = 0x01, /* 0001 */
+	OPAL_RW = 0x02, /* 0010 */
+	OPAL_LK = 0x04, /* 0100 */
+};
+
+struct opal_key {
+	uint8_t	lr;
+	uint8_t	key_len;
+	char 	key[OPAL_KEY_MAX];
+};
+
+struct opal_session_info {
+	int sum;
+	struct opal_key opal_key;
+	enum opal_user who;
+};
+
+struct opal_user_lr_setup {
+	struct opal_session_info session;
+	size_t range_start;
+	size_t range_length;
+	int    RLE; /* Read Lock enabled */
+	int    WLE; /* Write Lock Enabled */
+};
+
+struct opal_lock_unlock {
+	struct opal_session_info session;
+	enum opal_lock_state l_state;
+};
+
+struct opal_new_pw {
+	struct opal_session_info session;
+
+	/* When we're not operating in sum, and we first set
+	 * passwords we need to set them via ADMIN authority.
+	 * After passwords are changed, we can set them via,
+	 * User authorities.
+	 * Because of this restriction we need to know about
+	 * Two different users. One in 'session' which we will use
+	 * to start the session and new_userr_pw as the user we're
+	 * chaning the pw for.
+	 */
+	struct opal_session_info new_user_pw;
+};
+
+struct opal_mbr_data {
+	u8 enable_disable;
+	struct opal_key key;
+};
+
+#define IOC_OPAL_SAVE		    _IOW('p', 220, struct opal_lock_unlock)
+#define IOC_OPAL_LOCK_UNLOCK	    _IOW('p', 221, struct opal_lock_unlock)
+#define IOC_OPAL_TAKE_OWNERSHIP	    _IOW('p', 222, struct opal_key)
+#define IOC_OPAL_ACTIVATE_LSP       _IOW('p', 223, struct opal_key)
+#define IOC_OPAL_SET_PW             _IOW('p', 224, struct opal_new_pw)
+#define IOC_OPAL_ACTIVATE_USR       _IOW('p', 225, struct opal_session_info)
+#define IOC_OPAL_REVERT_TPR         _IOW('p', 226, struct opal_key)
+#define IOC_OPAL_LR_SETUP           _IOW('p', 227, struct opal_user_lr_setup)
+#define IOC_OPAL_ADD_USR_TO_LR      _IOW('p', 228, struct opal_lock_unlock)
+#define IOC_OPAL_ENABLE_DISABLE_MBR _IOW('p', 229, struct opal_mbr_data)
+#define IOC_OPAL_ERASE_LR           _IOW('p', 230, struct opal_session_info)
+#define IOC_OPAL_SECURE_ERASE_LR    _IOW('p', 231, struct opal_session_info)
+
+#endif /* _UAPI_SED_OPAL_H */
Signature · 1 line
2.7.4
#2 lore raw

PATCH v4 2/6 block: Add Sed-opal library

In reply to Scott Bauer

This patch implements the necessary logic to bring an Opal enabled drive out of a factory-enabled into a working Opal state.

This patch set also enables logic to save a password to be replayed during a resume from suspend.

Signed-off-by Scott Bauer <scott.bauer at intel.com>
Signed-off-by Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 block/opal_proto.h       |  588 ++++++++++++
 block/sed-opal.c         | 2392 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/sed-opal.h |   59 ++
 include/linux/sed.h      |   80 ++
 4 files changed, 3119 insertions(+)
 create mode 100644 block/opal_proto.h
 create mode 100644 block/sed-opal.c
 create mode 100644 include/linux/sed-opal.h
 create mode 100644 include/linux/sed.h
block/opal_proto.h new file +588 -0
new file mode 100644
index 0000000..62adee6
@@ -0,0 +1,588 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _OPAL_PROTO_H
+#define _OPAL_PROTO_H
+
+#define DTAERROR_NO_METHOD_STATUS 0x89
+#define GENERIC_HOST_SESSION_NUM 0x41
+
+#define TPER_SYNC_SUPPORTED BIT(0)
+
+#define TINY_ATOM_DATA_MASK GENMASK(5, 0)
+#define TINY_ATOM_SIGNED BIT(6)
+
+#define SHORT_ATOM_ID BIT(7)
+#define SHORT_ATOM_BYTESTRING BIT(5)
+#define SHORT_ATOM_SIGNED BIT(4)
+#define SHORT_ATOM_LEN_MASK GENMASK(3, 0)
+
+#define MEDIUM_ATOM_ID (BIT(7) | BIT(6))
+#define MEDIUM_ATOM_BYTESTRING BIT(4)
+#define MEDIUM_ATOM_SIGNED BIT(3)
+#define MEDIUM_ATOM_LEN_MASK GENMASK(2, 0)
+
+#define LONG_ATOM_ID (BIT(7) | BIT(6) | BIT(5))
+#define LONG_ATOM_BYTESTRING BIT(1)
+#define LONG_ATOM_SIGNED BIT(0)
+
+/* Derived from TCG Core spec 2.01 Section:
+ * 3.2.2.1
+ * Data Type
+ */
+#define TINY_ATOM_BYTE   0x7F
+#define SHORT_ATOM_BYTE  0xBF
+#define MEDIUM_ATOM_BYTE 0xDF
+#define LONG_ATOM_BYTE   0xE3
+
+#define OPAL_INVAL_PARAM 12
+#define OPAL_MANUFACTURED_INACTIVE 0x08
+#define OPAL_DISCOVERY_COMID 0x0001
+
+#define LOCKING_RANGE_NON_GLOBAL 0x03
+/*
+ * User IDs used in the TCG storage SSCs
+ * Derived from: TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Section: 6.3 Assigned UIDs
+ */
+static const u8 OPALUID[][8] = {
+	/* users */
+
+	/* session management  */
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff},
+	/* special "thisSP" syntax */
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+	/* Administrative SP */
+	{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },
+	/* Locking SP */
+	{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },
+	/* ENTERPRISE Locking SP  */
+	{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 },
+	/* anybody */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },
+	/* SID */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },
+	/* ADMIN1 */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },
+	/* USER1 */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },
+	/* USER2 */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },
+	/* PSID user */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },
+	/* BandMaster 0 */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 },
+	 /* EraseMaster */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 },
+
+	/* tables */
+
+	/* Locking_GlobalRange */
+	{ 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 },
+	/* ACE_Locking_Range_Set_RdLocked UID */
+	{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 },
+	/* ACE_Locking_Range_Set_WrLocked UID */
+	{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 },
+	/* MBR Control */
+	{ 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 },
+	/* Shadow MBR */
+	{ 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 },
+	/* AUTHORITY_TABLE */
+	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00},
+	/* C_PIN_TABLE */
+	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00},
+	/* OPAL Locking Info */
+	{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 },
+	/* Enterprise Locking Info */
+	{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
+
+	/* C_PIN_TABLE object ID's */
+
+	/* C_PIN_MSID */
+	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02},
+	/* C_PIN_SID */
+	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01},
+	 /* C_PIN_ADMIN1 */
+	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01},
+
+	/* half UID's (only first 4 bytes used) */
+
+	/* Half-UID ? Authority_object_ref */
+	{ 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff },
+	/* Half-UID ? Boolean ACE */
+	{ 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff },
+
+	/* special value for omitted optional parameter */
+
+	/* HEXFF for omitted */
+	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+};
+#define OPAL_UID_LENGTH 8
+#define OPAL_MSID_KEYLEN 15
+#define OPAL_UID_LENGTH_HALF 4
+
+
+/* Enum to index OPALUID array */
+enum OPAL_UID {
+	/* users */
+	OPAL_SMUID_UID,
+	OPAL_THISSP_UID,
+	OPAL_ADMINSP_UID,
+	OPAL_LOCKINGSP_UID,
+	OPAL_ENTERPRISE_LOCKINGSP_UID,
+	OPAL_ANYBODY_UID,
+	OPAL_SID_UID,
+	OPAL_ADMIN1_UID,
+	OPAL_USER1_UID,
+	OPAL_USER2_UID,
+	OPAL_PSID_UID,
+	OPAL_ENTERPRISE_BANDMASTER0_UID,
+	OPAL_ENTERPRISE_ERASEMASTER_UID,
+	/* tables */
+	OPAL_LOCKINGRANGE_GLOBAL,
+	OPAL_LOCKINGRANGE_ACE_RDLOCKED,
+	OPAL_LOCKINGRANGE_ACE_WRLOCKED,
+	OPAL_MBRCONTROL,
+	OPAL_MBR,
+	OPAL_AUTHORITY_TABLE,
+	OPAL_C_PIN_TABLE,
+	OPAL_LOCKING_INFO_TABLE,
+	OPAL_ENTERPRISE_LOCKING_INFO_TABLE,
+	/* C_PIN_TABLE object ID's */
+	OPAL_C_PIN_MSID,
+	OPAL_C_PIN_SID,
+	OPAL_C_PIN_ADMIN1,
+	/* half UID's (only first 4 bytes used) */
+	OPAL_HALF_UID_AUTHORITY_OBJ_REF,
+	OPAL_HALF_UID_BOOLEAN_ACE,
+	/* omitted optional parameter */
+	OPAL_UID_HEXFF,
+};
+
+/*
+ * TCG Storage SSC Methods.
+ * Derived from: TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Section: 6.3 Assigned UIDs
+ */
+static const u8 OPALMETHOD[][8] = {
+	/* Properties */
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 },
+	/* STARTSESSION */
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 },
+	/* Revert */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 },
+	/* Activate */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 },
+	/* Enterprise Get */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 },
+	/* Enterprise Set */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 },
+	/* NEXT */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 },
+	/* Enterprise Authenticate */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c },
+	/* GetACL */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d },
+	/* GenKey */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 },
+	/* revertSP */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 },
+	/* Get */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 },
+	/* Set */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 },
+	/* Authenticate */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c },
+	/* Random */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },
+	/* Erase */
+	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 },
+};
+#define OPAL_METHOD_LENGTH 8
+
+/* Enum for indexing the OPALMETHOD array */
+enum OPAL_METHOD {
+	OPAL_PROPERTIES,
+	OPAL_STARTSESSION,
+	OPAL_REVERT,
+	OPAL_ACTIVATE,
+	OPAL_EGET,
+	OPAL_ESET,
+	OPAL_NEXT,
+	OPAL_EAUTHENTICATE,
+	OPAL_GETACL,
+	OPAL_GENKEY,
+	OPAL_REVERTSP,
+	OPAL_GET,
+	OPAL_SET,
+	OPAL_AUTHENTICATE,
+	OPAL_RANDOM,
+	OPAL_ERASE,
+};
+
+/*
+ * Token defs derived from:
+ * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * 3.2.2 Data Stream Encoding
+ */
+enum OPAL_RESPONSE_TOKEN {
+	OPAL_DTA_TOKENID_BYTESTRING = 0xe0,
+	OPAL_DTA_TOKENID_SINT = 0xe1,
+	OPAL_DTA_TOKENID_UINT = 0xe2,
+	OPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */
+	OPAL_DTA_TOKENID_INVALID = 0X0
+};
+
+enum OPAL_TOKEN {
+	/* Boolean */
+	OPAL_TRUE = 0x01,
+	OPAL_FALSE = 0x00,
+	OPAL_BOOLEAN_EXPR = 0x03,
+	/* cellblocks */
+	OPAL_TABLE = 0x00,
+	OPAL_STARTROW = 0x01,
+	OPAL_ENDROW = 0x02,
+	OPAL_STARTCOLUMN = 0x03,
+	OPAL_ENDCOLUMN = 0x04,
+	OPAL_VALUES = 0x01,
+	/* authority table */
+	OPAL_PIN = 0x03,
+	/* locking tokens */
+	OPAL_RANGESTART = 0x03,
+	OPAL_RANGELENGTH = 0x04,
+	OPAL_READLOCKENABLED = 0x05,
+	OPAL_WRITELOCKENABLED = 0x06,
+	OPAL_READLOCKED = 0x07,
+	OPAL_WRITELOCKED = 0x08,
+	OPAL_ACTIVEKEY = 0x0A,
+	/* locking info table */
+	OPAL_MAXRANGES = 0x04,
+	 /* mbr control */
+	OPAL_MBRENABLE = 0x01,
+	OPAL_MBRDONE = 0x02,
+	/* properties */
+	OPAL_HOSTPROPERTIES = 0x00,
+	/* atoms */
+	OPAL_STARTLIST = 0xf0,
+	OPAL_ENDLIST = 0xf1,
+	OPAL_STARTNAME = 0xf2,
+	OPAL_ENDNAME = 0xf3,
+	OPAL_CALL = 0xf8,
+	OPAL_ENDOFDATA = 0xf9,
+	OPAL_ENDOFSESSION = 0xfa,
+	OPAL_STARTTRANSACTON = 0xfb,
+	OPAL_ENDTRANSACTON = 0xfC,
+	OPAL_EMPTYATOM = 0xff,
+	OPAL_WHERE = 0x00,
+};
+
+/* Useful tiny atoms.
+ * Useful for table columns etc
+ */
+enum OPAL_TINY_ATOM {
+	OPAL_TINY_UINT_00 = 0x00,
+	OPAL_TINY_UINT_01 = 0x01,
+	OPAL_TINY_UINT_02 = 0x02,
+	OPAL_TINY_UINT_03 = 0x03,
+	OPAL_TINY_UINT_04 = 0x04,
+	OPAL_TINY_UINT_05 = 0x05,
+	OPAL_TINY_UINT_06 = 0x06,
+	OPAL_TINY_UINT_07 = 0x07,
+	OPAL_TINY_UINT_08 = 0x08,
+	OPAL_TINY_UINT_09 = 0x09,
+	OPAL_TINY_UINT_10 = 0x0a,
+	OPAL_TINY_UINT_11 = 0x0b,
+	OPAL_TINY_UINT_12 = 0x0c,
+	OPAL_TINY_UINT_13 = 0x0d,
+	OPAL_TINY_UINT_14 = 0x0e,
+	OPAL_TINY_UINT_15 = 0x0f,
+};
+
+enum OPAL_ATOM_WIDTH {
+	OPAL_WIDTH_TINY,
+	OPAL_WIDTH_SHORT,
+	OPAL_WIDTH_MEDIUM,
+	OPAL_WIDTH_LONG,
+	OPAL_WIDTH_TOKEN
+};
+
+/* Locking state for a locking range */
+enum OPAL_LOCKINGSTATE {
+	OPAL_LOCKING_READWRITE = 0x01,
+	OPAL_LOCKING_READONLY = 0x02,
+	OPAL_LOCKING_LOCKED = 0x03,
+};
+
+/*
+ * Structures to build and decode the Opal SSC messages
+ * fields that are NOT really numeric are defined as u8[] to
+ * help reduce the endianness issues
+ */
+
+/* Packets derived from:
+ * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Secion: 3.2.3 ComPackets, Packets & Subpackets
+ */
+
+/* Comm Packet (header) for transmissions. */
+struct opal_compacket {
+	u32 reserved0;
+	u8 extendedComID[4];
+	u32 outstandingData;
+	u32 minTransfer;
+	u32 length;
+};
+
+/* Packet structure. */
+struct opal_packet {
+	u32 tsn;
+	u32 hsn;
+	u32 seq_number;
+	u16 reserved0;
+	u16 ack_type;
+	u32 acknowledgment;
+	u32 length;
+};
+
+/* Data sub packet header */
+struct opal_data_subpacket {
+	u8 reserved0[6];
+	u16 kind;
+	u32 length;
+};
+
+/* header of a response */
+struct opal_header {
+	struct opal_compacket cp;
+	struct opal_packet pkt;
+	struct opal_data_subpacket subpkt;
+};
+
+#define FC_TPER       0x0001
+#define FC_LOCKING    0x0002
+#define FC_GEOMETRY   0x0003
+#define FC_ENTERPRISE 0x0100
+#define FC_DATASTORE  0x0202
+#define FC_SINGLEUSER 0x0201
+#define FC_OPALV100   0x0200
+#define FC_OPALV200   0x0203
+
+/*
+ * The Discovery 0 Header. As defined in
+ * Opal SSC Documentation
+ * Section: 3.3.5 Capability Discovery
+ */
+struct d0_header {
+	u32 length; /* the length of the header 48 in 2.00.100 */
+	u32 revision; /**< revision of the header 1 in 2.00.100 */
+	u32 reserved01;
+	u32 reserved02;
+	/*
+	 * the remainder of the structure is vendor specific and will not be
+	 * addressed now
+	 */
+	u8 ignored[32];
+};
+
+/*
+ * TPer Feature Descriptor. Contains flags indicating support for the
+ * TPer features described in the OPAL specification. The names match the
+ * OPAL terminology
+ *
+ * code == 0x001 in 2.00.100
+ */
+struct d0_tper_features {
+	/*
+	 * supported_features bits:
+	 * bit 7: reserved
+	 * bit 6: com ID management
+	 * bit 5: reserved
+	 * bit 4: streaming support
+	 * bit 3: buffer management
+	 * bit 2: ACK/NACK
+	 * bit 1: async
+	 * bit 0: sync
+	 */
+	u8 supported_features;
+	/*
+	 * bytes 5 through 15 are reserved, but we represent the first 3 as
+	 * u8 to keep the other two 32bits integers aligned.
+	 */
+	u8 reserved01[3];
+	u32 reserved02;
+	u32 reserved03;
+};
+
+/*
+ * Locking Feature Descriptor. Contains flags indicating support for the
+ * locking features described in the OPAL specification. The names match the
+ * OPAL terminology
+ *
+ * code == 0x0002 in 2.00.100
+ */
+struct d0_locking_features {
+	/*
+	 * supported_features bits:
+	 * bits 6-7: reserved
+	 * bit 5: MBR done
+	 * bit 4: MBR enabled
+	 * bit 3: media encryption
+	 * bit 2: locked
+	 * bit 1: locking enabled
+	 * bit 0: locking supported
+	 */
+	u8 supported_features;
+	/*
+	 * bytes 5 through 15 are reserved, but we represent the first 3 as
+	 * u8 to keep the other two 32bits integers aligned.
+	 */
+	u8 reserved01[3];
+	u32 reserved02;
+	u32 reserved03;
+};
+
+/*
+ * Geometry Feature Descriptor. Contains flags indicating support for the
+ * geometry features described in the OPAL specification. The names match the
+ * OPAL terminology
+ *
+ * code == 0x0003 in 2.00.100
+ */
+struct d0_geometry_features {
+	/*
+	 * skip 32 bits from header, needed to align the struct to 64 bits.
+	 */
+	u8 header[4];
+	/*
+	 * reserved01:
+	 * bits 1-6: reserved
+	 * bit 0: align
+	 */
+	u8 reserved01;
+	u8 reserved02[7];
+	u32 logical_block_size;
+	u64 alignment_granularity;
+	u64 lowest_aligned_lba;
+};
+
+/*
+ * Enterprise SSC Feature
+ *
+ * code == 0x0100
+ */
+struct d0_enterprise_ssc {
+	u16 baseComID;
+	u16 numComIDs;
+	/* range_crossing:
+	 * bits 1-6: reserved
+	 * bit 0: range crossing
+	 */
+	u8 range_crossing;
+	u8 reserved01;
+	u16 reserved02;
+	u32 reserved03;
+	u32 reserved04;
+};
+
+/*
+ * Opal V1 feature
+ *
+ * code == 0x0200
+ */
+struct d0_opal_v100 {
+	u16 baseComID;
+	u16 numComIDs;
+};
+
+/*
+ * Single User Mode feature
+ *
+ * code == 0x0201
+ */
+struct d0_single_user_mode {
+	u32 num_locking_objects;
+	/* reserved01:
+	 * bit 0: any
+	 * bit 1: all
+	 * bit 2: policy
+	 * bits 3-7: reserved
+	 */
+	u8 reserved01;
+	u8 reserved02;
+	u16 reserved03;
+	u32 reserved04;
+};
+
+/*
+ * Additonal Datastores feature
+ *
+ * code == 0x0202
+ */
+struct d0_datastore_table {
+	u16 reserved01;
+	u16 max_tables;
+	u32 max_size_tables;
+	u32 table_size_alignment;
+};
+
+/*
+ * OPAL 2.0 feature
+ *
+ * code == 0x0203
+ */
+struct d0_opal_v200 {
+	u16 baseComID;
+	u16 numComIDs;
+	/* range_crossing:
+	 * bits 1-6: reserved
+	 * bit 0: range crossing
+	 */
+	u8 range_crossing;
+	/* num_locking_admin_auth:
+	 * not aligned to 16 bits, so use two u8.
+	 * stored in big endian:
+	 * 0: MSB
+	 * 1: LSB
+	 */
+	u8 num_locking_admin_auth[2];
+	/* num_locking_user_auth:
+	 * not aligned to 16 bits, so use two u8.
+	 * stored in big endian:
+	 * 0: MSB
+	 * 1: LSB
+	 */
+	u8 num_locking_user_auth[2];
+	u8 initialPIN;
+	u8 revertedPIN;
+	u8 reserved01;
+	u32 reserved02;
+};
+
+/* Union of features used to parse the discovery 0 response */
+struct d0_features {
+	u16 code;
+	/*
+	 * r_version bits:
+	 * bits 4-7: version
+	 * bits 0-3: reserved
+	 */
+	u8 r_version;
+	u8 length;
+	u8 features[];
+};
+
+#endif /* _OPAL_PROTO_H */
block/sed-opal.c new file +2392 -0

2,392 lines not on this page · raw message

include/linux/sed-opal.h new file +59 -0

20 lines not on this page · raw message

include/linux/sed.h new file +80 -0

80 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.7.4

Part of the diff is not shown here. View the raw message.

#3 lore raw

PATCH v4 2/6 block: Add Sed-opal library

Hi Scott,

I haven't had much time with this yet, but..

[snip]

Quoted 19 lines
block/sed-opal.c new file +18 -0
+static int do_cmds(struct opal_dev *dev)
+{
+	int ret;
+	ret = next(dev);
+	mutex_unlock(&dev->dev_lock);
+	return ret;
+}
+
+static struct opal_dev *get_opal_dev(struct sed_context *sedc,
+				     const opal_step *funcs)
+{
+	struct opal_dev *dev = sedc->dev;
+	if (dev) {
+		mutex_lock(&dev->dev_lock);
+		dev->state = 0;
+		dev->funcs = funcs;
+		dev->tsn = 0;
+		dev->hsn = 0;

block/sed-opal.c line 1989

Quoted 10 lines
block/sed-opal.c new file +10 -0
+		dev->error_cb = end_opal_session_error;
+		dev->error_cb_data = dev;
+		dev->func_data = NULL;
+		dev->prev_data = NULL;
+		dev->sed_ctx = sedc;
+		dev->save_discovery = false;
+	}
+	return dev;
+}
+

It's a bit nontraditional to lock and unlock in different functions, but I see why you're doing it this way.

Can we move the mutex locking/unlocking to the callers of these functions, such that they are both in the same function; then we can use lockdep_assert_held(..) on the in-between?

Cheers

#4 lore raw

PATCH v4 2/6 block: Add Sed-opal library

Quoted 6 lines · Jon Derrick

It's a bit nontraditional to lock and unlock in different functions, but I see why you're doing it this way.

Can we move the mutex locking/unlocking to the callers of these functions, such that they are both in the same function; then we can use lockdep_assert_held(..) on the in-between?

Yes, that sounds like a good idea to me. Note that sparse would warn about these unbalanced locks/unlocks without annotations, so I'll use this opportunity to run sparse over it. Documentation for it used to be trivial to find in Documentation/sparse.txt but somehow has disappeared in the latest kernel tree unfortunately.

#5 lore raw

PATCH v4 2/6 block: Add Sed-opal library

In reply to Scott Bauer
Quoted 3 lines · Scott Bauer
Signed-off-by Scott Bauer <scott.bauer at intel.com>
Signed-off-by Rafael Antognolli <Rafael.Antognolli at intel.com>

---

Please use the proper @ sign for email addresses.

block/opal_proto.h line 26

Quoted 3 lines
block/opal_proto.h new file +3 -0
+#define TPER_SYNC_SUPPORTED BIT(0)
+
+#define TINY_ATOM_DATA_MASK GENMASK(5, 0)

I know some people suggest to use BIT and GENMASK, but I find these horrible to read compared to the traditional C notations..

Quoted 1 line

+static const u8 OPALUID[][8] = {

As per the last run: please no actual variable declarations in header files, these arrays belong into a .c file, e.g. opal_proto.c or simply in sed-opal.c

Quoted 12 lines
block/opal_proto.h new file +12 -0
+
+/* Useful tiny atoms.
+ * Useful for table columns etc
+ */
+enum OPAL_TINY_ATOM {
+	OPAL_TINY_UINT_00 = 0x00,
+	OPAL_TINY_UINT_01 = 0x01,
+	OPAL_TINY_UINT_02 = 0x02,
+	OPAL_TINY_UINT_03 = 0x03,
+	OPAL_TINY_UINT_04 = 0x04,
+	OPAL_TINY_UINT_05 = 0x05,
+	OPAL_TINY_UINT_06 = 0x06,

block/opal_proto.h line 313

Quoted 10 lines
block/opal_proto.h new file +10 -0
+	OPAL_TINY_UINT_07 = 0x07,
+	OPAL_TINY_UINT_08 = 0x08,
+	OPAL_TINY_UINT_09 = 0x09,
+	OPAL_TINY_UINT_10 = 0x0a,
+	OPAL_TINY_UINT_11 = 0x0b,
+	OPAL_TINY_UINT_12 = 0x0c,
+	OPAL_TINY_UINT_13 = 0x0d,
+	OPAL_TINY_UINT_14 = 0x0e,
+	OPAL_TINY_UINT_15 = 0x0f,
+};

Just using 0/1/.../15 in decimal notation directly in the code would be a lot easier to read I think :)

block/sed-opal.c line 43

Quoted 4 lines
block/sed-opal.c new file +4 -0
+
+struct opal_cmd {
+	cont_fn *cb;
+	void *cb_data;

It seems like these are both unused.

block/sed-opal.c line 119

Quoted 1 line
block/sed-opal.c new file +1 -0
+	opal_step error_cb;

This one always seems to be end_opal_session_error, which suggests it could be replaced with a direct call.

block/sed-opal.c line 121

Quoted 1 line
block/sed-opal.c new file +1 -0
+	bool save_discovery;

And this just points back to the opal_dev, so it might as well be removed.

block/sed-opal.c line 329

Quoted 1 line
block/sed-opal.c new file +1 -0
+		dev->prev_data = kmemdup(cpos, epos - cpos, GFP_KERNEL);

The kmemdup return value needs to be checked for errors.

Quoted 7 lines
block/sed-opal.c new file +7 -0
+	if (!supported) {
+		pr_err("This device is not Opal enabled. Not Supported!\n");
+		return 1;
+	}
+
+	if (!single_user)
+		pr_warn("Device doesn't support single user mode\n");

block/sed-opal.c line 389

Quoted 10 lines
block/sed-opal.c new file +10 -0
+
+
+	if (!foundComID) {
+		pr_warn("Could not find OPAL comid for device. Returning early\n");
+		return 1;
+	}
+
+	dev->comid = comid;
+
+	return 0;

Maybe switch the return value to a bool? Also please change foundComID to normal Linux variable spelling, e.g. found_comid.

block/sed-opal.c line 1950

Quoted 6 lines
block/sed-opal.c new file +6 -0
+	cmd->cmd = cmd->cmd_buf;
+	cmd->resp = cmd->resp_buf;
+
+	dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1;
+	cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align);
+	cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align);

The block layer will automatically bounce buffer non-aligned payloads. If the cost of copying is too high we could switch back to dynamic allocations using kmalloc here, which will be properly aligned.

Also ->cmd and ->resp probably should be void pointers, so that no casting is required for the various command and response structures.

Quoted 9 lines
block/sed-opal.c new file +9 -0
+static struct opal_dev *get_opal_dev(struct sed_context *sedc,
+				     const opal_step *funcs)
+{
+	struct opal_dev *dev = sedc->dev;
+	if (dev) {
+		mutex_lock(&dev->dev_lock);
+		dev->state = 0;
+		dev->funcs = funcs;
+		dev->tsn = 0;

block/sed-opal.c line 1988

Quoted 10 lines
block/sed-opal.c new file +10 -0
+		dev->hsn = 0;
+		dev->error_cb = end_opal_session_error;
+		dev->error_cb_data = dev;
+		dev->func_data = NULL;
+		dev->prev_data = NULL;
+		dev->sed_ctx = sedc;
+		dev->save_discovery = false;
+	}
+	return dev;
+}

This seems to be a bit misnamed. In the this starts a OPAL session, so maybe the name should reflect that?

Also it seems a bit odd to hide the sedc->dev derference in here, why not have the caller do that if it's needed, which for the few callers I looked at shouldn't even be nessecary.

e.g.

	struct opal_dev *dev = sedc->dev;

	mutex_lock(&dev->dev_lock);
	opal_start_session(dev);
	...
	mutex_lock(&dev->dev_lock);

That beeing said I'm also a bit confused about all the structures. It seems like sed_context and opal_dev could easily be merged. With two little accessors the memembers would not even have to be exposed publicly.

Also opal_cmd only seems to exist in the form of being embedded into opal_dev, so I don't strictly see the need for it either.

block/sed-opal.c line 2119

Quoted 1 line
block/sed-opal.c new file +1 -0
+	if(!suspend)

missing whitespace before the (

block/sed-opal.c line 2377

Quoted 3 lines
block/sed-opal.c new file +3 -0
+	list_for_each_entry(suspend, &dev->unlk_lst, node) {
+			dev->state = 0;
+			dev->func_data[1] = &suspend->unlk.session;

doube indentation.

block/sed-opal.c line 2390

Quoted 13 lines
block/sed-opal.c new file +13 -0
+			dev->func_data[2] = &suspend->unlk;
+			if (suspend->unlk.session.sum)
+				dev->funcs = ulk_funcs_sum;
+			else
+				dev->funcs = _unlock_funcs;
+			dev->tsn = 0;
+			dev->hsn = 0;
+			ret = next(dev);
+			if (ret)
+				was_failure = true;
+	}
+	mutex_unlock(&dev->dev_lock);
+	return was_failure ? 1 : 0;

Just return was_failure and change the prototype to return a bool as well.

Quoted 5 lines

+ *Drivers can use this to pass necessary data required for
+ *Their implementation of send/recv.
+ * @dev: Currently an Opal Dev structure. In the future can be other types
+ *Of security structures.
+ * @supported: Whether or not the device is sed supported.

There should always be a whitespace after the * in kernel comments.

In general it might be worth to run scripts/checkpath.pl over your patches before sending them and fix all errors, while the warnings are to be taken with a grain of salt unfortunately.

Quoted 9 lines
include/linux/sed.h new file +9 -0
+/*
+ * sec_ops - transport specific Trusted Send/Receive functions
+* See SPC-4 for specific definitions
+ *
+ * @sec_send: sends the payload to the trusted peripheral
+ *     spsp: Security Protocol Specific
+ *     secp: Security Protocol
+ *     buf: Payload
+ *     len: Payload length

include/linux/sed.h line 77

Quoted 10 lines
include/linux/sed.h new file +10 -0
+ * @recv: Receives a payload from the trusted peripheral
+ *     spsp: Security Protocol Specific
+ *     secp: Security Protocol
+ *     buf: Payload
+ *     len: Payload length
+ */
+struct sec_ops {
+	int (*sec_send)(void *ctrl_data, u16 spsp, u8 secp, void *buf, size_t len);
+	int (*sec_recv)(void *ctrl_data, u16 spsp, u8 secp, void *buf, size_t len);
+};

These aren't actually used.

Quoted 6 lines
include/linux/sed.h new file +3 -0
+int sed_ioctl(struct sed_context *sed_ctx, unsigned int cmd, unsigned long arg);
+
+#endif /* LINUX_SED_H */
Signature · 1 line
2.7.4

---end quoted text---

#6 lore raw

PATCH v4 2/6 block: Add Sed-opal library

[Snip...]

Quoted 6 lines

block/sed-opal.c line 2119

Quoted 2 lines
block/sed-opal.c new file +1 -0
+	if(!suspend)

missing whitespace before the (

Quoted 1 line
Quoted 6 lines

block/sed-opal.c line 2377

Quoted 3 lines
block/sed-opal.c new file +3 -0
+	list_for_each_entry(suspend, &dev->unlk_lst, node) {
+			dev->state = 0;
+			dev->func_data[1] = &suspend->unlk.session;

doube indentation.

Is checkpatch.pl being used before the patches are sent to the list? ?That tool should have flagged these problems to fix.

While you are at it, it would be good to run the code thru sparse if you haven't already.

Jay

Quoted 1 line
Quoted 1 line

?

#7 lore raw

PATCH v4 2/6 block: Add Sed-opal library

In reply to Christoph Hellwig
Quoted 13 lines · Christoph Hellwig

block/sed-opal.c line 1950

Quoted 6 lines · Scott Bauer
block/sed-opal.c new file +6 -0
+	cmd->cmd = cmd->cmd_buf;
+	cmd->resp = cmd->resp_buf;
+
+	dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1;
+	cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align);
+	cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align);

The block layer will automatically bounce buffer non-aligned payloads. If the cost of copying is too high we could switch back to dynamic allocations using kmalloc here, which will be properly aligned.

Quoted 2 lines

Also ->cmd and ->resp probably should be void pointers, so that no casting is required for the various command and response structures.

We'll keep it unaligned and let the block layer deal with it. I had previously toyed with the void pointers, but we reference directly into cmd->cmd[] during command setup. So while we'll avoid a cast here we'll end up adding more code/casts to other functions, so I'm going to leave it as is in the series coming out in an hour or so.

#8 lore raw

PATCH v4 2/6 block: Add Sed-opal library

In reply to Scott Bauer
Quoted 18 lines
block/sed-opal.c new file +17 -0
+struct opal_dev *alloc_opal_dev(struct request_queue *q)
+{
+	struct opal_dev *opal_dev;
+	unsigned long dma_align;
+	struct opal_cmd *cmd;
+
+	opal_dev = kzalloc(sizeof(*opal_dev), GFP_KERNEL);
+	if (!opal_dev)
+		return opal_dev;
+
+	cmd = &opal_dev->cmd;
+	cmd->cmd = cmd->cmd_buf;
+	cmd->resp = cmd->resp_buf;
+
+	dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1;
+	cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align);
+	cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align);

block/sed-opal.c line 1960

Quoted 10 lines
block/sed-opal.c new file +10 -0
+
+	INIT_LIST_HEAD(&opal_dev->unlk_lst);
+	opal_dev->state = 0;
+
+	mutex_init(&opal_dev->dev_lock);
+
+	return opal_dev;
+
+}
+EXPORT_SYMBOL(alloc_opal_dev);

Internally we've been discussing this function. We don't like the requirement that we have to pass in a request_queue just to allocate an opal dev.

We have a few ideas and wanted to toss them out here and see if anyone has one they love or one they hate.

So Idea one:

Pass in the alignment insetead of the request_queue. This pushes the burden onto the driver calling alloc_opal_dev instead of the opal core. It also removes the requirement of passing in a request_queue to something we think should be agnostic to any blocklayer/lower level structures/knowledge.

Idea two:

Just let alloc_opal_dev kzalloc normally and do no alignment. It would then be up to the drivers to move the data from the buffer to a bounce buffer, that is aligned, in the send/recv functions before sending down to the controller.

Both are easy to implement but we wanted to see if anyone had other ideas or liked one over the other.

#9 lore raw

PATCH v4 2/6 block: Add Sed-opal library

Quoted 35 lines · Scott Bauer
Quoted 18 lines
block/sed-opal.c new file +17 -0
+struct opal_dev *alloc_opal_dev(struct request_queue *q)
+{
+	struct opal_dev *opal_dev;
+	unsigned long dma_align;
+	struct opal_cmd *cmd;
+
+	opal_dev = kzalloc(sizeof(*opal_dev), GFP_KERNEL);
+	if (!opal_dev)
+		return opal_dev;
+
+	cmd = &opal_dev->cmd;
+	cmd->cmd = cmd->cmd_buf;
+	cmd->resp = cmd->resp_buf;
+
+	dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1;
+	cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align);
+	cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align);

block/sed-opal.c line 1960

Quoted 10 lines
block/sed-opal.c new file +10 -0
+
+	INIT_LIST_HEAD(&opal_dev->unlk_lst);
+	opal_dev->state = 0;
+
+	mutex_init(&opal_dev->dev_lock);
+
+	return opal_dev;
+
+}
+EXPORT_SYMBOL(alloc_opal_dev);

Internally we've been discussing this function. We don't like the requirement that we have to pass in a request_queue just to allocate an opal dev.

We have a few ideas and wanted to toss them out here and see if anyone has one they love or one they hate.

Quoted 9 lines

So Idea one:

Pass in the alignment insetead of the request_queue. This pushes the burden onto the driver calling alloc_opal_dev instead of the opal core. It also removes
the requirement of passing in a request_queue to something we think should be agnostic to any blocklayer/lower level structures/knowledge.

I would think it would be easier to support and validate and guarantee working operation of opal if the driver controlled the alignment instead relying on someone else in the kernel to make sure it's aligned. ?Plus wouldn't this also supply a more optimized solution?

Quoted 16 lines

Idea two:

Just let alloc_opal_dev kzalloc normally and do no alignment. It would then be up to the drivers to move the data from the buffer to a bounce buffer, that is aligned, in the send/recv functions before sending down to the controller.

Both are easy to implement but we wanted to see if anyone had other ideas or liked
one over the other.

_______________________________________________
Linux-nvme mailing list
Linux-nvme at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

#10 lore raw

PATCH v4 2/6 block: Add Sed-opal library

In reply to Scott Bauer
Quoted 6 lines · Scott Bauer

Just let alloc_opal_dev kzalloc normally and do no alignment. It would then be up to the drivers to move the data from the buffer to a bounce buffer, that is aligned, in the send/recv functions before sending down to the controller.

Both are easy to implement but we wanted to see if anyone had other ideas or liked one over the other.

Option two works, and there won't be any bounce buffering as kmalloc allocations are always naturally and dma boundary aligned.

Option three is to simply drop the alignment and let the block layer bounce buffer if needed.

Either two or three are fine with me.

#11 lore raw

PATCH v4 3/6 block: add ioctl interface for interfacing with Opal library

In reply to Scott Bauer
Signed-off-by Scott Bauer <scott.bauer at intel.com>
Signed-off-by Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 block/sed-ioctl.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)
 create mode 100644 block/sed-ioctl.c
block/sed-ioctl.c new file +164 -0
new file mode 100644
index 0000000..d17a84f
@@ -0,0 +1,164 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/sed.h>
+#include <linux/sed-opal.h>
+#include <asm/uaccess.h>
+
+static int sed_opal_save(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_lock_unlock lk_unlk;
+
+	if (copy_from_user(&lk_unlk, arg, sizeof(lk_unlk)))
+	    return -EFAULT;
+	return opal_save(sed_ctx, &lk_unlk);
+}
+
+static int sed_opal_lock_unlock(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_lock_unlock lk_unlk;
+
+	if (copy_from_user(&lk_unlk, arg, sizeof(lk_unlk)))
+		return -EFAULT;
+	return opal_lock_unlock(sed_ctx, &lk_unlk);
+}
+
+static int sed_opal_take_ownership(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_key opal_key;
+
+	if (copy_from_user(&opal_key, arg, sizeof(opal_key)))
+		return -EFAULT;
+	return opal_take_ownership(sed_ctx, &opal_key);
+}
+
+static int sed_opal_activate_lsp(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_key opal_key;
+
+	if (copy_from_user(&opal_key, arg, sizeof(opal_key)))
+		return -EFAULT;
+	return opal_activate_lsp(sed_ctx, &opal_key);
+}
+
+static int sed_opal_set_pw(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_new_pw opal_pw;
+	if (copy_from_user(&opal_pw, arg, sizeof(opal_pw)))
+		return -EFAULT;
+	return opal_set_new_pw(sed_ctx, &opal_pw);
+}
+
+static int sed_opal_activate_user(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_session_info session;
+	if (copy_from_user(&session, arg, sizeof(session)))
+		return -EFAULT;
+	return opal_activate_user(sed_ctx, &session);
+}
+
+static int sed_opal_reverttper(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_key opal_key;
+
+	if (copy_from_user(&opal_key, arg, sizeof(opal_key)))
+		return -EFAULT;
+	return opal_reverttper(sed_ctx, &opal_key);
+}
+
+static int sed_opal_setup_locking_range(struct sed_context *sed_ctx,
+					void __user *arg)
+{
+	struct opal_user_lr_setup lrs;
+	if (copy_from_user(&lrs, arg, sizeof(lrs)))
+		return -EFAULT;
+	return opal_setup_locking_range(sed_ctx, &lrs);
+}
+
+static int sed_opal_adduser_to_lr(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_lock_unlock lk_unlk;
+
+	if (copy_from_user(&lk_unlk, arg, sizeof(lk_unlk)))
+		return -EFAULT;
+	return opal_add_user_to_lr(sed_ctx, &lk_unlk);
+}
+
+static int sed_opal_do_mbr(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_mbr_data mbr;
+	if (copy_from_user(&mbr, arg, sizeof(mbr)))
+		return -EFAULT;
+	return opal_enable_disable_shadow_mbr(sed_ctx, &mbr);
+}
+
+static int sed_opal_erase_lr(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_session_info session;
+	if (copy_from_user(&session, arg, sizeof(session)))
+		return -EFAULT;
+	return opal_erase_locking_range(sed_ctx, &session);
+}
+
+static int sed_opal_secure_erase_lr(struct sed_context *sed_ctx, void __user *arg)
+{
+	struct opal_session_info session;
+	if (copy_from_user(&session, arg, sizeof(session)))
+		return -EFAULT;
+	return opal_secure_erase_locking_range(sed_ctx, &session);
+}
+
+int sed_ioctl(struct sed_context *sed_ctx, unsigned int cmd, unsigned long arg)
+{
+	void __user *ptr = (void __user *)arg;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	if (!sed_ctx->supported) {
+		pr_err("Not supported\n");
+		return -ENOTSUPP;
+	}
+
+	switch (cmd) {
+	case IOC_OPAL_SAVE:
+		return sed_opal_save(sed_ctx, ptr);
+	case IOC_OPAL_LOCK_UNLOCK:
+		return sed_opal_lock_unlock(sed_ctx, ptr);
+	case IOC_OPAL_TAKE_OWNERSHIP:
+		return sed_opal_take_ownership(sed_ctx, ptr);
+	case IOC_OPAL_ACTIVATE_LSP:
+		return sed_opal_activate_lsp(sed_ctx, ptr);
+	case IOC_OPAL_SET_PW:
+		return sed_opal_set_pw(sed_ctx, ptr);
+	case IOC_OPAL_ACTIVATE_USR:
+		return sed_opal_activate_user(sed_ctx, ptr);
+	case IOC_OPAL_REVERT_TPR:
+		return sed_opal_reverttper(sed_ctx, ptr);
+	case IOC_OPAL_LR_SETUP:
+		return sed_opal_setup_locking_range(sed_ctx, ptr);
+	case IOC_OPAL_ADD_USR_TO_LR:
+		return sed_opal_adduser_to_lr(sed_ctx, ptr);
+	case IOC_OPAL_ENABLE_DISABLE_MBR:
+		return sed_opal_do_mbr(sed_ctx, ptr);
+	case IOC_OPAL_ERASE_LR:
+		return sed_opal_erase_lr(sed_ctx, ptr);
+	case IOC_OPAL_SECURE_ERASE_LR:
+		return sed_opal_secure_erase_lr(sed_ctx, ptr);
+	}
+	return -ENOTTY;
+}
+EXPORT_SYMBOL_GPL(sed_ioctl);
Signature · 1 line
2.7.4
#12 lore raw

PATCH v4 3/6 block: add ioctl interface for interfacing with Opal library

Given that by now these are OPAL-family specific I'd just merge this file into sed-opal.c. That why all the ioctl implementation functions can become static in that file, and only sed_ioctl needs to be exported to the drivers.

#13 lore raw

PATCH v4 4/6 block: Add Opal Files to Makefile & add config option to Kconfig

In reply to Scott Bauer
Signed-off-by Scott Bauer <scott.bauer at intel.com>
Signed-off-by Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 block/Kconfig  | 6 ++++++
 block/Makefile | 1 +
 2 files changed, 7 insertions(+)
block/Kconfig +6 -0
index 8bf114a..45a7863 100644
@@ -147,6 +147,12 @@ config BLK_WBT_MQ
 	Multiqueue currently doesn't have support for IO scheduling,
 	enabling this option is recommended.
 
+config BLK_SED_OPAL
+        bool "Library for interfacing with Opal enabled SEDs"
+	default n
+	---help---
+	Builds library for interfacing with Opal enabled controllers.
+
 menu "Partition Types"
 
 source "block/partitions/Kconfig"
block/Makefile +1 -0
index a827f98..876c28d 100644
@@ -25,3 +25,4 @@ obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
 obj-$(CONFIG_BLK_MQ_PCI)	+= blk-mq-pci.o
 obj-$(CONFIG_BLK_DEV_ZONED)	+= blk-zoned.o
 obj-$(CONFIG_BLK_WBT)		+= blk-wbt.o
+obj-$(CONFIG_BLK_SED_OPAL)	+= sed-opal.o sed-ioctl.o
Signature · 1 line
2.7.4
#14 lore raw

PATCH v4 4/6 block: Add Opal Files to Makefile & add config option to Kconfig

block/Kconfig config BLK_WBT_MQ · line 155

Quoted 6 lines
block/Kconfig +6 -0
+config BLK_SED_OPAL
+        bool "Library for interfacing with Opal enabled SEDs"
+	default n
+	---help---
+	Builds library for interfacing with Opal enabled controllers.
+

Inconsistant whitespaces here, kust use tabs. The defauly n is the defaul, so it could be dropped. Maybe the help text could be expanded a bit, including explining what SED stands for (I know, but many potential users don't), and de-emphasis the library part.

E.g. something like

config BLK_SED_OPAL
bool "Support for OPAL Self Encrypting Drives" help
This optional enables support for Self Encrypting Drives using the TCG OPAL protocol family.

#15 lore raw

PATCH v4 5/6 nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls

In reply to Scott Bauer

This patch implements the necessary logic to unlock an Opal enabled device coming back from an S3.

The patch also implements the SED/Opal allocation necessary to support the opal ioctls.

Signed-off-by Scott Bauer <scott.bauer at intel.com>
---
 drivers/nvme/host/Kconfig |  7 +++++
 drivers/nvme/host/core.c  | 78 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/nvme.h  |  9 +++++-
 drivers/nvme/host/pci.c   |  4 +++
 4 files changed, 97 insertions(+), 1 deletion(-)
drivers/nvme/host/Kconfig +7 -0
index 90745a6..f492b00 100644
@@ -25,6 +25,13 @@ config BLK_DEV_NVME_SCSI
 	  emulation to provide stable device names for mount by id, like
 	  some OpenSuSE and SLES versions.
 
+config BLK_DEV_SED_OPAL
+       bool "Enable support for Opal Enabled NVMe Device"
+       depends on BLK_SED_OPAL
+       default n
+       ---help---
+       This enables support for an Opal enabled NVMe device.
+
 config NVME_FABRICS
 	tristate
 
drivers/nvme/host/core.c +78 -0

108 lines not on this page · raw message

drivers/nvme/host/nvme.h +8 -1
index bd53214..1f18c53 100644
@@ -19,6 +19,7 @@
 #include <linux/kref.h>
 #include <linux/blk-mq.h>
 #include <linux/lightnvm.h>
+#include <linux/sed.h>
 
 enum {
 	/*
@@ -188,6 +189,10 @@ struct nvme_ns {
 
 	u64 mode_select_num_blocks;
 	u32 mode_select_block_len;
+
+#ifdef CONFIG_BLK_SED_OPAL
+	struct sed_context sed_ctx;
+#endif
 };
 
 struct nvme_ctrl_ops {
@@ -256,7 +261,8 @@ static inline int nvme_error_status(u16 status)
 
 static inline bool nvme_req_needs_retry(struct request *req, u16 status)
 {
-	return !(status & NVME_SC_DNR || blk_noretry_request(req)) &&
+	return !(status & NVME_SC_DNR || status & NVME_SC_ACCESS_DENIED ||
+		 blk_noretry_request(req)) &&
 		(jiffies - req->start_time) < req->timeout &&
 		req->retries < nvme_max_retries;
 }
@@ -275,6 +281,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl);
 
 void nvme_queue_scan(struct nvme_ctrl *ctrl);
 void nvme_remove_namespaces(struct nvme_ctrl *ctrl);
+void nvme_unlock_from_suspend(struct nvme_ctrl *ctrl);
 
 #define NVME_NR_AERS	1
 void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
drivers/nvme/host/pci.c +4 -0
index 3d21a15..dbf7818 100644
@@ -1764,6 +1764,7 @@ static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status)
 static void nvme_reset_work(struct work_struct *work)
 {
 	struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
+	bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL);
 	int result = -ENODEV;
 
 	if (WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING))
@@ -1796,6 +1797,9 @@ static void nvme_reset_work(struct work_struct *work)
 	if (result)
 		goto out;
 
+	if (was_suspend)
+		nvme_unlock_from_suspend(&dev->ctrl);
+
 	result = nvme_setup_io_queues(dev);
 	if (result)
 		goto out;
Signature · 1 line
2.7.4
#16 lore raw

PATCH v4 5/6 nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls

drivers/nvme/host/Kconfig config BLK_DEV_NVME_SCSI · line 33

Quoted 6 lines
drivers/nvme/host/Kconfig +6 -0
+config BLK_DEV_SED_OPAL
+       bool "Enable support for Opal Enabled NVMe Device"
+       depends on BLK_SED_OPAL
+       default n
+       ---help---
+       This enables support for an Opal enabled NVMe device.

I'd like to hear an opinion from Keith as well, but I personally would drop this confif option and just enable NVMe OPAL support if core block OPAL is supported.

drivers/nvme/host/core.c static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, · line 771

Quoted 1 line
drivers/nvme/host/core.c +1 -0
+	struct nvme_command cmd = { 0 };

This creates a warning for me:

../drivers/nvme/host/core.c: In function ?nvme_sec_submit?:
../drivers/nvme/host/core.c:771:9: warning: missing braces around initializer [-Wmissing-braces]

  struct nvme_command cmd = { 0 };
         ^

../drivers/nvme/host/core.c:771:9: warning: (near initialization for ?cmd.<anonymous>?) [-Wmissing-braces]

maybe just follow the other examples of nvme_command initializations in the file.

drivers/nvme/host/core.c static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, · line 779

Quoted 8 lines
drivers/nvme/host/core.c +8 -0
+	struct nvme_ns *ns = NULL;
+
+	if (send)
+		cmd.common.opcode = nvme_admin_security_send;
+	else
+		cmd.common.opcode = nvme_admin_security_recv;
+	ns = container_of(ctx, struct nvme_ns, sed_ctx);
+	cmd.common.nsid = cpu_to_le32(ns->ns_id);

Until we support the configurable namespace locking extension we should have the sed_ctx in the nvme_ctrl structure, and not be tried to a namespace here. I hope to get some concensus out of the working group about which value to pass exactly soon.

drivers/nvme/host/core.c static int nvme_ioctl(struct block_device *bdev, fmode_t mode, · line 814

Quoted 4 lines
drivers/nvme/host/core.c +4 -0
+#ifdef CONFIG_BLK_DEV_SED_OPAL
+		if (is_sed_ioctl(cmd))
+			return sed_ioctl(&ns->sed_ctx, cmd, arg);
+#endif

To avoid these ifdefs I would suggest to provide an always false inline version of is_sed_ioctl and a no-op inline of sed_ioctl in the header.

#17 lore raw

PATCH v4 5/6 nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls

Quoted 10 lines · Christoph Hellwig

drivers/nvme/host/Kconfig config BLK_DEV_NVME_SCSI · line 33

Quoted 6 lines
drivers/nvme/host/Kconfig +6 -0
+config BLK_DEV_SED_OPAL
+       bool "Enable support for Opal Enabled NVMe Device"
+       depends on BLK_SED_OPAL
+       default n
+       ---help---
+       This enables support for an Opal enabled NVMe device.

I'd like to hear an opinion from Keith as well, but I personally would drop this confif option and just enable NVMe OPAL support if core block OPAL is supported.

Yes, I'd agree to just dropping this and tying it to BLK_SED_OPAL rather than having this longer chain of config dependencies.

Quoted 8 lines

drivers/nvme/host/core.c static int nvme_ioctl(struct block_device *bdev, fmode_t mode, · line 814

Quoted 4 lines
drivers/nvme/host/core.c +4 -0
+#ifdef CONFIG_BLK_DEV_SED_OPAL
+		if (is_sed_ioctl(cmd))
+			return sed_ioctl(&ns->sed_ctx, cmd, arg);
+#endif

To avoid these ifdefs I would suggest to provide an always false inline version of is_sed_ioctl and a no-op inline of sed_ioctl in the header.

Yeah, see section 20 of the Linux kernel coding-style in Documentation/process/coding-style.rst on the recommended way of conditional code depending on config options.

#18 lore raw

PATCH v4 5/6 nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls

In reply to Christoph Hellwig
Quoted 7 lines · Christoph Hellwig

drivers/nvme/host/core.c static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, · line 779

Quoted 2 lines
drivers/nvme/host/core.c +2 -0
+	ns = container_of(ctx, struct nvme_ns, sed_ctx);
+	cmd.common.nsid = cpu_to_le32(ns->ns_id);

Until we support the configurable namespace locking extension we should have the sed_ctx in the nvme_ctrl structure, and not be tried to a namespace here. I hope to get some concensus out of the working group about which value to pass exactly soon.

No progress on that yet. What do you think about just passing in the nn value from the Identify Controller structure in here for now, as that should always be a valid nsid?

#19 lore raw

PATCH v4 5/6 nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls

In reply to Scott Bauer

[snip]

Quoted 8 lines
drivers/nvme/host/core.c +8 -0
+static int nvme_opal_initialize(struct nvme_ns *ns)
+{
+
+#ifdef CONFIG_BLK_DEV_SED_OPAL
+	/* Opal dev has already been allocated for this controller */
+	if (ns->sed_ctx.dev)
+		return 0;
+

drivers/nvme/host/core.c static const struct pr_ops nvme_pr_ops = { · line 1099

Quoted 10 lines
drivers/nvme/host/core.c +10 -0
+	ns->sed_ctx.dev = alloc_opal_dev(ns->ctrl->admin_q);
+	if (!ns->sed_ctx.dev)
+		return -ENOMEM;
+	ns->sed_ctx.send_recv = &nvme_sec_submit;
+
+	/* In the future when we have to determine whether or not we're in
+	 * Multi-LR Mult-NS mode or Single-LR Multi-NS mode we'll
+	 * pass pointers into is_opal_supported
+	 */
+	if (is_opal_supported(&ns->sed_ctx, NULL, NULL) != 1) {

I don't know if it's helpful to have is_opal_supported able to return errno if we're just going to ignore the error. Maybe change that to check_opal_support, which has less true/false connotation, and can return 0 for success and positive if we need it for any unknowns.

Then do:

        if (check_opal_support(..) < 0)
                cleanup...

drivers/nvme/host/core.c static const struct pr_ops nvme_pr_ops = { · line 1102

Quoted 3 lines
drivers/nvme/host/core.c +3 -0
+		dev_warn(ns->ctrl->device, "Opal is not supported\n");
+		kfree(ns->sed_ctx.dev);
+		ns->sed_ctx.dev = NULL;

I might get some pushback since it's only two lines, but I'd say move the two lines above into a free_opal_dev to match the alloc_opal_dev. Also if there's any more de-initialization we need to do in the future (opal buffers, etc), then the free_opal_dev() will be ready for it.

#20 lore raw

PATCH v4 6/6 Maintainers: Add maintainer info for SED/Opal library

In reply to Scott Bauer
Signed-off-by Scott Bauer <scott.bauer at intel.com>
---
 MAINTAINERS | 11 +++++++++++
 1 file changed, 11 insertions(+)
MAINTAINERS +11 -0
index cfff2c9..fe936c1 100644
@@ -11065,6 +11065,17 @@ L:	linux-mmc at vger.kernel.org
 S:	Maintained
 F:	drivers/mmc/host/sdhci-spear.c
 
+SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER
+M:	Scott Bauer <scott.bauer at intel.com>
+M:	Jonathan Derrick <jonathan.derrick at intel.com>
+M:	Rafael Antognolli <rafael.antognolli at intel.com>
+L:	linux-nvme at lists.infradead.org
+S:	Supported
+F:	block/sed*
+F:      block/opal_proto.h
+F:	include/linux/sed*
+F:	include/uapi/linux/sed*
+
 SECURITY SUBSYSTEM
 M:	James Morris <james.l.morris at oracle.com>
 M:	"Serge E. Hallyn" <serge at hallyn.com>
Signature · 1 line
2.7.4
#21 lore raw

v4 cover SED OPAL Library

In reply to Scott Bauer

Apparently I can't insert in emacs to save my life, here is 1->4:

Changes from v3->v4:
1) Moved back from lib/ to block/
2) Files are hidden behind a CONFIG_ must be explicitly enabled in menuconfig
3) NVMe support is hidden behind a CONFIG_ that depends on the above CONFIG
4) Fixed Issues pointed out by Christoph and Jon in previous v3 review. 4a) Tried to aggregate UAPI/In kernel structures/On-the-wire structures into seperate headers.
4b) Renamed block/sed.c to block/sed-ioctl.c...
There was discussion around trying to remove the sed to opal inderection. The code still has some inderection, but it's specifically for doing copy_from_user before going into the opal core. I want to keep the sed-opal.c a "Library" where it doesn't have to do any copy_from_user stuff. This way, when we have in-kernel users they don't have to do gross get_fs(), set_fs() calls.

Quoted 86 lines · Scott Bauer

5) Removed dependency on the file struct. We also do not add a new entry into the block structures. We enter through the drivers block ioctl handler, which will test if it's a sed ioctl. If it is, we pass a previously allocated sed_context structure, cmd and arg, into the sed-ioctl.c which will dispatch it into the opal core.

6) The NVMe patch changed a bit:
The sed_context is now per-namespace for two reasons. First The spec says we have to send a namespace ID for the security commands, even if TCG spec currently ignores them. Second, there is public review for a modification to the spec where the namespace ID will be vitally important:
https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_Storage_Feature_Set_Namespaces_phase_1b_v1_00_r1_19_public-review.pdf

7) To facilitate the above public review changes, and potentially future changes the Opal core now exposes a new method which in-kernel users can call:
is_opal_supported().
The method is not exposed to userland, but will be used for drivers who wish to see if their controller supports Opal. The function can save the entire disovery0 payload which the driver can then parse to find out more info.

8) The NVMe driver now calls the new function above to see if the controller supports opal. If it does not we free the structures. The current implementation does not save the discovery0 payload. When the public review spec is finalized and someone ships devices with multiple namespace multiple LR support they can modify the code to save the payload and parse it to figure out what NS/LR mode they're going to be operating in.

===============================================================================
This Patch series implements a large portion of the Opal protocol for self encrypting devices. The driver has the capability of storing a locking range's password. The password can then be replayed during a resume from previous suspend-to-RAM.

The driver also supports logic to bring the device out of a factory default-inactive state into a functional Opal state.

The following logic is supported in order to bring the tper into a working state:

1) Taking Ownership of the drive (Setting the Admin CPIN).
2) Activating the Locking SP (In Single User Mode or Normal Mode).
3) Setting up Locking Ranges (Single User or Normal Mode).
4) Adding users to Locking Ranges (Normal Mode Only).
5) Locking or Unlocking Locking Ranges (Single User Mode or Normal Mode).
6) Reverting the TPer (Restore to factory default).
7) Setting LR/User passwords (Single User Mode or Normal Mode).
8) Enabling/disabling Shadow MBR.
9) Enabling Users in the LockingSP (Normal Mode Only).
10) Saving Password for resume from suspend.
11) Erase and Secure erasing locking ranges.

Scott Bauer (6):
Include: Uapi: Add user ABI for Sed/Opal
block: Add Sed-opal library
block: add ioctl interface for interfacing with Opal library
block: Add Opal Files to Makefile & add config option to Kconfig
nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls
Maintainers: Add maintainer info for SED/Opal library

 MAINTAINERS                   |   11 +
 block/Kconfig                 |    6 +
 block/Makefile                |    1 +
 block/opal_proto.h            |  588 ++++++++++
 block/sed-ioctl.c             |  164 +++
 block/sed-opal.c              | 2392 +++++++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/Kconfig     |    7 +
 drivers/nvme/host/core.c      |   78 ++
 drivers/nvme/host/nvme.h      |    9 +-
 drivers/nvme/host/pci.c       |    4 +
 include/linux/sed-opal.h      |   59 +
 include/linux/sed.h           |   80 ++
 include/uapi/linux/sed-opal.h |  107 ++
 13 files changed, 3505 insertions(+), 1 deletion(-)
 create mode 100644 block/opal_proto.h
 create mode 100644 block/sed-ioctl.c
 create mode 100644 block/sed-opal.c
 create mode 100644 include/linux/sed-opal.h
 create mode 100644 include/linux/sed.h
 create mode 100644 include/uapi/linux/sed-opal.h

_______________________________________________
Linux-nvme mailing list
Linux-nvme at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

#22 lore raw

v4 cover SED OPAL Library

In reply to Scott Bauer

Hi Scott,

do you have a pointer to the userspace using this ioctls? Over the holidays I finally managed to put a test system for my collection of m.2 key M cards together, so I should be able to test the code, which I'd definitively like to do before ACKing. More comments on the code itself will follow soon.

#23 lore raw

v4 cover SED OPAL Library

Quoted 7 lines · Christoph Hellwig

Hi Scott,

do you have a pointer to the userspace using this ioctls? Over the holidays I finally managed to put a test system for my collection of m.2 key M cards together, so I should be able to test the code, which I'd definitively like to do before ACKing. More comments on the code itself will follow soon.

We've enabled the supporte into nvmecli you can pull my branch here:
https://github.com/ScottyBauer/nvme-cli/tree/sed-nvme

Here are some shellscripts I use for testing -- also a HOW-TO-USE in there.
https://github.com/ScottyBauer/nvme-cli-sed-sh

I may have regressed some Single user mode stuff in the library. I was under the impression one could setup multiple Locking ranges under Single User Mode. But I can only get one setup without my drive complaining. It doesn't work in sed-util either, so I have to go read the SUM spec again and see if that is actually a use-case that's possible or if I was dreaming this test up. I swore I had this working on previous iterations, but I could be wrong. Normal mode seems to work fine, though.

#24 lore raw

v4 cover SED OPAL Library

Quoted 10 lines · Scott Bauer
Quoted 7 lines · Christoph Hellwig

Hi Scott,

do you have a pointer to the userspace using this ioctls? Over the holidays I finally managed to put a test system for my collection of m.2 key M cards together, so I should be able to test the code, which I'd definitively like to do before ACKing. More comments on the code itself will follow soon.

Quoted 2 lines

We've enabled the supporte into nvmecli you can pull my branch here:
https://github.com/ScottyBauer/nvme-cli/tree/sed-nvme

Can we move this out of nvme-cli into a separate tool? I'd like to use your code to support ATA disk as well. (and that should give us SCSI for free, but I don't have access to a SCSI disk with OPAL support)

#25 lore raw

v4 cover SED OPAL Library

Quoted 11 lines · Christoph Hellwig
Quoted 10 lines · Scott Bauer
Quoted 7 lines · Christoph Hellwig

Hi Scott,

do you have a pointer to the userspace using this ioctls? Over the holidays I finally managed to put a test system for my collection of m.2 key M cards together, so I should be able to test the code, which I'd definitively like to do before ACKing. More comments on the code itself will follow soon.

Quoted 7 lines
Quoted 2 lines

We've enabled the supporte into nvmecli you can pull my branch here:
https://github.com/ScottyBauer/nvme-cli/tree/sed-nvme

Can we move this out of nvme-cli into a separate tool? I'd like to use your code to support ATA disk as well. (and that should give us SCSI for free, but I don't have access to a SCSI disk with OPAL support)

I don't have an issue with that. It may take a week or two we'll have to have lawyers and crap OK the new program, not sure how long that takes.

#26 lore raw

v4 cover SED OPAL Library

Quoted 2 lines · Scott Bauer

I don't have an issue with that. It may take a week or two we'll have to have lawyers and crap OK the new program, not sure how long that takes.

If it makes your life easier I can just take your existing code and move it to a new tools once we're ready to merge the kernel code.

#27 lore raw

v4 cover SED OPAL Library

Quoted 6 lines · Christoph Hellwig
Quoted 2 lines · Scott Bauer

I don't have an issue with that. It may take a week or two we'll have to have lawyers and crap OK the new program, not sure how long that takes.

If it makes your life easier I can just take your existing code and move it to a new tools once we're ready to merge the kernel code.

I think that will be the best for us. I've ripped it out of nvme-cli and attempted to make a stand alone utility. I blatantly stole some functions and files from nvme-cli to get it to work but it isn't dependent on nvme-cli anymore.

I've temporarily pushed it here:
https://github.com/ScottyBauer/sed-opal-temp

I don't know anything about licensing but it's dependent on some GPL2 code in argconfig.c so I assume it will have to be under that one as well.

I'd prefer to maintain it off my Personal Github account so if we want to host it on infradead that would be good or if we want to create another repo on github that's fine too (like what nvme-cli is hosted on).