diff mbox series

block: sed-opal: Implement RevertSP IOCTL

Message ID 20200413231121.8207-1-revanth.rajashekar@intel.com (mailing list archive)
State New, archived
Headers show
Series block: sed-opal: Implement RevertSP IOCTL | expand

Commit Message

Revanth Rajashekar April 13, 2020, 11:11 p.m. UTC
This patch implements an ioctl for Reverting SP functionality.
RevertSP fucntionality can be used under scenarios where user
data shall not be erased after TPer reverting.

The pacth adds a new optional parameter 'keep_glbl_rn_key' to opal_key struct.
If the optional parameter, keep_glbl_rn_key(KeepGlobalRangeKey),is provided
with a value of TRUE, then the media encryption key associated with
Locking_GlobalRange is preserved. Else, all user data is cryptographically
erased.

Test Scenarios:
RevertSP(keep_glbl_rn_key = true)  + RevertTper => Data is retained
RevertSP(keep_glbl_rn_key = false) + RevertTper => Data is erased
RevertSP(no keep_glbl_rn_key)      + RevertTper => Data is erased

Reference:
1. Section 5.1.3 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage-Opal_SSC_v2.01_rev1.00.pdf
2. Section 3.2.12.2 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage_Opal_SSC_Application_Note_1-00_1-00-Final.pdf

Signed-off-by: Revanth Rajashekar <revanth.rajashekar@intel.com>
---
 block/opal_proto.h            |  6 ++++
 block/sed-opal.c              | 52 +++++++++++++++++++++++++++++++----
 include/linux/sed-opal.h      |  1 +
 include/uapi/linux/sed-opal.h |  4 ++-
 4 files changed, 57 insertions(+), 6 deletions(-)

--
2.17.1

Comments

Jon Derrick April 14, 2020, 4:14 p.m. UTC | #1
Hi Revanth,


On Mon, 2020-04-13 at 17:11 -0600, Revanth Rajashekar wrote:
> This patch implements an ioctl for Reverting SP functionality.
> RevertSP fucntionality
*functionality

> can be used under scenarios where user
> data shall not be erased after TPer reverting.
> 
> The pacth
*patch

> adds a new optional parameter 'keep_glbl_rn_key' to opal_key struct.
> If the optional parameter,
> keep_glbl_rn_key(KeepGlobalRangeKey),is provided
space after comma

> with a value of TRUE, then the media encryption key associated with
> Locking_GlobalRange is preserved. Else, all user data is cryptographically
> erased.
> 
> Test Scenarios:
> RevertSP(keep_glbl_rn_key = true)  + RevertTper => Data is retained
> RevertSP(keep_glbl_rn_key = false) + RevertTper => Data is erased
> RevertSP(no keep_glbl_rn_key)      + RevertTper => Data is erased
> 
> Reference:
> 1. Section 5.1.3 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage-Opal_SSC_v2.01_rev1.00.pdf
> 2. Section 3.2.12.2 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage_Opal_SSC_Application_Note_1-00_1-00-Final.pdf
> 
> Signed-off-by: Revanth Rajashekar <revanth.rajashekar@intel.com>
> ---
>  block/opal_proto.h            |  6 ++++
>  block/sed-opal.c              | 52 +++++++++++++++++++++++++++++++----
>  include/linux/sed-opal.h      |  1 +
>  include/uapi/linux/sed-opal.h |  4 ++-
>  4 files changed, 57 insertions(+), 6 deletions(-)
> 
> diff --git a/block/opal_proto.h b/block/opal_proto.h
> index b486b3ec7dc4..8c6faa418ab4 100644
> --- a/block/opal_proto.h
> +++ b/block/opal_proto.h
> @@ -140,6 +140,12 @@ enum opal_method {
>  	OPAL_ERASE,
>  };
> 
> +enum opal_revert_method {
> +	OPAL_REVERT_TPER,
> +	OPAL_REVERT_PSID,
> +	OPAL_REVERT_SP,
> +};
> +
>  enum opal_token {
>  	/* Boolean */
>  	OPAL_TRUE = 0x01,
> diff --git a/block/sed-opal.c b/block/sed-opal.c
> index daafadbb88ca..1939df83c45e 100644
> --- a/block/sed-opal.c
> +++ b/block/sed-opal.c
> @@ -1552,6 +1552,28 @@ static int revert_tper(struct opal_dev *dev, void *data)
>  	return finalize_and_send(dev, parse_and_check_status);
>  }
> 
> +static int revert_sp(struct opal_dev *dev, void *data)
> +{
> +	int err;
> +	struct opal_key *key = data;
> +
> +	err = cmd_start(dev, opaluid[OPAL_THISSP_UID],
> +			opalmethod[OPAL_REVERTSP]);
> +
> +	add_token_u8(&err, dev, OPAL_STARTNAME);
> +	add_token_u64(&err, dev, OPAL_SUM_SET_LIST);
> +
> +	/*
> +	 * If KeepGlobalRangeKey is true, then the media encryption key
> +	 * associated with Locking_GlobalRange is preserved.
> +	 * If not true, then all user data is cryptographically erased.
> +	 */
> +	add_token_u8(&err, dev, key->keep_glbl_rn_key ? OPAL_TRUE : OPAL_FALSE);
> +	add_token_u8(&err, dev, OPAL_ENDNAME);
> +
> +	return finalize_and_send(dev, parse_and_check_status);
> +}
> +
>  static int internal_activate_user(struct opal_dev *dev, void *data)
>  {
>  	struct opal_session_info *session = data;
> @@ -2327,7 +2349,8 @@ static int opal_add_user_to_lr(struct opal_dev *dev,
>  	return ret;
>  }
> 
> -static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psid)
> +static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal,
> +			   enum opal_revert_method revert_type)
>  {
>  	/* controller will terminate session */
>  	const struct opal_step revert_steps[] = {
> @@ -2338,17 +2361,33 @@ static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psi
>  		{ start_PSID_opal_session, opal },
>  		{ revert_tper, }
>  	};
> +	const struct opal_step revertsp_steps[] = {
> +		{ start_admin1LSP_opal_session, opal },
> +		{ revert_sp, opal }
> +	};
> 
>  	int ret;
> 
>  	mutex_lock(&dev->dev_lock);
>  	setup_opal_dev(dev);
> -	if (psid)
> +	switch (revert_type) {
> +	case OPAL_REVERT_PSID:
>  		ret = execute_steps(dev, psid_revert_steps,
>  				    ARRAY_SIZE(psid_revert_steps));
> -	else
> +		break;
> +	case OPAL_REVERT_TPER:
>  		ret = execute_steps(dev, revert_steps,
>  				    ARRAY_SIZE(revert_steps));
> +		break;
> +	case OPAL_REVERT_SP:
> +		ret = execute_steps(dev, revertsp_steps,
> +				    ARRAY_SIZE(revertsp_steps));
> +		break;
> +	default:
> +		pr_debug("Invalid revert type\n");
> +		ret = -EINVAL;
> +		break;
> +	}
>  	mutex_unlock(&dev->dev_lock);
> 
>  	/*
> @@ -2656,7 +2695,7 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
>  		ret = opal_activate_user(dev, p);
>  		break;
>  	case IOC_OPAL_REVERT_TPR:
> -		ret = opal_reverttper(dev, p, false);
> +		ret = opal_reverttper(dev, p, OPAL_REVERT_TPER);
>  		break;
>  	case IOC_OPAL_LR_SETUP:
>  		ret = opal_setup_locking_range(dev, p);
> @@ -2680,11 +2719,14 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
>  		ret = opal_secure_erase_locking_range(dev, p);
>  		break;
>  	case IOC_OPAL_PSID_REVERT_TPR:
> -		ret = opal_reverttper(dev, p, true);
> +		ret = opal_reverttper(dev, p, OPAL_REVERT_PSID);
>  		break;
>  	case IOC_OPAL_GENERIC_TABLE_RW:
>  		ret = opal_generic_read_write_table(dev, p);
>  		break;
> +	case IOC_OPAL_REVERT_SP:
> +		ret = opal_reverttper(dev, p, OPAL_REVERT_SP);
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
> index 1ac0d712a9c3..85ad7bb7da41 100644
> --- a/include/linux/sed-opal.h
> +++ b/include/linux/sed-opal.h
> @@ -43,6 +43,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
>  	case IOC_OPAL_MBR_DONE:
>  	case IOC_OPAL_WRITE_SHADOW_MBR:
>  	case IOC_OPAL_GENERIC_TABLE_RW:
> +	case IOC_OPAL_REVERT_SP:
>  		return true;
>  	}
>  	return false;
> diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
> index 6f5af1a84213..ac59fbc1d06b 100644
> --- a/include/uapi/linux/sed-opal.h
> +++ b/include/uapi/linux/sed-opal.h
> @@ -47,7 +47,8 @@ enum opal_lock_state {
>  struct opal_key {
>  	__u8 lr;
>  	__u8 key_len;
> -	__u8 __align[6];
> +	__u8 keep_glbl_rn_key;
> +	__u8 __align[5];
> 
This is mostly fine, except that we're changing the definition of bits
in an existing ioctl structure. We're not using those bits for any
other ioctl so I wouldn't expect issues.

I think instead you should take 4 bytes of __align and change it to a
__u32 'flags', and #define a bitwise flag for your purposes. Eg,
similar to the flags param in opal_read_write_table.

Please update the commit message if you do that.

>  	__u8 key[OPAL_KEY_MAX];
>  };
> 
> @@ -148,5 +149,6 @@ struct opal_read_write_table {
>  #define IOC_OPAL_MBR_DONE           _IOW('p', 233, struct opal_mbr_done)
>  #define IOC_OPAL_WRITE_SHADOW_MBR   _IOW('p', 234, struct opal_shadow_mbr)
>  #define IOC_OPAL_GENERIC_TABLE_RW   _IOW('p', 235, struct opal_read_write_table)
> +#define IOC_OPAL_REVERT_SP          _IOW('p', 236, struct opal_key)
> 
>  #endif /* _UAPI_SED_OPAL_H */
> --
> 2.17.1
>
Revanth Rajashekar April 14, 2020, 4:33 p.m. UTC | #2
Hi Jon,

Thanks for the feedback.

On 4/14/2020 10:14 AM, Derrick, Jonathan wrote:
> Hi Revanth,
>
>
> On Mon, 2020-04-13 at 17:11 -0600, Revanth Rajashekar wrote:
>> This patch implements an ioctl for Reverting SP functionality.
>> RevertSP fucntionality
> *functionality
Will fix it.
>
>> can be used under scenarios where user
>> data shall not be erased after TPer reverting.
>>
>> The pacth
> *patch
Will fix it.
>
>> adds a new optional parameter 'keep_glbl_rn_key' to opal_key struct.
>> If the optional parameter,
>> keep_glbl_rn_key(KeepGlobalRangeKey),is provided
> space after comma
Will fix it.
>
>> with a value of TRUE, then the media encryption key associated with
>> Locking_GlobalRange is preserved. Else, all user data is cryptographically
>> erased.
>>
>> Test Scenarios:
>> RevertSP(keep_glbl_rn_key = true)  + RevertTper => Data is retained
>> RevertSP(keep_glbl_rn_key = false) + RevertTper => Data is erased
>> RevertSP(no keep_glbl_rn_key)      + RevertTper => Data is erased
>>
>> Reference:
>> 1. Section 5.1.3 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage-Opal_SSC_v2.01_rev1.00.pdf
>> 2. Section 3.2.12.2 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage_Opal_SSC_Application_Note_1-00_1-00-Final.pdf
>>
>> Signed-off-by: Revanth Rajashekar <revanth.rajashekar@intel.com>
>> ---
>>  block/opal_proto.h            |  6 ++++
>>  block/sed-opal.c              | 52 +++++++++++++++++++++++++++++++----
>>  include/linux/sed-opal.h      |  1 +
>>  include/uapi/linux/sed-opal.h |  4 ++-
>>  4 files changed, 57 insertions(+), 6 deletions(-)
>>
>> diff --git a/block/opal_proto.h b/block/opal_proto.h
>> index b486b3ec7dc4..8c6faa418ab4 100644
>> --- a/block/opal_proto.h
>> +++ b/block/opal_proto.h
>> @@ -140,6 +140,12 @@ enum opal_method {
>>  	OPAL_ERASE,
>>  };
>>
>> +enum opal_revert_method {
>> +	OPAL_REVERT_TPER,
>> +	OPAL_REVERT_PSID,
>> +	OPAL_REVERT_SP,
>> +};
>> +
>>  enum opal_token {
>>  	/* Boolean */
>>  	OPAL_TRUE = 0x01,
>> diff --git a/block/sed-opal.c b/block/sed-opal.c
>> index daafadbb88ca..1939df83c45e 100644
>> --- a/block/sed-opal.c
>> +++ b/block/sed-opal.c
>> @@ -1552,6 +1552,28 @@ static int revert_tper(struct opal_dev *dev, void *data)
>>  	return finalize_and_send(dev, parse_and_check_status);
>>  }
>>
>> +static int revert_sp(struct opal_dev *dev, void *data)
>> +{
>> +	int err;
>> +	struct opal_key *key = data;
>> +
>> +	err = cmd_start(dev, opaluid[OPAL_THISSP_UID],
>> +			opalmethod[OPAL_REVERTSP]);
>> +
>> +	add_token_u8(&err, dev, OPAL_STARTNAME);
>> +	add_token_u64(&err, dev, OPAL_SUM_SET_LIST);
>> +
>> +	/*
>> +	 * If KeepGlobalRangeKey is true, then the media encryption key
>> +	 * associated with Locking_GlobalRange is preserved.
>> +	 * If not true, then all user data is cryptographically erased.
>> +	 */
>> +	add_token_u8(&err, dev, key->keep_glbl_rn_key ? OPAL_TRUE : OPAL_FALSE);
>> +	add_token_u8(&err, dev, OPAL_ENDNAME);
>> +
>> +	return finalize_and_send(dev, parse_and_check_status);
>> +}
>> +
>>  static int internal_activate_user(struct opal_dev *dev, void *data)
>>  {
>>  	struct opal_session_info *session = data;
>> @@ -2327,7 +2349,8 @@ static int opal_add_user_to_lr(struct opal_dev *dev,
>>  	return ret;
>>  }
>>
>> -static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psid)
>> +static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal,
>> +			   enum opal_revert_method revert_type)
>>  {
>>  	/* controller will terminate session */
>>  	const struct opal_step revert_steps[] = {
>> @@ -2338,17 +2361,33 @@ static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psi
>>  		{ start_PSID_opal_session, opal },
>>  		{ revert_tper, }
>>  	};
>> +	const struct opal_step revertsp_steps[] = {
>> +		{ start_admin1LSP_opal_session, opal },
>> +		{ revert_sp, opal }
>> +	};
>>
>>  	int ret;
>>
>>  	mutex_lock(&dev->dev_lock);
>>  	setup_opal_dev(dev);
>> -	if (psid)
>> +	switch (revert_type) {
>> +	case OPAL_REVERT_PSID:
>>  		ret = execute_steps(dev, psid_revert_steps,
>>  				    ARRAY_SIZE(psid_revert_steps));
>> -	else
>> +		break;
>> +	case OPAL_REVERT_TPER:
>>  		ret = execute_steps(dev, revert_steps,
>>  				    ARRAY_SIZE(revert_steps));
>> +		break;
>> +	case OPAL_REVERT_SP:
>> +		ret = execute_steps(dev, revertsp_steps,
>> +				    ARRAY_SIZE(revertsp_steps));
>> +		break;
>> +	default:
>> +		pr_debug("Invalid revert type\n");
>> +		ret = -EINVAL;
>> +		break;
>> +	}
>>  	mutex_unlock(&dev->dev_lock);
>>
>>  	/*
>> @@ -2656,7 +2695,7 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
>>  		ret = opal_activate_user(dev, p);
>>  		break;
>>  	case IOC_OPAL_REVERT_TPR:
>> -		ret = opal_reverttper(dev, p, false);
>> +		ret = opal_reverttper(dev, p, OPAL_REVERT_TPER);
>>  		break;
>>  	case IOC_OPAL_LR_SETUP:
>>  		ret = opal_setup_locking_range(dev, p);
>> @@ -2680,11 +2719,14 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
>>  		ret = opal_secure_erase_locking_range(dev, p);
>>  		break;
>>  	case IOC_OPAL_PSID_REVERT_TPR:
>> -		ret = opal_reverttper(dev, p, true);
>> +		ret = opal_reverttper(dev, p, OPAL_REVERT_PSID);
>>  		break;
>>  	case IOC_OPAL_GENERIC_TABLE_RW:
>>  		ret = opal_generic_read_write_table(dev, p);
>>  		break;
>> +	case IOC_OPAL_REVERT_SP:
>> +		ret = opal_reverttper(dev, p, OPAL_REVERT_SP);
>> +		break;
>>  	default:
>>  		break;
>>  	}
>> diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
>> index 1ac0d712a9c3..85ad7bb7da41 100644
>> --- a/include/linux/sed-opal.h
>> +++ b/include/linux/sed-opal.h
>> @@ -43,6 +43,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
>>  	case IOC_OPAL_MBR_DONE:
>>  	case IOC_OPAL_WRITE_SHADOW_MBR:
>>  	case IOC_OPAL_GENERIC_TABLE_RW:
>> +	case IOC_OPAL_REVERT_SP:
>>  		return true;
>>  	}
>>  	return false;
>> diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
>> index 6f5af1a84213..ac59fbc1d06b 100644
>> --- a/include/uapi/linux/sed-opal.h
>> +++ b/include/uapi/linux/sed-opal.h
>> @@ -47,7 +47,8 @@ enum opal_lock_state {
>>  struct opal_key {
>>  	__u8 lr;
>>  	__u8 key_len;
>> -	__u8 __align[6];
>> +	__u8 keep_glbl_rn_key;
>> +	__u8 __align[5];
>>
> This is mostly fine, except that we're changing the definition of bits
> in an existing ioctl structure. We're not using those bits for any
> other ioctl so I wouldn't expect issues.
>
> I think instead you should take 4 bytes of __align and change it to a
> __u32 'flags', and #define a bitwise flag for your purposes. Eg,
> similar to the flags param in opal_read_write_table.

Changing to __u32 flag is a very good idea. This can be used for any future implementations as well.

How about having an enumeration "opal_key_flags", instead of #define for the flag.

>
> Please update the commit message if you do that.
Sure... will do it.
>
>>  	__u8 key[OPAL_KEY_MAX];
>>  };
>>
>> @@ -148,5 +149,6 @@ struct opal_read_write_table {
>>  #define IOC_OPAL_MBR_DONE           _IOW('p', 233, struct opal_mbr_done)
>>  #define IOC_OPAL_WRITE_SHADOW_MBR   _IOW('p', 234, struct opal_shadow_mbr)
>>  #define IOC_OPAL_GENERIC_TABLE_RW   _IOW('p', 235, struct opal_read_write_table)
>> +#define IOC_OPAL_REVERT_SP          _IOW('p', 236, struct opal_key)
>>
>>  #endif /* _UAPI_SED_OPAL_H */
>> --
>> 2.17.1
>>
diff mbox series

Patch

diff --git a/block/opal_proto.h b/block/opal_proto.h
index b486b3ec7dc4..8c6faa418ab4 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -140,6 +140,12 @@  enum opal_method {
 	OPAL_ERASE,
 };

+enum opal_revert_method {
+	OPAL_REVERT_TPER,
+	OPAL_REVERT_PSID,
+	OPAL_REVERT_SP,
+};
+
 enum opal_token {
 	/* Boolean */
 	OPAL_TRUE = 0x01,
diff --git a/block/sed-opal.c b/block/sed-opal.c
index daafadbb88ca..1939df83c45e 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1552,6 +1552,28 @@  static int revert_tper(struct opal_dev *dev, void *data)
 	return finalize_and_send(dev, parse_and_check_status);
 }

+static int revert_sp(struct opal_dev *dev, void *data)
+{
+	int err;
+	struct opal_key *key = data;
+
+	err = cmd_start(dev, opaluid[OPAL_THISSP_UID],
+			opalmethod[OPAL_REVERTSP]);
+
+	add_token_u8(&err, dev, OPAL_STARTNAME);
+	add_token_u64(&err, dev, OPAL_SUM_SET_LIST);
+
+	/*
+	 * If KeepGlobalRangeKey is true, then the media encryption key
+	 * associated with Locking_GlobalRange is preserved.
+	 * If not true, then all user data is cryptographically erased.
+	 */
+	add_token_u8(&err, dev, key->keep_glbl_rn_key ? OPAL_TRUE : OPAL_FALSE);
+	add_token_u8(&err, dev, OPAL_ENDNAME);
+
+	return finalize_and_send(dev, parse_and_check_status);
+}
+
 static int internal_activate_user(struct opal_dev *dev, void *data)
 {
 	struct opal_session_info *session = data;
@@ -2327,7 +2349,8 @@  static int opal_add_user_to_lr(struct opal_dev *dev,
 	return ret;
 }

-static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psid)
+static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal,
+			   enum opal_revert_method revert_type)
 {
 	/* controller will terminate session */
 	const struct opal_step revert_steps[] = {
@@ -2338,17 +2361,33 @@  static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psi
 		{ start_PSID_opal_session, opal },
 		{ revert_tper, }
 	};
+	const struct opal_step revertsp_steps[] = {
+		{ start_admin1LSP_opal_session, opal },
+		{ revert_sp, opal }
+	};

 	int ret;

 	mutex_lock(&dev->dev_lock);
 	setup_opal_dev(dev);
-	if (psid)
+	switch (revert_type) {
+	case OPAL_REVERT_PSID:
 		ret = execute_steps(dev, psid_revert_steps,
 				    ARRAY_SIZE(psid_revert_steps));
-	else
+		break;
+	case OPAL_REVERT_TPER:
 		ret = execute_steps(dev, revert_steps,
 				    ARRAY_SIZE(revert_steps));
+		break;
+	case OPAL_REVERT_SP:
+		ret = execute_steps(dev, revertsp_steps,
+				    ARRAY_SIZE(revertsp_steps));
+		break;
+	default:
+		pr_debug("Invalid revert type\n");
+		ret = -EINVAL;
+		break;
+	}
 	mutex_unlock(&dev->dev_lock);

 	/*
@@ -2656,7 +2695,7 @@  int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
 		ret = opal_activate_user(dev, p);
 		break;
 	case IOC_OPAL_REVERT_TPR:
-		ret = opal_reverttper(dev, p, false);
+		ret = opal_reverttper(dev, p, OPAL_REVERT_TPER);
 		break;
 	case IOC_OPAL_LR_SETUP:
 		ret = opal_setup_locking_range(dev, p);
@@ -2680,11 +2719,14 @@  int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
 		ret = opal_secure_erase_locking_range(dev, p);
 		break;
 	case IOC_OPAL_PSID_REVERT_TPR:
-		ret = opal_reverttper(dev, p, true);
+		ret = opal_reverttper(dev, p, OPAL_REVERT_PSID);
 		break;
 	case IOC_OPAL_GENERIC_TABLE_RW:
 		ret = opal_generic_read_write_table(dev, p);
 		break;
+	case IOC_OPAL_REVERT_SP:
+		ret = opal_reverttper(dev, p, OPAL_REVERT_SP);
+		break;
 	default:
 		break;
 	}
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 1ac0d712a9c3..85ad7bb7da41 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -43,6 +43,7 @@  static inline bool is_sed_ioctl(unsigned int cmd)
 	case IOC_OPAL_MBR_DONE:
 	case IOC_OPAL_WRITE_SHADOW_MBR:
 	case IOC_OPAL_GENERIC_TABLE_RW:
+	case IOC_OPAL_REVERT_SP:
 		return true;
 	}
 	return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 6f5af1a84213..ac59fbc1d06b 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -47,7 +47,8 @@  enum opal_lock_state {
 struct opal_key {
 	__u8 lr;
 	__u8 key_len;
-	__u8 __align[6];
+	__u8 keep_glbl_rn_key;
+	__u8 __align[5];
 	__u8 key[OPAL_KEY_MAX];
 };

@@ -148,5 +149,6 @@  struct opal_read_write_table {
 #define IOC_OPAL_MBR_DONE           _IOW('p', 233, struct opal_mbr_done)
 #define IOC_OPAL_WRITE_SHADOW_MBR   _IOW('p', 234, struct opal_shadow_mbr)
 #define IOC_OPAL_GENERIC_TABLE_RW   _IOW('p', 235, struct opal_read_write_table)
+#define IOC_OPAL_REVERT_SP          _IOW('p', 236, struct opal_key)

 #endif /* _UAPI_SED_OPAL_H */