summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/opal_proto.h1
-rw-r--r--block/sed-opal.c99
-rw-r--r--include/linux/sed-opal.h1
-rw-r--r--include/uapi/linux/sed-opal.h14
4 files changed, 115 insertions, 0 deletions
diff --git a/block/opal_proto.h b/block/opal_proto.h
index 3ccee5977c10..d138785b8198 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -155,6 +155,7 @@ enum opal_method {
OPAL_AUTHENTICATE,
OPAL_RANDOM,
OPAL_ERASE,
+ OPAL_REACTIVATE,
};
enum opal_token {
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 83bee47aa29f..5d06f5f433bf 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -220,6 +220,8 @@ static const u8 opalmethod[][OPAL_METHOD_LENGTH] = {
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },
[OPAL_ERASE] =
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 },
+ [OPAL_REACTIVATE] =
+ { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x01 },
};
static int end_opal_session_error(struct opal_dev *dev);
@@ -2287,6 +2289,74 @@ static int activate_lsp(struct opal_dev *dev, void *data)
return finalize_and_send(dev, parse_and_check_status);
}
+static int reactivate_lsp(struct opal_dev *dev, void *data)
+{
+ struct opal_lr_react *opal_react = data;
+ u8 user_lr[OPAL_UID_LENGTH];
+ int err, i;
+
+ err = cmd_start(dev, opaluid[OPAL_THISSP_UID],
+ opalmethod[OPAL_REACTIVATE]);
+
+ if (err) {
+ pr_debug("Error building Reactivate LockingSP command.\n");
+ return err;
+ }
+
+ /*
+ * If neither 'entire_table' nor 'num_lrs' is set, the device
+ * gets reactivated with SUM disabled. Only Admin1PIN will change
+ * if set.
+ */
+ if (opal_react->entire_table) {
+ /* Entire Locking table (all locking ranges) will be put in SUM. */
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u64(&err, dev, OPAL_SUM_SET_LIST);
+ add_token_bytestring(&err, dev, opaluid[OPAL_LOCKING_TABLE], OPAL_UID_LENGTH);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+ } else if (opal_react->num_lrs) {
+ /* Subset of Locking table (selected locking range(s)) to be put in SUM */
+ err = build_locking_range(user_lr, sizeof(user_lr),
+ opal_react->lr[0]);
+ if (err)
+ return err;
+
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u64(&err, dev, OPAL_SUM_SET_LIST);
+
+ add_token_u8(&err, dev, OPAL_STARTLIST);
+ add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
+ for (i = 1; i < opal_react->num_lrs; i++) {
+ user_lr[7] = opal_react->lr[i];
+ add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
+ }
+ add_token_u8(&err, dev, OPAL_ENDLIST);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+ }
+
+ /* Skipping the rangle policy parameter is same as setting its value to zero */
+ if (opal_react->range_policy && (opal_react->num_lrs || opal_react->entire_table)) {
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u64(&err, dev, OPAL_SUM_RANGE_POLICY);
+ add_token_u8(&err, dev, 1);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+ }
+
+ /*
+ * Optional parameter. If set, it changes the Admin1 PIN even when SUM
+ * is being disabled.
+ */
+ if (opal_react->new_admin_key.key_len) {
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u64(&err, dev, OPAL_SUM_ADMIN1_PIN);
+ add_token_bytestring(&err, dev, opal_react->new_admin_key.key,
+ opal_react->new_admin_key.key_len);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+ }
+
+ return finalize_and_send(dev, parse_and_check_status);
+}
+
/* Determine if we're in the Manufactured Inactive or Active state */
static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
{
@@ -2957,6 +3027,32 @@ static int opal_activate_lsp(struct opal_dev *dev,
return ret;
}
+static int opal_reactivate_lsp(struct opal_dev *dev,
+ struct opal_lr_react *opal_lr_react)
+{
+ const struct opal_step active_steps[] = {
+ { start_admin1LSP_opal_session, &opal_lr_react->key },
+ { reactivate_lsp, opal_lr_react },
+ /* No end_opal_session. The controller terminates the session */
+ };
+ int ret;
+
+ /* use either 'entire_table' parameter or set of locking ranges */
+ if (opal_lr_react->num_lrs > OPAL_MAX_LRS ||
+ (opal_lr_react->num_lrs && opal_lr_react->entire_table))
+ return -EINVAL;
+
+ ret = opal_get_key(dev, &opal_lr_react->key);
+ if (ret)
+ return ret;
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, active_steps, ARRAY_SIZE(active_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_setup_locking_range(struct opal_dev *dev,
struct opal_user_lr_setup *opal_lrs)
{
@@ -3315,6 +3411,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_SET_SID_PW:
ret = opal_set_new_sid_pw(dev, p);
break;
+ case IOC_OPAL_REACTIVATE_LSP:
+ ret = opal_reactivate_lsp(dev, p);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 80f33a93f944..2ae5e6b0ac21 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -53,6 +53,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_DISCOVERY:
case IOC_OPAL_REVERT_LSP:
case IOC_OPAL_SET_SID_PW:
+ case IOC_OPAL_REACTIVATE_LSP:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 9025dd5a4f0f..d03e590b6501 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -74,6 +74,19 @@ struct opal_lr_act {
__u8 align[2]; /* Align to 8 byte boundary */
};
+struct opal_lr_react {
+ struct opal_key key;
+ struct opal_key new_admin_key; /* Set new Admin1 PIN if key_len is > 0 */
+ __u8 num_lrs; /*
+ * Configure selected ranges (from lr[]) in SUM.
+ * If num_lrs > 0 the 'entire_table' must be 0
+ */
+ __u8 lr[OPAL_MAX_LRS];
+ __u8 range_policy; /* Set RangeStartRangeLengthPolicy parameter */
+ __u8 entire_table; /* Set all locking objects in SUM */
+ __u8 align[4]; /* Align to 8 byte boundary */
+};
+
struct opal_session_info {
__u32 sum;
__u32 who;
@@ -216,5 +229,6 @@ struct opal_revert_lsp {
#define IOC_OPAL_DISCOVERY _IOW('p', 239, struct opal_discovery)
#define IOC_OPAL_REVERT_LSP _IOW('p', 240, struct opal_revert_lsp)
#define IOC_OPAL_SET_SID_PW _IOW('p', 241, struct opal_new_pw)
+#define IOC_OPAL_REACTIVATE_LSP _IOW('p', 242, struct opal_lr_react)
#endif /* _UAPI_SED_OPAL_H */