* [PATCH 1/6] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
@ 2026-01-30 16:25 ` Ondrej Kozina
2026-02-02 23:17 ` Hannes Reinecke
2026-02-05 10:53 ` Milan Broz
2026-01-30 16:25 ` [PATCH 2/6] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals Ondrej Kozina
` (15 subsequent siblings)
16 siblings, 2 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-01-30 16:25 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, gjoyce, jonathan.derrick
This adds the 'Reactivate' method as described in the
"TCG Storage Opal SSC Feature Set: Single User Mode"
document (ch. 3.1.1.1).
The method enables switching an already active SED OPAL2 device,
with appropriate firmware support for Single User Mode (SUM),
to or from SUM.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 4 ++
block/sed-opal.c | 91 +++++++++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 14 ++++++
4 files changed, 110 insertions(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index d247a457bf6e..d138785b8198 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -125,6 +125,7 @@ enum opal_uid {
OPAL_LOCKING_INFO_TABLE,
OPAL_ENTERPRISE_LOCKING_INFO_TABLE,
OPAL_DATASTORE,
+ OPAL_LOCKING_TABLE,
/* C_PIN_TABLE object ID's */
OPAL_C_PIN_MSID,
OPAL_C_PIN_SID,
@@ -154,6 +155,7 @@ enum opal_method {
OPAL_AUTHENTICATE,
OPAL_RANDOM,
OPAL_ERASE,
+ OPAL_REACTIVATE,
};
enum opal_token {
@@ -224,6 +226,8 @@ enum opal_lockingstate {
enum opal_parameter {
OPAL_SUM_SET_LIST = 0x060000,
+ OPAL_SUM_RANGE_POLICY = 0x060001,
+ OPAL_SUM_ADMIN1_PIN = 0x060002,
};
enum opal_revertlsp {
diff --git a/block/sed-opal.c b/block/sed-opal.c
index a26a94642d84..552aa2b48a7b 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -162,6 +162,8 @@ static const u8 opaluid[][OPAL_UID_LENGTH] = {
{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
[OPAL_DATASTORE] =
{ 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00 },
+ [OPAL_LOCKING_TABLE] =
+ { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00 },
/* C_PIN_TABLE object ID's */
[OPAL_C_PIN_MSID] =
@@ -220,6 +222,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 +2291,64 @@ 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 (opal_react->entire_table) {
+ 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) {
+ 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);
+ }
+
+ 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 +3019,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 +3403,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..ef3ddb93b3e3 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 RangePolicy 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 */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH 1/6] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
2026-01-30 16:25 ` [PATCH 1/6] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
@ 2026-02-02 23:17 ` Hannes Reinecke
2026-02-05 10:53 ` Milan Broz
1 sibling, 0 replies; 48+ messages in thread
From: Hannes Reinecke @ 2026-02-02 23:17 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gmazyland, gjoyce, jonathan.derrick
On 1/30/26 17:25, Ondrej Kozina wrote:
> This adds the 'Reactivate' method as described in the
> "TCG Storage Opal SSC Feature Set: Single User Mode"
> document (ch. 3.1.1.1).
>
... only you don't. You also add the definition for 'LOCKING TABLE'.
Please mention that in the description.
> The method enables switching an already active SED OPAL2 device,
> with appropriate firmware support for Single User Mode (SUM),
> to or from SUM.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 4 ++
> block/sed-opal.c | 91 +++++++++++++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 14 ++++++
> 4 files changed, 110 insertions(+)
>
> diff --git a/block/opal_proto.h b/block/opal_proto.h
> index d247a457bf6e..d138785b8198 100644
> --- a/block/opal_proto.h
> +++ b/block/opal_proto.h
> @@ -125,6 +125,7 @@ enum opal_uid {
> OPAL_LOCKING_INFO_TABLE,
> OPAL_ENTERPRISE_LOCKING_INFO_TABLE,
> OPAL_DATASTORE,
> + OPAL_LOCKING_TABLE,
> /* C_PIN_TABLE object ID's */
> OPAL_C_PIN_MSID,
> OPAL_C_PIN_SID,
> @@ -154,6 +155,7 @@ enum opal_method {
> OPAL_AUTHENTICATE,
> OPAL_RANDOM,
> OPAL_ERASE,
> + OPAL_REACTIVATE,
> };
>
> enum opal_token {
> @@ -224,6 +226,8 @@ enum opal_lockingstate {
>
> enum opal_parameter {
> OPAL_SUM_SET_LIST = 0x060000,
> + OPAL_SUM_RANGE_POLICY = 0x060001,
> + OPAL_SUM_ADMIN1_PIN = 0x060002,
> };
>
> enum opal_revertlsp {
> diff --git a/block/sed-opal.c b/block/sed-opal.c
> index a26a94642d84..552aa2b48a7b 100644
> --- a/block/sed-opal.c
> +++ b/block/sed-opal.c
> @@ -162,6 +162,8 @@ static const u8 opaluid[][OPAL_UID_LENGTH] = {
> { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
> [OPAL_DATASTORE] =
> { 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00 },
> + [OPAL_LOCKING_TABLE] =
> + { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00 },
>
> /* C_PIN_TABLE object ID's */
> [OPAL_C_PIN_MSID] =
> @@ -220,6 +222,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 },
> };
>
Maybe split the above in a separate patch.
> static int end_opal_session_error(struct opal_dev *dev);
> @@ -2287,6 +2291,64 @@ 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 (opal_react->entire_table) {
> + 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) {
> + 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);
> + }
> +
> + 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 +3019,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 +3403,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..ef3ddb93b3e3 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 RangePolicy 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 */
Otherwise looks good.
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH 1/6] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
2026-01-30 16:25 ` [PATCH 1/6] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
2026-02-02 23:17 ` Hannes Reinecke
@ 2026-02-05 10:53 ` Milan Broz
1 sibling, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-05 10:53 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gjoyce, jonathan.derrick
On 1/30/26 5:25 PM, Ondrej Kozina wrote:
> This adds the 'Reactivate' method as described in the
> "TCG Storage Opal SSC Feature Set: Single User Mode"
> document (ch. 3.1.1.1).
>
> The method enables switching an already active SED OPAL2 device,
> with appropriate firmware support for Single User Mode (SUM),
> to or from SUM.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 4 ++
> block/sed-opal.c | 91 +++++++++++++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 14 ++++++
> 4 files changed, 110 insertions(+)
>
> diff --git a/block/opal_proto.h b/block/opal_proto.h
> index d247a457bf6e..d138785b8198 100644
> --- a/block/opal_proto.h
> +++ b/block/opal_proto.h
> @@ -125,6 +125,7 @@ enum opal_uid {
> OPAL_LOCKING_INFO_TABLE,
> OPAL_ENTERPRISE_LOCKING_INFO_TABLE,
> OPAL_DATASTORE,
> + OPAL_LOCKING_TABLE,
This addition should be mentioned in commit messages.
Perhaps separate new UID definitions to another patch.
> @@ -2287,6 +2291,64 @@ 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;
> + }
> +
Hera I would add comment describing which variants it implement
- set SUM for whole locking table (no list)
- set SUM for separate LRs
and how it differs.
> + if (opal_react->entire_table) {
> + 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) {
> + 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);
> +
Remove empty line here?
> + 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);
> + }
> +
This is optional, if not set, admin key remains unchanged. Add comment?
> + 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);
> + }
...
Otherwise looks good.
Milan
p.s.
I implemented similar code in userspace for opal-toolset and tested on several drives.
Original sedutils do not implement SUM / reactivate at all.
That said, there are many drives that have broken SUM implementation... but I am pretty
sure the construction above is according to TCG standard.
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH 2/6] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
2026-01-30 16:25 ` [PATCH 1/6] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
@ 2026-01-30 16:25 ` Ondrej Kozina
2026-01-30 16:25 ` [PATCH 3/6] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl Ondrej Kozina
` (14 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-01-30 16:25 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, gjoyce, jonathan.derrick
IOC_OPAL_LR_SETUP is used to set up a locking range entirely under a
single authority (usually Admin1), but for Single User Mode (SUM),
the permissions for attributes (RangeStart, RangeLength)
and (ReadLockEnable, WriteLockEnable, ReadLocked, WriteLocked)
may be split between two different authorities. Typically, it is Admin1
for the former and the User associated with the LockingRange in SUM
for the latter.
This commit only splits the internals in preparation for the introduction
of separate ioctls for setting RangeStart, RangeLength and the rest
using new ioctl calls.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 73 +++++++++++++++++++++++++++++-------------------
1 file changed, 45 insertions(+), 28 deletions(-)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 552aa2b48a7b..9fb6e0b953d5 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1520,7 +1520,7 @@ static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
return err;
}
-static int setup_locking_range(struct opal_dev *dev, void *data)
+static int setup_enable_range(struct opal_dev *dev, void *data)
{
u8 uid[OPAL_UID_LENGTH];
struct opal_user_lr_setup *setup = data;
@@ -1534,38 +1534,47 @@ static int setup_locking_range(struct opal_dev *dev, void *data)
if (lr == 0)
err = enable_global_lr(dev, uid, setup);
- else {
- err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
+ else
+ err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE, 0, 0);
+ if (err) {
+ pr_debug("Failed to create enable lr command.\n");
+ return err;
+ }
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_VALUES);
- add_token_u8(&err, dev, OPAL_STARTLIST);
+ return finalize_and_send(dev, parse_and_check_status);
+}
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_RANGESTART);
- add_token_u64(&err, dev, setup->range_start);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+static int setup_locking_range_start_length(struct opal_dev *dev, void *data)
+{
+ int err;
+ u8 uid[OPAL_UID_LENGTH];
+ struct opal_user_lr_setup *setup = data;
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_RANGELENGTH);
- add_token_u64(&err, dev, setup->range_length);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ err = build_locking_range(uid, sizeof(uid), setup->session.opal_key.lr);
+ if (err)
+ return err;
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_READLOCKENABLED);
- add_token_u64(&err, dev, !!setup->RLE);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_WRITELOCKENABLED);
- add_token_u64(&err, dev, !!setup->WLE);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_VALUES);
+ add_token_u8(&err, dev, OPAL_STARTLIST);
+
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_RANGESTART);
+ add_token_u64(&err, dev, setup->range_start);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_RANGELENGTH);
+ add_token_u64(&err, dev, setup->range_length);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+
+ add_token_u8(&err, dev, OPAL_ENDLIST);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
- add_token_u8(&err, dev, OPAL_ENDLIST);
- add_token_u8(&err, dev, OPAL_ENDNAME);
- }
if (err) {
- pr_debug("Error building Setup Locking range command.\n");
+ pr_debug("Error building Setup Locking RangeStartLength command.\n");
return err;
}
@@ -3050,7 +3059,12 @@ static int opal_setup_locking_range(struct opal_dev *dev,
{
const struct opal_step lr_steps[] = {
{ start_auth_opal_session, &opal_lrs->session },
- { setup_locking_range, opal_lrs },
+ { setup_locking_range_start_length, opal_lrs },
+ { setup_enable_range, opal_lrs },
+ { end_opal_session, }
+ }, lr_global_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_enable_range, opal_lrs },
{ end_opal_session, }
};
int ret;
@@ -3060,7 +3074,10 @@ static int opal_setup_locking_range(struct opal_dev *dev,
return ret;
mutex_lock(&dev->dev_lock);
setup_opal_dev(dev);
- ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ if (opal_lrs->session.opal_key.lr == 0)
+ ret = execute_steps(dev, lr_global_steps, ARRAY_SIZE(lr_global_steps));
+ else
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
mutex_unlock(&dev->dev_lock);
return ret;
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH 3/6] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
2026-01-30 16:25 ` [PATCH 1/6] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
2026-01-30 16:25 ` [PATCH 2/6] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals Ondrej Kozina
@ 2026-01-30 16:25 ` Ondrej Kozina
2026-01-30 16:25 ` [PATCH 4/6] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR Ondrej Kozina
` (13 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-01-30 16:25 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, gjoyce, jonathan.derrick
This ioctl is used to set up locking range start (offset)
and locking range length attributes only.
In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
is set in the 'Reactivate' method, only Admin authority maintains the
locking range length and start (offset) attributes of Locking objects
set up for SUM. All other attributes from struct opal_user_lr_setup
(RLE - read locking enabled, WLE - write locking enabled) shall
remain in possession of the User authority associated with the Locking
object set for SUM.
Therefore, we need a separate function for setting up locking range
start and locking range length because it may require two different
authorities (and sessions) if the RangeStartRangeLengthPolicy attribute
is set.
With the IOC_OPAL_LR_SET_START_LEN ioctl, the opal_user_lr_setup
members 'RLE' and 'WLE' of the ioctl argument are ignored.
The RangeStartRangeLengthPolicy attribute is described in ch.
3.1.1.1.1.2 of the TCG Storage Opal SSC Feature Set: Single User Mode
document.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 28 ++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 1 +
3 files changed, 30 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 9fb6e0b953d5..2c8d85cabdd5 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3083,6 +3083,31 @@ static int opal_setup_locking_range(struct opal_dev *dev,
return ret;
}
+static int opal_setup_locking_range_start_length(struct opal_dev *dev,
+ struct opal_user_lr_setup *opal_lrs)
+{
+ const struct opal_step lr_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_locking_range_start_length, opal_lrs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ /* we can not set global locking range offset or length */
+ if (opal_lrs->session.opal_key.lr == 0)
+ return -EINVAL;
+
+ ret = opal_get_key(dev, &opal_lrs->session.opal_key);
+ if (ret)
+ return ret;
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_locking_range_status(struct opal_dev *dev,
struct opal_lr_status *opal_lrst,
void __user *data)
@@ -3423,6 +3448,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_REACTIVATE_LSP:
ret = opal_reactivate_lsp(dev, p);
break;
+ case IOC_OPAL_LR_SET_START_LEN:
+ ret = opal_setup_locking_range_start_length(dev, p);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 2ae5e6b0ac21..a0df6819b0a9 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -54,6 +54,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_REVERT_LSP:
case IOC_OPAL_SET_SID_PW:
case IOC_OPAL_REACTIVATE_LSP:
+ case IOC_OPAL_LR_SET_START_LEN:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index ef3ddb93b3e3..bf796c05f4d0 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -230,5 +230,6 @@ struct opal_revert_lsp {
#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)
+#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH 4/6] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (2 preceding siblings ...)
2026-01-30 16:25 ` [PATCH 3/6] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl Ondrej Kozina
@ 2026-01-30 16:25 ` Ondrej Kozina
2026-01-30 16:25 ` [PATCH 5/6] sed-opal: increase column attribute type size to 64 bits Ondrej Kozina
` (12 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-01-30 16:25 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, gjoyce, jonathan.derrick
This ioctl is used to set up RLE (read lock enabled) and WLE (write
lock enabled) parameters of the Locking object.
In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
is set in the 'Reactivate' method, only Admin authority maintains the
locking range length and start (offset) attributes of Locking objects
set up for SUM. All other attributes from struct opal_user_lr_setup
(RLE - read locking enabled, WLE - write locking enabled) shall
remain in possession of the User authority associated with the Locking
object set for SUM.
With the IOC_OPAL_ENABLE_DISABLE_LR ioctl, the opal_user_lr_setup
members 'range_start' and 'range_length' of the ioctl argument are
ignored.
The RangeStartRangeLengthPolicy attribute is described in ch.
3.1.1.1.1.2 of the TCG Storage Opal SSC Feature Set: Single User Mode
document.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 24 ++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 1 +
3 files changed, 26 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 2c8d85cabdd5..d960450ab3ac 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3108,6 +3108,27 @@ static int opal_setup_locking_range_start_length(struct opal_dev *dev,
return ret;
}
+static int opal_enable_disable_range(struct opal_dev *dev,
+ struct opal_user_lr_setup *opal_lrs)
+{
+ const struct opal_step lr_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_enable_range, opal_lrs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ ret = opal_get_key(dev, &opal_lrs->session.opal_key);
+ if (ret)
+ return ret;
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_locking_range_status(struct opal_dev *dev,
struct opal_lr_status *opal_lrst,
void __user *data)
@@ -3451,6 +3472,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_LR_SET_START_LEN:
ret = opal_setup_locking_range_start_length(dev, p);
break;
+ case IOC_OPAL_ENABLE_DISABLE_LR:
+ ret = opal_enable_disable_range(dev, p);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index a0df6819b0a9..1d63479838cf 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -55,6 +55,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_SET_SID_PW:
case IOC_OPAL_REACTIVATE_LSP:
case IOC_OPAL_LR_SET_START_LEN:
+ case IOC_OPAL_ENABLE_DISABLE_LR:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index bf796c05f4d0..5c3a9f3e4abc 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -231,5 +231,6 @@ 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)
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
+#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH 5/6] sed-opal: increase column attribute type size to 64 bits.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (3 preceding siblings ...)
2026-01-30 16:25 ` [PATCH 4/6] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR Ondrej Kozina
@ 2026-01-30 16:25 ` Ondrej Kozina
2026-01-30 16:25 ` [PATCH 6/6] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
` (11 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-01-30 16:25 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, gjoyce, jonathan.derrick
Change the column parameter in response_get_column() from u8 to u64
to support the full range of column identifiers.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index d960450ab3ac..ae1a6f668cbb 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1583,7 +1583,7 @@ static int setup_locking_range_start_length(struct opal_dev *dev, void *data)
static int response_get_column(const struct parsed_resp *resp,
int *iter,
- u8 column,
+ u64 column,
u64 *value)
{
const struct opal_resp_tok *tok;
@@ -1601,7 +1601,7 @@ static int response_get_column(const struct parsed_resp *resp,
n++;
if (response_get_u64(resp, n) != column) {
- pr_debug("Token %d does not match expected column %u.\n",
+ pr_debug("Token %d does not match expected column %llu.\n",
n, column);
return OPAL_INVAL_PARAM;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH 6/6] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (4 preceding siblings ...)
2026-01-30 16:25 ` [PATCH 5/6] sed-opal: increase column attribute type size to 64 bits Ondrej Kozina
@ 2026-01-30 16:25 ` Ondrej Kozina
2026-02-05 10:58 ` Milan Broz
2026-02-05 11:03 ` [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Milan Broz
` (10 subsequent siblings)
16 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-01-30 16:25 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, gjoyce, jonathan.derrick
This adds a function for retrieving the set of Locking objects enabled
for Single User Mode (SUM) and the value of the
RangeStartRangeLengthPolicy parameter.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 149 ++++++++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 9 ++
3 files changed, 159 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index ae1a6f668cbb..695d25bccd8b 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1759,6 +1759,12 @@ static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
OPAL_ADMINSP_UID, NULL, 0);
}
+static int start_anybodyLSP_opal_session(struct opal_dev *dev, void *data)
+{
+ return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
+ OPAL_LOCKINGSP_UID, NULL, 0);
+}
+
static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
{
int ret;
@@ -3381,6 +3387,146 @@ static int opal_get_geometry(struct opal_dev *dev, void __user *data)
return 0;
}
+static int get_sum_ranges(struct opal_dev *dev, void *data)
+{
+ const char *lr_uid;
+ size_t lr_uid_len;
+ u64 val;
+ const struct opal_resp_tok *tok;
+ int err, tok_n = 2;
+ struct opal_sum_ranges *sranges = data;
+ const __u8 lr_all[OPAL_MAX_LRS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ err = generic_get_columns(dev, opaluid[OPAL_LOCKING_INFO_TABLE], OPAL_SUM_SET_LIST,
+ OPAL_SUM_RANGE_POLICY);
+ if (err) {
+ pr_debug("Couldn't get locking info table columns %d to %d.\n",
+ OPAL_SUM_SET_LIST, OPAL_SUM_RANGE_POLICY);
+ return err;
+ }
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ if (!response_token_matches(tok, OPAL_STARTNAME)) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ if (response_get_u64(&dev->parsed, tok_n) != OPAL_SUM_SET_LIST) {
+ pr_debug("Token %d does not match expected column %u.\n",
+ tok_n, OPAL_SUM_SET_LIST);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ if (response_token_matches(tok, OPAL_STARTLIST)) {
+ sranges->num_lrs = 0;
+
+ tok_n++;
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ while (!response_token_matches(tok, OPAL_ENDLIST)) {
+ lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
+ if (lr_uid_len != OPAL_UID_LENGTH) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+
+ if (memcmp(lr_uid, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH)) {
+ if (lr_uid[5] != LOCKING_RANGE_NON_GLOBAL) {
+ pr_debug("Unexpected byte %d at LR UUID position 5.\n",
+ lr_uid[5]);
+ return OPAL_INVAL_PARAM;
+ }
+ sranges->lr[sranges->num_lrs++] = lr_uid[7];
+ } else
+ sranges->lr[sranges->num_lrs++] = 0;
+
+ tok_n++;
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+ }
+ } else {
+ /* Only OPAL_LOCKING_TABLE UID is an alternative to OPAL_STARTLIST here. */
+ lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
+ if (lr_uid_len != OPAL_UID_LENGTH) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+
+ if (memcmp(lr_uid, opaluid[OPAL_LOCKING_TABLE], OPAL_UID_LENGTH)) {
+ pr_debug("Unexpected response UID.\n");
+ return OPAL_INVAL_PARAM;
+ }
+
+ /* sed-opal kernel API already provides following limit in Activate command */
+ sranges->num_lrs = OPAL_MAX_LRS;
+ memcpy(sranges->lr, lr_all, OPAL_MAX_LRS);
+ }
+ tok_n++;
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ if (!response_token_matches(tok, OPAL_ENDNAME)) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ err = response_get_column(&dev->parsed, &tok_n, OPAL_SUM_RANGE_POLICY, &val);
+ if (err)
+ return err;
+
+ sranges->range_policy = val ? 1 : 0;
+
+ return 0;
+}
+
+static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opal_sum_rngs,
+ void __user *data)
+{
+ const struct opal_step admin_steps[] = {
+ { start_admin1LSP_opal_session, &opal_sum_rngs->key },
+ { get_sum_ranges, opal_sum_rngs },
+ { end_opal_session, }
+ }, anybody_steps[] = {
+ { start_anybodyLSP_opal_session, NULL },
+ { get_sum_ranges, opal_sum_rngs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ if (opal_sum_rngs->key.key_len)
+ ret = execute_steps(dev, admin_steps, ARRAY_SIZE(admin_steps));
+ else
+ ret = execute_steps(dev, anybody_steps, ARRAY_SIZE(anybody_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ /* skip session info when copying back to uspace */
+ if (!ret && copy_to_user(data + offsetof(struct opal_sum_ranges, num_lrs),
+ (void *)opal_sum_rngs + offsetof(struct opal_sum_ranges, num_lrs),
+ sizeof(*opal_sum_rngs) - offsetof(struct opal_sum_ranges, num_lrs))) {
+ pr_debug("Error copying SUM ranges info to userspace\n");
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
{
void *p;
@@ -3475,6 +3621,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_ENABLE_DISABLE_LR:
ret = opal_enable_disable_range(dev, p);
break;
+ case IOC_OPAL_GET_SUM_STATUS:
+ ret = opal_get_sum_ranges(dev, p, arg);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 1d63479838cf..aa006edb612b 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -56,6 +56,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_REACTIVATE_LSP:
case IOC_OPAL_LR_SET_START_LEN:
case IOC_OPAL_ENABLE_DISABLE_LR:
+ case IOC_OPAL_GET_SUM_STATUS:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 5c3a9f3e4abc..28d97a03f98f 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -111,6 +111,14 @@ struct opal_lr_status {
__u8 align[4];
};
+struct opal_sum_ranges {
+ struct opal_key key;
+ __u8 num_lrs;
+ __u8 lr[OPAL_MAX_LRS];
+ __u8 range_policy;
+ __u8 align[5]; /* Align to 8 byte boundary */
+};
+
struct opal_lock_unlock {
struct opal_session_info session;
__u32 l_state;
@@ -232,5 +240,6 @@ struct opal_revert_lsp {
#define IOC_OPAL_REACTIVATE_LSP _IOW('p', 242, struct opal_lr_react)
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
+#define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH 6/6] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
2026-01-30 16:25 ` [PATCH 6/6] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
@ 2026-02-05 10:58 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-05 10:58 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gjoyce, jonathan.derrick
On 1/30/26 5:25 PM, Ondrej Kozina wrote:
> This adds a function for retrieving the set of Locking objects enabled
> for Single User Mode (SUM) and the value of the
> RangeStartRangeLengthPolicy parameter.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
...>
> +static int get_sum_ranges(struct opal_dev *dev, void *data)
> +{
...
I would add here comment (with reference to TCG spec) explaining two possible responses
(list or whole table).
> + while (!response_token_matches(tok, OPAL_ENDLIST)) {
> + lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
> + if (lr_uid_len != OPAL_UID_LENGTH) {
> + pr_debug("Unexpected response token type %d.\n", tok_n);
> + return OPAL_INVAL_PARAM;
> + }
> +
> + if (memcmp(lr_uid, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH)) {
> + if (lr_uid[5] != LOCKING_RANGE_NON_GLOBAL) {
> + pr_debug("Unexpected byte %d at LR UUID position 5.\n",
> + lr_uid[5]);
> + return OPAL_INVAL_PARAM;
> + }
> + sranges->lr[sranges->num_lrs++] = lr_uid[7];
> + } else
> + sranges->lr[sranges->num_lrs++] = 0;
> +
> + tok_n++;
> + tok = response_get_token(&dev->parsed, tok_n);
> + if (IS_ERR(tok))
> + return PTR_ERR(tok);
> + }
> + } else {
> + /* Only OPAL_LOCKING_TABLE UID is an alternative to OPAL_STARTLIST here. */
> + lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
> + if (lr_uid_len != OPAL_UID_LENGTH) {
> + pr_debug("Unexpected response token type %d.\n", tok_n);
> + return OPAL_INVAL_PARAM;
> + }
> +
> + if (memcmp(lr_uid, opaluid[OPAL_LOCKING_TABLE], OPAL_UID_LENGTH)) {
> + pr_debug("Unexpected response UID.\n");
> + return OPAL_INVAL_PARAM;
> + }
> +
> + /* sed-opal kernel API already provides following limit in Activate command */
> + sranges->num_lrs = OPAL_MAX_LRS;
> + memcpy(sranges->lr, lr_all, OPAL_MAX_LRS);
> + }
...
Otherwise it is ok.
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (5 preceding siblings ...)
2026-01-30 16:25 ` [PATCH 6/6] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
@ 2026-02-05 11:03 ` Milan Broz
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (9 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-05 11:03 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gjoyce, jonathan.derrick
On 1/30/26 5:25 PM, Ondrej Kozina wrote:
> This patch series extends support for TCG Storage Opal SSC Single User
> Mode (SUM) in the sed-opal kernel interface. SUM addresses few
> shortcomins described in the chapter 2 of the OPAL2 sepecification
> extension (see below). It better isolates Admin authority from User
> stored data by taking the Lock/Unlock/Enable/Disable privileges from
> Admin when managing Locking Ranges configured for SUM.
>
> This permission split necessitates separate ioctl calls for operations
> that previously could be performed atomically under a single authority.
> The series refactors existing code and introduces new ioctls to support
> this model:
>
> - IOC_OPAL_REACTIVATE_LSP: Switch an active OPAL2 device to/from SUM
> - IOC_OPAL_LR_SET_START_LEN: Set locking range boundaries only
> - IOC_OPAL_ENABLE_DISABLE_LR: Set lock enable states only
> - IOC_OPAL_GET_SUM_STATUS: Query SUM configuration status
>
> References:
> - TCG Storage Opal SSC Feature Set: Single User Mode specification
> - cryptsetup code using the extended sed-opal interface:
> https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/832
I have tested this + cryptsetup userspace on my collection of SED devices
(some SATA, but mostly NVMe).
There are several broken Opal2 implementations, as vendors
usually refuses to fix it as it is out of support, we need detect
"supportable" SUM.
Anyway, kernel ioctls should remain simple here, in general, LGTM.
Please check comments on for separate patches.
Once fixed, I'll add my review/tested signature.
Thanks!
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread* [PATCH v2 0/9] Extend Single User Mode (SUM) support in sed-opal.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (6 preceding siblings ...)
2026-02-05 11:03 ` [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Milan Broz
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-06 14:17 ` [PATCH v3 " Ondrej Kozina
` (9 more replies)
2026-02-05 15:09 ` [PATCH v2 1/9] sed-opal: add UID of Locking Table Ondrej Kozina
` (8 subsequent siblings)
16 siblings, 10 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This patch series extends support for TCG Storage Opal SSC Single User
Mode (SUM) in the sed-opal kernel interface. SUM addresses few
shortcomins described in the chapter 2 of the OPAL2 sepecification
extension (see below). It better isolates Admin authority from User
stored data by taking the Lock/Unlock/Enable/Disable privileges from
Admin when managing Locking Ranges configured for SUM.
This permission split necessitates separate ioctl calls for operations
that previously could be performed atomically under a single authority.
The series refactors existing code and introduces new ioctls to support
this model:
- IOC_OPAL_REACTIVATE_LSP: Switch an active OPAL2 device to/from SUM
- IOC_OPAL_LR_SET_START_LEN: Set locking range boundaries only
- IOC_OPAL_ENABLE_DISABLE_LR: Set lock enable states only
- IOC_OPAL_GET_SUM_STATUS: Query SUM configuration status
References:
- TCG Storage Opal SSC Feature Set: Single User Mode specification
- cryptsetup code using the extended sed-opal interface:
https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/832
Changes since previus version:
v2:
- Make separate patch adding Locking table UID
- Make separate patch adding RangeStartRangeLengthPolicy parameter
- Make separate patch adding Admin1PIN parameter
- Add comments explaining differences between passing Locking table
UID and separate Locking Ranges UID via array in IOC_OPAL_REACTIVATE_LSP
- Minor whitespace fixes
- Minor commit messages changes in IOC_OPAL_LR_SET_START_LEN and
IOC_OPAL_ENABLE_DISABLE_LR ioctls patches.
- Additional comments explaining expected answer from the
controller in IOC_OPAL_GET_SUM_STATUS ioctl.
Ondrej Kozina (9):
sed-opal: add UID of Locking Table.
sed-opal: add RangeStartRangeLengthPolicy parameter.
sed-opal: add Admin1PIN parameter.
sed-opal: add IOC_OPAL_REACTIVATE_LSP.
sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
sed-opal: increase column attribute type size to 64 bits.
sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
block/opal_proto.h | 4 +
block/sed-opal.c | 385 +++++++++++++++++++++++++++++++---
include/linux/sed-opal.h | 4 +
include/uapi/linux/sed-opal.h | 25 +++
4 files changed, 389 insertions(+), 29 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 48+ messages in thread* [PATCH v3 0/9] Extend Single User Mode (SUM) support in sed-opal.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
@ 2026-02-06 14:17 ` Ondrej Kozina
2026-02-26 13:47 ` Ondrej Kozina
2026-02-26 15:41 ` Jens Axboe
2026-02-06 14:17 ` [PATCH v3 1/9] sed-opal: add UID of Locking Table Ondrej Kozina
` (8 subsequent siblings)
9 siblings, 2 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:17 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This patch series extends support for TCG Storage Opal SSC Single User
Mode (SUM) in the sed-opal kernel interface. SUM addresses few
shortcomins described in the chapter 2 of the OPAL2 sepecification
extension (see below). It better isolates Admin authority from User
stored data by taking the Lock/Unlock/Enable/Disable privileges from
Admin when managing Locking Ranges configured for SUM.
This permission split necessitates separate ioctl calls for operations
that previously could be performed atomically under a single authority.
The series refactors existing code and introduces new ioctls to support
this model:
- IOC_OPAL_REACTIVATE_LSP: Switch an active OPAL2 device to/from SUM
- IOC_OPAL_LR_SET_START_LEN: Set locking range boundaries only
- IOC_OPAL_ENABLE_DISABLE_LR: Set lock enable states only
- IOC_OPAL_GET_SUM_STATUS: Query SUM configuration status
References:
- TCG Storage Opal SSC Feature Set: Single User Mode specification
- cryptsetup code using the extended sed-opal interface:
https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/832
Changes since previus version:
v3:
- Add code comments in the IOC_OPAL_GET_SUM_STATUS patch explaining
the different code paths for key set or not set in the opal_sum_ranges
ioctl parameter
- Extended IOC_OPAL_GET_SUM_STATUS commit message referencing the TCG
doc where the new columns are described.
v2:
- Make separate patch adding Locking table UID
- Make separate patch adding RangeStartRangeLengthPolicy parameter
- Make separate patch adding Admin1PIN parameter
- Add comments explaining differences between passing Locking table
UID and separate Locking Ranges UID via array in IOC_OPAL_REACTIVATE_LSP
- Minor whitespace fixes
- Minor commit messages changes in IOC_OPAL_LR_SET_START_LEN and
IOC_OPAL_ENABLE_DISABLE_LR ioctls patches.
- Additional comments explaining expected answer from the
controller in IOC_OPAL_GET_SUM_STATUS ioctl.
Ondrej Kozina (9):
sed-opal: add UID of Locking Table.
sed-opal: add RangeStartRangeLengthPolicy parameter.
sed-opal: add Admin1PIN parameter.
sed-opal: add IOC_OPAL_REACTIVATE_LSP.
sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
sed-opal: increase column attribute type size to 64 bits.
sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
block/opal_proto.h | 4 +
block/sed-opal.c | 387 +++++++++++++++++++++++++++++++---
include/linux/sed-opal.h | 4 +
include/uapi/linux/sed-opal.h | 29 +++
4 files changed, 395 insertions(+), 29 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 48+ messages in thread* Re: [PATCH v3 0/9] Extend Single User Mode (SUM) support in sed-opal.
2026-02-06 14:17 ` [PATCH v3 " Ondrej Kozina
@ 2026-02-26 13:47 ` Ondrej Kozina
2026-02-26 15:34 ` Jens Axboe
2026-02-26 15:41 ` Jens Axboe
1 sibling, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-26 13:47 UTC (permalink / raw)
To: linux-block; +Cc: axboe
Hi,
a gentle ping: is there anything I can improve on in the patch set?
With kind regards
O.
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v3 0/9] Extend Single User Mode (SUM) support in sed-opal.
2026-02-06 14:17 ` [PATCH v3 " Ondrej Kozina
2026-02-26 13:47 ` Ondrej Kozina
@ 2026-02-26 15:41 ` Jens Axboe
1 sibling, 0 replies; 48+ messages in thread
From: Jens Axboe @ 2026-02-26 15:41 UTC (permalink / raw)
To: linux-block, Ondrej Kozina; +Cc: gmazyland, jonathan.derrick, gjoyce, hare
On Fri, 06 Feb 2026 15:17:54 +0100, Ondrej Kozina wrote:
> This patch series extends support for TCG Storage Opal SSC Single User
> Mode (SUM) in the sed-opal kernel interface. SUM addresses few
> shortcomins described in the chapter 2 of the OPAL2 sepecification
> extension (see below). It better isolates Admin authority from User
> stored data by taking the Lock/Unlock/Enable/Disable privileges from
> Admin when managing Locking Ranges configured for SUM.
>
> [...]
Applied, thanks!
[1/9] sed-opal: add UID of Locking Table.
commit: 985977af2390d5055ae30f9f56846b74dbe16311
[2/9] sed-opal: add RangeStartRangeLengthPolicy parameter.
commit: d7c65aba73efb1519685bda79d0b924f3fc1d856
[3/9] sed-opal: add Admin1PIN parameter.
commit: 1ccd8e90d2d705ccee423acb7eb69cdc2e17b3f3
[4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
commit: e00c5bf602e9e99397c9385fc6687403b6536676
[5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
commit: 700cc7055c96dcecb1fe3ce86ad9769b6ecf87ba
[6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
commit: 401262181b2f041679f526c9557e13ef4d243cd9
[7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
commit: e777eba95dae6427d640dd493c489511342f8b7f
[8/9] sed-opal: increase column attribute type size to 64 bits.
commit: 93c58e070b38cd5be7a9870b324a14a4b0142475
[9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
commit: 42dcb3826c86288a5c517dc2b465da687e7b38d6
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 1/9] sed-opal: add UID of Locking Table.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
2026-02-06 14:17 ` [PATCH v3 " Ondrej Kozina
@ 2026-02-06 14:17 ` Ondrej Kozina
2026-02-06 15:30 ` Milan Broz
2026-02-06 14:17 ` [PATCH v3 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter Ondrej Kozina
` (7 subsequent siblings)
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:17 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
As described in ch. 6.3, Table 240 in TCG Storage
Architecture Core Specification document.
It's also referenced in TCG Storage Opal SSC Feature Set:
Single User Mode document, ch. 3.1.1.1 Reactivate method.
It will be used later in Reactivate method implemetation
for sed-opal interface.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
block/sed-opal.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index d247a457bf6e..3dfba3de7be1 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -125,6 +125,7 @@ enum opal_uid {
OPAL_LOCKING_INFO_TABLE,
OPAL_ENTERPRISE_LOCKING_INFO_TABLE,
OPAL_DATASTORE,
+ OPAL_LOCKING_TABLE,
/* C_PIN_TABLE object ID's */
OPAL_C_PIN_MSID,
OPAL_C_PIN_SID,
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 5a28f23f7f22..13ed2dd83c5d 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -160,6 +160,8 @@ static const u8 opaluid[][OPAL_UID_LENGTH] = {
{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
[OPAL_DATASTORE] =
{ 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00 },
+ [OPAL_LOCKING_TABLE] =
+ { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00 },
/* C_PIN_TABLE object ID's */
[OPAL_C_PIN_MSID] =
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 1/9] sed-opal: add UID of Locking Table.
2026-02-06 14:17 ` [PATCH v3 1/9] sed-opal: add UID of Locking Table Ondrej Kozina
@ 2026-02-06 15:30 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:30 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:17 PM, Ondrej Kozina wrote:
> As described in ch. 6.3, Table 240 in TCG Storage
> Architecture Core Specification document.
>
> It's also referenced in TCG Storage Opal SSC Feature Set:
> Single User Mode document, ch. 3.1.1.1 Reactivate method.
>
> It will be used later in Reactivate method implemetation
> for sed-opal interface.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> block/sed-opal.c | 2 ++
> 2 files changed, 3 insertions(+)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
2026-02-06 14:17 ` [PATCH v3 " Ondrej Kozina
2026-02-06 14:17 ` [PATCH v3 1/9] sed-opal: add UID of Locking Table Ondrej Kozina
@ 2026-02-06 14:17 ` Ondrej Kozina
2026-02-06 15:31 ` Milan Broz
2026-02-06 14:17 ` [PATCH v3 3/9] sed-opal: add Admin1PIN parameter Ondrej Kozina
` (6 subsequent siblings)
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:17 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
As desribed in ch. 3.1.1.1.1.2 of TCG Storage Opal SSC Feature Set:
Single User Mode document.
To be used later in Reactivate method implementation and in function
for retrieving SUM device status.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index 3dfba3de7be1..b9877eacfe91 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -225,6 +225,7 @@ enum opal_lockingstate {
enum opal_parameter {
OPAL_SUM_SET_LIST = 0x060000,
+ OPAL_SUM_RANGE_POLICY = 0x060001,
};
enum opal_revertlsp {
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter.
2026-02-06 14:17 ` [PATCH v3 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter Ondrej Kozina
@ 2026-02-06 15:31 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:31 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:17 PM, Ondrej Kozina wrote:
> As desribed in ch. 3.1.1.1.1.2 of TCG Storage Opal SSC Feature Set:
> Single User Mode document.
>
> To be used later in Reactivate method implementation and in function
> for retrieving SUM device status.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> 1 file changed, 1 insertion(+)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 3/9] sed-opal: add Admin1PIN parameter.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (2 preceding siblings ...)
2026-02-06 14:17 ` [PATCH v3 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter Ondrej Kozina
@ 2026-02-06 14:17 ` Ondrej Kozina
2026-02-06 15:31 ` Milan Broz
2026-02-06 14:17 ` [PATCH v3 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
` (5 subsequent siblings)
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:17 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
As desribed in ch. 3.1.1.1.1.3 of TCG Storage Opal SSC Feature Set:
Single User Mode document.
To be used later in Reactivate method implementation.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index b9877eacfe91..3ccee5977c10 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -226,6 +226,7 @@ enum opal_lockingstate {
enum opal_parameter {
OPAL_SUM_SET_LIST = 0x060000,
OPAL_SUM_RANGE_POLICY = 0x060001,
+ OPAL_SUM_ADMIN1_PIN = 0x060002,
};
enum opal_revertlsp {
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 3/9] sed-opal: add Admin1PIN parameter.
2026-02-06 14:17 ` [PATCH v3 3/9] sed-opal: add Admin1PIN parameter Ondrej Kozina
@ 2026-02-06 15:31 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:31 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:17 PM, Ondrej Kozina wrote:
> As desribed in ch. 3.1.1.1.1.3 of TCG Storage Opal SSC Feature Set:
> Single User Mode document.
>
> To be used later in Reactivate method implementation.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> 1 file changed, 1 insertion(+)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (3 preceding siblings ...)
2026-02-06 14:17 ` [PATCH v3 3/9] sed-opal: add Admin1PIN parameter Ondrej Kozina
@ 2026-02-06 14:17 ` Ondrej Kozina
2026-02-06 15:32 ` Milan Broz
2026-02-06 14:17 ` [PATCH v3 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals Ondrej Kozina
` (4 subsequent siblings)
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:17 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This adds the 'Reactivate' method as described in the
"TCG Storage Opal SSC Feature Set: Single User Mode"
document (ch. 3.1.1.1).
The method enables switching an already active SED OPAL2 device,
with appropriate firmware support for Single User Mode (SUM),
to or from SUM.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
block/sed-opal.c | 99 +++++++++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 14 +++++
4 files changed, 115 insertions(+)
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 13ed2dd83c5d..a8d18afb3eba 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)
{
@@ -2956,6 +3026,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)
{
@@ -3314,6 +3410,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 */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
2026-02-06 14:17 ` [PATCH v3 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
@ 2026-02-06 15:32 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:32 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:17 PM, Ondrej Kozina wrote:
> This adds the 'Reactivate' method as described in the
> "TCG Storage Opal SSC Feature Set: Single User Mode"
> document (ch. 3.1.1.1).
>
> The method enables switching an already active SED OPAL2 device,
> with appropriate firmware support for Single User Mode (SUM),
> to or from SUM.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> block/sed-opal.c | 99 +++++++++++++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 14 +++++
> 4 files changed, 115 insertions(+)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (4 preceding siblings ...)
2026-02-06 14:17 ` [PATCH v3 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
@ 2026-02-06 14:17 ` Ondrej Kozina
2026-02-06 15:33 ` Milan Broz
2026-02-06 14:18 ` [PATCH v3 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl Ondrej Kozina
` (3 subsequent siblings)
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:17 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
IOC_OPAL_LR_SETUP is used to set up a locking range entirely under a
single authority (usually Admin1), but for Single User Mode (SUM),
the permissions for attributes (RangeStart, RangeLength)
and (ReadLockEnable, WriteLockEnable, ReadLocked, WriteLocked)
may be split between two different authorities. Typically, it is Admin1
for the former and the User associated with the LockingRange in SUM
for the latter.
This commit only splits the internals in preparation for the introduction
of separate ioctls for setting RangeStart, RangeLength and the rest
using new ioctl calls.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 73 +++++++++++++++++++++++++++++-------------------
1 file changed, 45 insertions(+), 28 deletions(-)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index a8d18afb3eba..502ff9b0940b 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1518,7 +1518,7 @@ static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
return err;
}
-static int setup_locking_range(struct opal_dev *dev, void *data)
+static int setup_enable_range(struct opal_dev *dev, void *data)
{
u8 uid[OPAL_UID_LENGTH];
struct opal_user_lr_setup *setup = data;
@@ -1532,38 +1532,47 @@ static int setup_locking_range(struct opal_dev *dev, void *data)
if (lr == 0)
err = enable_global_lr(dev, uid, setup);
- else {
- err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
+ else
+ err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE, 0, 0);
+ if (err) {
+ pr_debug("Failed to create enable lr command.\n");
+ return err;
+ }
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_VALUES);
- add_token_u8(&err, dev, OPAL_STARTLIST);
+ return finalize_and_send(dev, parse_and_check_status);
+}
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_RANGESTART);
- add_token_u64(&err, dev, setup->range_start);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+static int setup_locking_range_start_length(struct opal_dev *dev, void *data)
+{
+ int err;
+ u8 uid[OPAL_UID_LENGTH];
+ struct opal_user_lr_setup *setup = data;
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_RANGELENGTH);
- add_token_u64(&err, dev, setup->range_length);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ err = build_locking_range(uid, sizeof(uid), setup->session.opal_key.lr);
+ if (err)
+ return err;
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_READLOCKENABLED);
- add_token_u64(&err, dev, !!setup->RLE);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_WRITELOCKENABLED);
- add_token_u64(&err, dev, !!setup->WLE);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_VALUES);
+ add_token_u8(&err, dev, OPAL_STARTLIST);
+
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_RANGESTART);
+ add_token_u64(&err, dev, setup->range_start);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_RANGELENGTH);
+ add_token_u64(&err, dev, setup->range_length);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+
+ add_token_u8(&err, dev, OPAL_ENDLIST);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
- add_token_u8(&err, dev, OPAL_ENDLIST);
- add_token_u8(&err, dev, OPAL_ENDNAME);
- }
if (err) {
- pr_debug("Error building Setup Locking range command.\n");
+ pr_debug("Error building Setup Locking RangeStartLength command.\n");
return err;
}
@@ -3057,7 +3066,12 @@ static int opal_setup_locking_range(struct opal_dev *dev,
{
const struct opal_step lr_steps[] = {
{ start_auth_opal_session, &opal_lrs->session },
- { setup_locking_range, opal_lrs },
+ { setup_locking_range_start_length, opal_lrs },
+ { setup_enable_range, opal_lrs },
+ { end_opal_session, }
+ }, lr_global_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_enable_range, opal_lrs },
{ end_opal_session, }
};
int ret;
@@ -3067,7 +3081,10 @@ static int opal_setup_locking_range(struct opal_dev *dev,
return ret;
mutex_lock(&dev->dev_lock);
setup_opal_dev(dev);
- ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ if (opal_lrs->session.opal_key.lr == 0)
+ ret = execute_steps(dev, lr_global_steps, ARRAY_SIZE(lr_global_steps));
+ else
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
mutex_unlock(&dev->dev_lock);
return ret;
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
2026-02-06 14:17 ` [PATCH v3 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals Ondrej Kozina
@ 2026-02-06 15:33 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:33 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:17 PM, Ondrej Kozina wrote:
> IOC_OPAL_LR_SETUP is used to set up a locking range entirely under a
> single authority (usually Admin1), but for Single User Mode (SUM),
> the permissions for attributes (RangeStart, RangeLength)
> and (ReadLockEnable, WriteLockEnable, ReadLocked, WriteLocked)
> may be split between two different authorities. Typically, it is Admin1
> for the former and the User associated with the LockingRange in SUM
> for the latter.
>
> This commit only splits the internals in preparation for the introduction
> of separate ioctls for setting RangeStart, RangeLength and the rest
> using new ioctl calls.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/sed-opal.c | 73 +++++++++++++++++++++++++++++-------------------
> 1 file changed, 45 insertions(+), 28 deletions(-)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (5 preceding siblings ...)
2026-02-06 14:17 ` [PATCH v3 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals Ondrej Kozina
@ 2026-02-06 14:18 ` Ondrej Kozina
2026-02-06 15:34 ` Milan Broz
2026-02-06 14:18 ` [PATCH v3 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR Ondrej Kozina
` (2 subsequent siblings)
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:18 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This ioctl is used to set up locking range start (offset)
and locking range length attributes only.
In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
is set in the 'Reactivate' method, only Admin authority maintains the
locking range length and start (offset) attributes of Locking objects
set up for SUM. All other attributes from struct opal_user_lr_setup
(RLE - read locking enabled, WLE - write locking enabled) shall
remain in possession of the User authority associated with the Locking
object set for SUM.
Therefore, we need a separate function for setting up locking range
start and locking range length because it may require two different
authorities (and sessions) if the RangeStartRangeLengthPolicy attribute
is set.
With the IOC_OPAL_LR_SET_START_LEN ioctl, the opal_user_lr_setup
members 'RLE' and 'WLE' of the ioctl argument are ignored.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 28 ++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 1 +
3 files changed, 30 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 502ff9b0940b..07b68cae362d 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3090,6 +3090,31 @@ static int opal_setup_locking_range(struct opal_dev *dev,
return ret;
}
+static int opal_setup_locking_range_start_length(struct opal_dev *dev,
+ struct opal_user_lr_setup *opal_lrs)
+{
+ const struct opal_step lr_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_locking_range_start_length, opal_lrs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ /* we can not set global locking range offset or length */
+ if (opal_lrs->session.opal_key.lr == 0)
+ return -EINVAL;
+
+ ret = opal_get_key(dev, &opal_lrs->session.opal_key);
+ if (ret)
+ return ret;
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_locking_range_status(struct opal_dev *dev,
struct opal_lr_status *opal_lrst,
void __user *data)
@@ -3430,6 +3455,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_REACTIVATE_LSP:
ret = opal_reactivate_lsp(dev, p);
break;
+ case IOC_OPAL_LR_SET_START_LEN:
+ ret = opal_setup_locking_range_start_length(dev, p);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 2ae5e6b0ac21..a0df6819b0a9 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -54,6 +54,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_REVERT_LSP:
case IOC_OPAL_SET_SID_PW:
case IOC_OPAL_REACTIVATE_LSP:
+ case IOC_OPAL_LR_SET_START_LEN:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index d03e590b6501..82de38f3fbeb 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -230,5 +230,6 @@ struct opal_revert_lsp {
#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)
+#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
2026-02-06 14:18 ` [PATCH v3 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl Ondrej Kozina
@ 2026-02-06 15:34 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:34 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:18 PM, Ondrej Kozina wrote:
> This ioctl is used to set up locking range start (offset)
> and locking range length attributes only.
>
> In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
> is set in the 'Reactivate' method, only Admin authority maintains the
> locking range length and start (offset) attributes of Locking objects
> set up for SUM. All other attributes from struct opal_user_lr_setup
> (RLE - read locking enabled, WLE - write locking enabled) shall
> remain in possession of the User authority associated with the Locking
> object set for SUM.
>
> Therefore, we need a separate function for setting up locking range
> start and locking range length because it may require two different
> authorities (and sessions) if the RangeStartRangeLengthPolicy attribute
> is set.
>
> With the IOC_OPAL_LR_SET_START_LEN ioctl, the opal_user_lr_setup
> members 'RLE' and 'WLE' of the ioctl argument are ignored.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/sed-opal.c | 28 ++++++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 1 +
> 3 files changed, 30 insertions(+)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (6 preceding siblings ...)
2026-02-06 14:18 ` [PATCH v3 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl Ondrej Kozina
@ 2026-02-06 14:18 ` Ondrej Kozina
2026-02-06 15:35 ` Milan Broz
2026-02-06 14:18 ` [PATCH v3 8/9] sed-opal: increase column attribute type size to 64 bits Ondrej Kozina
2026-02-06 14:18 ` [PATCH v3 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:18 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This ioctl is used to set up RLE (read lock enabled) and WLE (write
lock enabled) parameters of the Locking object.
In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
is set in the 'Reactivate' method, only Admin authority maintains the
locking range length and start (offset) attributes of Locking objects
set up for SUM. All other attributes from struct opal_user_lr_setup
(RLE - read locking enabled, WLE - write locking enabled) shall
remain in possession of the User authority associated with the Locking
object set for SUM.
With the IOC_OPAL_ENABLE_DISABLE_LR ioctl, the opal_user_lr_setup
members 'range_start' and 'range_length' of the ioctl argument are
ignored.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 24 ++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 1 +
3 files changed, 26 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 07b68cae362d..edde7fa52ab3 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3115,6 +3115,27 @@ static int opal_setup_locking_range_start_length(struct opal_dev *dev,
return ret;
}
+static int opal_enable_disable_range(struct opal_dev *dev,
+ struct opal_user_lr_setup *opal_lrs)
+{
+ const struct opal_step lr_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_enable_range, opal_lrs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ ret = opal_get_key(dev, &opal_lrs->session.opal_key);
+ if (ret)
+ return ret;
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_locking_range_status(struct opal_dev *dev,
struct opal_lr_status *opal_lrst,
void __user *data)
@@ -3458,6 +3479,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_LR_SET_START_LEN:
ret = opal_setup_locking_range_start_length(dev, p);
break;
+ case IOC_OPAL_ENABLE_DISABLE_LR:
+ ret = opal_enable_disable_range(dev, p);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index a0df6819b0a9..1d63479838cf 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -55,6 +55,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_SET_SID_PW:
case IOC_OPAL_REACTIVATE_LSP:
case IOC_OPAL_LR_SET_START_LEN:
+ case IOC_OPAL_ENABLE_DISABLE_LR:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 82de38f3fbeb..bde023ae2295 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -231,5 +231,6 @@ 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)
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
+#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
2026-02-06 14:18 ` [PATCH v3 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR Ondrej Kozina
@ 2026-02-06 15:35 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:35 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:18 PM, Ondrej Kozina wrote:
> This ioctl is used to set up RLE (read lock enabled) and WLE (write
> lock enabled) parameters of the Locking object.
>
> In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
> is set in the 'Reactivate' method, only Admin authority maintains the
> locking range length and start (offset) attributes of Locking objects
> set up for SUM. All other attributes from struct opal_user_lr_setup
> (RLE - read locking enabled, WLE - write locking enabled) shall
> remain in possession of the User authority associated with the Locking
> object set for SUM.
>
> With the IOC_OPAL_ENABLE_DISABLE_LR ioctl, the opal_user_lr_setup
> members 'range_start' and 'range_length' of the ioctl argument are
> ignored.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/sed-opal.c | 24 ++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 1 +
> 3 files changed, 26 insertions(+)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v3 8/9] sed-opal: increase column attribute type size to 64 bits.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (7 preceding siblings ...)
2026-02-06 14:18 ` [PATCH v3 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR Ondrej Kozina
@ 2026-02-06 14:18 ` Ondrej Kozina
2026-02-06 15:35 ` Milan Broz
2026-02-06 14:18 ` [PATCH v3 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:18 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
Change the column parameter in response_get_column() from u8 to u64
to support the full range of column identifiers.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index edde7fa52ab3..aec5f4708987 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1581,7 +1581,7 @@ static int setup_locking_range_start_length(struct opal_dev *dev, void *data)
static int response_get_column(const struct parsed_resp *resp,
int *iter,
- u8 column,
+ u64 column,
u64 *value)
{
const struct opal_resp_tok *tok;
@@ -1599,7 +1599,7 @@ static int response_get_column(const struct parsed_resp *resp,
n++;
if (response_get_u64(resp, n) != column) {
- pr_debug("Token %d does not match expected column %u.\n",
+ pr_debug("Token %d does not match expected column %llu.\n",
n, column);
return OPAL_INVAL_PARAM;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH v3 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
` (8 preceding siblings ...)
2026-02-06 14:18 ` [PATCH v3 8/9] sed-opal: increase column attribute type size to 64 bits Ondrej Kozina
@ 2026-02-06 14:18 ` Ondrej Kozina
2026-02-06 15:36 ` Milan Broz
9 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-06 14:18 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This adds a function for retrieving the set of Locking objects enabled
for Single User Mode (SUM) and the value of the
RangeStartRangeLengthPolicy parameter.
It retrieves data from the LockingInfo table, specifically the
columns SingleUserModeRanges and RangeStartLengthPolicy, which
were added according to the TCG Opal Feature Set: Single User Mode,
as described in chapters 4.4.3.1 and 4.4.3.2.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 159 ++++++++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 13 +++
3 files changed, 173 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index aec5f4708987..718c50565e49 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1757,6 +1757,12 @@ static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
OPAL_ADMINSP_UID, NULL, 0);
}
+static int start_anybodyLSP_opal_session(struct opal_dev *dev, void *data)
+{
+ return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
+ OPAL_LOCKINGSP_UID, NULL, 0);
+}
+
static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
{
int ret;
@@ -3388,6 +3394,156 @@ static int opal_get_geometry(struct opal_dev *dev, void __user *data)
return 0;
}
+static int get_sum_ranges(struct opal_dev *dev, void *data)
+{
+ const char *lr_uid;
+ size_t lr_uid_len;
+ u64 val;
+ const struct opal_resp_tok *tok;
+ int err, tok_n = 2;
+ struct opal_sum_ranges *sranges = data;
+ const __u8 lr_all[OPAL_MAX_LRS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ err = generic_get_columns(dev, opaluid[OPAL_LOCKING_INFO_TABLE], OPAL_SUM_SET_LIST,
+ OPAL_SUM_RANGE_POLICY);
+ if (err) {
+ pr_debug("Couldn't get locking info table columns %d to %d.\n",
+ OPAL_SUM_SET_LIST, OPAL_SUM_RANGE_POLICY);
+ return err;
+ }
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ if (!response_token_matches(tok, OPAL_STARTNAME)) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ if (response_get_u64(&dev->parsed, tok_n) != OPAL_SUM_SET_LIST) {
+ pr_debug("Token %d does not match expected column %u.\n",
+ tok_n, OPAL_SUM_SET_LIST);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ /*
+ * The OPAL_SUM_SET_LIST response contains two distinct values:
+ *
+ * - the list of individual locking ranges (UIDs) put in SUM. The list
+ * may also be empty signaling the SUM is disabled.
+ *
+ * - the Locking table UID if the entire Locking table is put in SUM.
+ */
+ if (response_token_matches(tok, OPAL_STARTLIST)) {
+ sranges->num_lrs = 0;
+
+ tok_n++;
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ while (!response_token_matches(tok, OPAL_ENDLIST)) {
+ lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
+ if (lr_uid_len != OPAL_UID_LENGTH) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+
+ if (memcmp(lr_uid, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH)) {
+ if (lr_uid[5] != LOCKING_RANGE_NON_GLOBAL) {
+ pr_debug("Unexpected byte %d at LR UUID position 5.\n",
+ lr_uid[5]);
+ return OPAL_INVAL_PARAM;
+ }
+ sranges->lr[sranges->num_lrs++] = lr_uid[7];
+ } else
+ sranges->lr[sranges->num_lrs++] = 0;
+
+ tok_n++;
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+ }
+ } else {
+ /* Only OPAL_LOCKING_TABLE UID is an alternative to OPAL_STARTLIST here. */
+ lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
+ if (lr_uid_len != OPAL_UID_LENGTH) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+
+ if (memcmp(lr_uid, opaluid[OPAL_LOCKING_TABLE], OPAL_UID_LENGTH)) {
+ pr_debug("Unexpected response UID.\n");
+ return OPAL_INVAL_PARAM;
+ }
+
+ /* sed-opal kernel API already provides following limit in Activate command */
+ sranges->num_lrs = OPAL_MAX_LRS;
+ memcpy(sranges->lr, lr_all, OPAL_MAX_LRS);
+ }
+ tok_n++;
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ if (!response_token_matches(tok, OPAL_ENDNAME)) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ err = response_get_column(&dev->parsed, &tok_n, OPAL_SUM_RANGE_POLICY, &val);
+ if (err)
+ return err;
+
+ sranges->range_policy = val ? 1 : 0;
+
+ return 0;
+}
+
+static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opal_sum_rngs,
+ void __user *data)
+{
+ const struct opal_step admin_steps[] = {
+ { start_admin1LSP_opal_session, &opal_sum_rngs->key },
+ { get_sum_ranges, opal_sum_rngs },
+ { end_opal_session, }
+ }, anybody_steps[] = {
+ { start_anybodyLSP_opal_session, NULL },
+ { get_sum_ranges, opal_sum_rngs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ if (opal_sum_rngs->key.key_len)
+ /* Use Admin1 session (authenticated by PIN) to retrieve LockingInfo columns */
+ ret = execute_steps(dev, admin_steps, ARRAY_SIZE(admin_steps));
+ else
+ /* Use Anybody session (no key) to retrieve LockingInfo columns */
+ ret = execute_steps(dev, anybody_steps, ARRAY_SIZE(anybody_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ /* skip session info when copying back to uspace */
+ if (!ret && copy_to_user(data + offsetof(struct opal_sum_ranges, num_lrs),
+ (void *)opal_sum_rngs + offsetof(struct opal_sum_ranges, num_lrs),
+ sizeof(*opal_sum_rngs) - offsetof(struct opal_sum_ranges, num_lrs))) {
+ pr_debug("Error copying SUM ranges info to userspace\n");
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
{
void *p;
@@ -3482,6 +3638,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_ENABLE_DISABLE_LR:
ret = opal_enable_disable_range(dev, p);
break;
+ case IOC_OPAL_GET_SUM_STATUS:
+ ret = opal_get_sum_ranges(dev, p, arg);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 1d63479838cf..aa006edb612b 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -56,6 +56,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_REACTIVATE_LSP:
case IOC_OPAL_LR_SET_START_LEN:
case IOC_OPAL_ENABLE_DISABLE_LR:
+ case IOC_OPAL_GET_SUM_STATUS:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index bde023ae2295..9830298ec51c 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -111,6 +111,18 @@ struct opal_lr_status {
__u8 align[4];
};
+struct opal_sum_ranges {
+ /*
+ * Initiate Admin1 session if key_len > 0,
+ * use Anybody session otherwise.
+ */
+ struct opal_key key;
+ __u8 num_lrs;
+ __u8 lr[OPAL_MAX_LRS];
+ __u8 range_policy;
+ __u8 align[5]; /* Align to 8 byte boundary */
+};
+
struct opal_lock_unlock {
struct opal_session_info session;
__u32 l_state;
@@ -232,5 +244,6 @@ struct opal_revert_lsp {
#define IOC_OPAL_REACTIVATE_LSP _IOW('p', 242, struct opal_lr_react)
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
+#define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v3 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
2026-02-06 14:18 ` [PATCH v3 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
@ 2026-02-06 15:36 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 15:36 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/6/26 3:18 PM, Ondrej Kozina wrote:
> This adds a function for retrieving the set of Locking objects enabled
> for Single User Mode (SUM) and the value of the
> RangeStartRangeLengthPolicy parameter.
>
> It retrieves data from the LockingInfo table, specifically the
> columns SingleUserModeRanges and RangeStartLengthPolicy, which
> were added according to the TCG Opal Feature Set: Single User Mode,
> as described in chapters 4.4.3.1 and 4.4.3.2.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/sed-opal.c | 159 ++++++++++++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 13 +++
> 3 files changed, 173 insertions(+)
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v2 1/9] sed-opal: add UID of Locking Table.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (7 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 0/9] " Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-06 0:04 ` Hannes Reinecke
2026-02-05 15:09 ` [PATCH v2 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter Ondrej Kozina
` (7 subsequent siblings)
16 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
As described in ch. 6.3, Table 240 in TCG Storage
Architecture Core Specification document.
It's also referenced in TCG Storage Opal SSC Feature Set:
Single User Mode document, ch. 3.1.1.1 Reactivate method.
It will be used later in Reactivate method implemetation
for sed-opal interface.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
block/sed-opal.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index d247a457bf6e..3dfba3de7be1 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -125,6 +125,7 @@ enum opal_uid {
OPAL_LOCKING_INFO_TABLE,
OPAL_ENTERPRISE_LOCKING_INFO_TABLE,
OPAL_DATASTORE,
+ OPAL_LOCKING_TABLE,
/* C_PIN_TABLE object ID's */
OPAL_C_PIN_MSID,
OPAL_C_PIN_SID,
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 5a28f23f7f22..13ed2dd83c5d 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -160,6 +160,8 @@ static const u8 opaluid[][OPAL_UID_LENGTH] = {
{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
[OPAL_DATASTORE] =
{ 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00 },
+ [OPAL_LOCKING_TABLE] =
+ { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00 },
/* C_PIN_TABLE object ID's */
[OPAL_C_PIN_MSID] =
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v2 1/9] sed-opal: add UID of Locking Table.
2026-02-05 15:09 ` [PATCH v2 1/9] sed-opal: add UID of Locking Table Ondrej Kozina
@ 2026-02-06 0:04 ` Hannes Reinecke
0 siblings, 0 replies; 48+ messages in thread
From: Hannes Reinecke @ 2026-02-06 0:04 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gmazyland, jonathan.derrick, gjoyce
On 2/5/26 16:09, Ondrej Kozina wrote:
> As described in ch. 6.3, Table 240 in TCG Storage
> Architecture Core Specification document.
>
> It's also referenced in TCG Storage Opal SSC Feature Set:
> Single User Mode document, ch. 3.1.1.1 Reactivate method.
>
> It will be used later in Reactivate method implemetation
> for sed-opal interface.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> block/sed-opal.c | 2 ++
> 2 files changed, 3 insertions(+)
>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v2 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (8 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 1/9] sed-opal: add UID of Locking Table Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-06 0:05 ` Hannes Reinecke
2026-02-05 15:09 ` [PATCH v2 3/9] sed-opal: add Admin1PIN parameter Ondrej Kozina
` (6 subsequent siblings)
16 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
As desribed in ch. 3.1.1.1.1.2 of TCG Storage Opal SSC Feature Set:
Single User Mode document.
To be used later in Reactivate method implementation and in function
for retrieving SUM device status.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index 3dfba3de7be1..b9877eacfe91 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -225,6 +225,7 @@ enum opal_lockingstate {
enum opal_parameter {
OPAL_SUM_SET_LIST = 0x060000,
+ OPAL_SUM_RANGE_POLICY = 0x060001,
};
enum opal_revertlsp {
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v2 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter.
2026-02-05 15:09 ` [PATCH v2 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter Ondrej Kozina
@ 2026-02-06 0:05 ` Hannes Reinecke
0 siblings, 0 replies; 48+ messages in thread
From: Hannes Reinecke @ 2026-02-06 0:05 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gmazyland, jonathan.derrick, gjoyce
On 2/5/26 16:09, Ondrej Kozina wrote:
> As desribed in ch. 3.1.1.1.1.2 of TCG Storage Opal SSC Feature Set:
> Single User Mode document.
>
> To be used later in Reactivate method implementation and in function
> for retrieving SUM device status.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/block/opal_proto.h b/block/opal_proto.h
> index 3dfba3de7be1..b9877eacfe91 100644
> --- a/block/opal_proto.h
> +++ b/block/opal_proto.h
> @@ -225,6 +225,7 @@ enum opal_lockingstate {
>
> enum opal_parameter {
> OPAL_SUM_SET_LIST = 0x060000,
> + OPAL_SUM_RANGE_POLICY = 0x060001,
> };
>
> enum opal_revertlsp {
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v2 3/9] sed-opal: add Admin1PIN parameter.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (9 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 2/9] sed-opal: add RangeStartRangeLengthPolicy parameter Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-06 0:06 ` Hannes Reinecke
2026-02-05 15:09 ` [PATCH v2 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
` (5 subsequent siblings)
16 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
As desribed in ch. 3.1.1.1.1.3 of TCG Storage Opal SSC Feature Set:
Single User Mode document.
To be used later in Reactivate method implementation.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index b9877eacfe91..3ccee5977c10 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -226,6 +226,7 @@ enum opal_lockingstate {
enum opal_parameter {
OPAL_SUM_SET_LIST = 0x060000,
OPAL_SUM_RANGE_POLICY = 0x060001,
+ OPAL_SUM_ADMIN1_PIN = 0x060002,
};
enum opal_revertlsp {
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v2 3/9] sed-opal: add Admin1PIN parameter.
2026-02-05 15:09 ` [PATCH v2 3/9] sed-opal: add Admin1PIN parameter Ondrej Kozina
@ 2026-02-06 0:06 ` Hannes Reinecke
0 siblings, 0 replies; 48+ messages in thread
From: Hannes Reinecke @ 2026-02-06 0:06 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gmazyland, jonathan.derrick, gjoyce
On 2/5/26 16:09, Ondrej Kozina wrote:
> As desribed in ch. 3.1.1.1.1.3 of TCG Storage Opal SSC Feature Set:
> Single User Mode document.
>
> To be used later in Reactivate method implementation.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/block/opal_proto.h b/block/opal_proto.h
> index b9877eacfe91..3ccee5977c10 100644
> --- a/block/opal_proto.h
> +++ b/block/opal_proto.h
> @@ -226,6 +226,7 @@ enum opal_lockingstate {
> enum opal_parameter {
> OPAL_SUM_SET_LIST = 0x060000,
> OPAL_SUM_RANGE_POLICY = 0x060001,
> + OPAL_SUM_ADMIN1_PIN = 0x060002,
> };
>
> enum opal_revertlsp {
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v2 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (10 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 3/9] sed-opal: add Admin1PIN parameter Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-06 0:08 ` Hannes Reinecke
2026-02-05 15:09 ` [PATCH v2 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals Ondrej Kozina
` (4 subsequent siblings)
16 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This adds the 'Reactivate' method as described in the
"TCG Storage Opal SSC Feature Set: Single User Mode"
document (ch. 3.1.1.1).
The method enables switching an already active SED OPAL2 device,
with appropriate firmware support for Single User Mode (SUM),
to or from SUM.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/opal_proto.h | 1 +
block/sed-opal.c | 99 +++++++++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 14 +++++
4 files changed, 115 insertions(+)
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 13ed2dd83c5d..a8d18afb3eba 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)
{
@@ -2956,6 +3026,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)
{
@@ -3314,6 +3410,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 */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v2 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP.
2026-02-05 15:09 ` [PATCH v2 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
@ 2026-02-06 0:08 ` Hannes Reinecke
0 siblings, 0 replies; 48+ messages in thread
From: Hannes Reinecke @ 2026-02-06 0:08 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: gmazyland, jonathan.derrick, gjoyce
On 2/5/26 16:09, Ondrej Kozina wrote:
> This adds the 'Reactivate' method as described in the
> "TCG Storage Opal SSC Feature Set: Single User Mode"
> document (ch. 3.1.1.1).
>
> The method enables switching an already active SED OPAL2 device,
> with appropriate firmware support for Single User Mode (SUM),
> to or from SUM.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
> ---
> block/opal_proto.h | 1 +
> block/sed-opal.c | 99 +++++++++++++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 14 +++++
> 4 files changed, 115 insertions(+)
>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v2 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (11 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 4/9] sed-opal: add IOC_OPAL_REACTIVATE_LSP Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-05 15:09 ` [PATCH v2 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl Ondrej Kozina
` (3 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
IOC_OPAL_LR_SETUP is used to set up a locking range entirely under a
single authority (usually Admin1), but for Single User Mode (SUM),
the permissions for attributes (RangeStart, RangeLength)
and (ReadLockEnable, WriteLockEnable, ReadLocked, WriteLocked)
may be split between two different authorities. Typically, it is Admin1
for the former and the User associated with the LockingRange in SUM
for the latter.
This commit only splits the internals in preparation for the introduction
of separate ioctls for setting RangeStart, RangeLength and the rest
using new ioctl calls.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 73 +++++++++++++++++++++++++++++-------------------
1 file changed, 45 insertions(+), 28 deletions(-)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index a8d18afb3eba..502ff9b0940b 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1518,7 +1518,7 @@ static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
return err;
}
-static int setup_locking_range(struct opal_dev *dev, void *data)
+static int setup_enable_range(struct opal_dev *dev, void *data)
{
u8 uid[OPAL_UID_LENGTH];
struct opal_user_lr_setup *setup = data;
@@ -1532,38 +1532,47 @@ static int setup_locking_range(struct opal_dev *dev, void *data)
if (lr == 0)
err = enable_global_lr(dev, uid, setup);
- else {
- err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
+ else
+ err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE, 0, 0);
+ if (err) {
+ pr_debug("Failed to create enable lr command.\n");
+ return err;
+ }
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_VALUES);
- add_token_u8(&err, dev, OPAL_STARTLIST);
+ return finalize_and_send(dev, parse_and_check_status);
+}
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_RANGESTART);
- add_token_u64(&err, dev, setup->range_start);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+static int setup_locking_range_start_length(struct opal_dev *dev, void *data)
+{
+ int err;
+ u8 uid[OPAL_UID_LENGTH];
+ struct opal_user_lr_setup *setup = data;
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_RANGELENGTH);
- add_token_u64(&err, dev, setup->range_length);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ err = build_locking_range(uid, sizeof(uid), setup->session.opal_key.lr);
+ if (err)
+ return err;
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_READLOCKENABLED);
- add_token_u64(&err, dev, !!setup->RLE);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
- add_token_u8(&err, dev, OPAL_STARTNAME);
- add_token_u8(&err, dev, OPAL_WRITELOCKENABLED);
- add_token_u64(&err, dev, !!setup->WLE);
- add_token_u8(&err, dev, OPAL_ENDNAME);
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_VALUES);
+ add_token_u8(&err, dev, OPAL_STARTLIST);
+
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_RANGESTART);
+ add_token_u64(&err, dev, setup->range_start);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+
+ add_token_u8(&err, dev, OPAL_STARTNAME);
+ add_token_u8(&err, dev, OPAL_RANGELENGTH);
+ add_token_u64(&err, dev, setup->range_length);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
+
+ add_token_u8(&err, dev, OPAL_ENDLIST);
+ add_token_u8(&err, dev, OPAL_ENDNAME);
- add_token_u8(&err, dev, OPAL_ENDLIST);
- add_token_u8(&err, dev, OPAL_ENDNAME);
- }
if (err) {
- pr_debug("Error building Setup Locking range command.\n");
+ pr_debug("Error building Setup Locking RangeStartLength command.\n");
return err;
}
@@ -3057,7 +3066,12 @@ static int opal_setup_locking_range(struct opal_dev *dev,
{
const struct opal_step lr_steps[] = {
{ start_auth_opal_session, &opal_lrs->session },
- { setup_locking_range, opal_lrs },
+ { setup_locking_range_start_length, opal_lrs },
+ { setup_enable_range, opal_lrs },
+ { end_opal_session, }
+ }, lr_global_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_enable_range, opal_lrs },
{ end_opal_session, }
};
int ret;
@@ -3067,7 +3081,10 @@ static int opal_setup_locking_range(struct opal_dev *dev,
return ret;
mutex_lock(&dev->dev_lock);
setup_opal_dev(dev);
- ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ if (opal_lrs->session.opal_key.lr == 0)
+ ret = execute_steps(dev, lr_global_steps, ARRAY_SIZE(lr_global_steps));
+ else
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
mutex_unlock(&dev->dev_lock);
return ret;
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH v2 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (12 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 5/9] sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-05 15:09 ` [PATCH v2 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR Ondrej Kozina
` (2 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This ioctl is used to set up locking range start (offset)
and locking range length attributes only.
In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
is set in the 'Reactivate' method, only Admin authority maintains the
locking range length and start (offset) attributes of Locking objects
set up for SUM. All other attributes from struct opal_user_lr_setup
(RLE - read locking enabled, WLE - write locking enabled) shall
remain in possession of the User authority associated with the Locking
object set for SUM.
Therefore, we need a separate function for setting up locking range
start and locking range length because it may require two different
authorities (and sessions) if the RangeStartRangeLengthPolicy attribute
is set.
With the IOC_OPAL_LR_SET_START_LEN ioctl, the opal_user_lr_setup
members 'RLE' and 'WLE' of the ioctl argument are ignored.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 28 ++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 1 +
3 files changed, 30 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 502ff9b0940b..07b68cae362d 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3090,6 +3090,31 @@ static int opal_setup_locking_range(struct opal_dev *dev,
return ret;
}
+static int opal_setup_locking_range_start_length(struct opal_dev *dev,
+ struct opal_user_lr_setup *opal_lrs)
+{
+ const struct opal_step lr_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_locking_range_start_length, opal_lrs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ /* we can not set global locking range offset or length */
+ if (opal_lrs->session.opal_key.lr == 0)
+ return -EINVAL;
+
+ ret = opal_get_key(dev, &opal_lrs->session.opal_key);
+ if (ret)
+ return ret;
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_locking_range_status(struct opal_dev *dev,
struct opal_lr_status *opal_lrst,
void __user *data)
@@ -3430,6 +3455,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_REACTIVATE_LSP:
ret = opal_reactivate_lsp(dev, p);
break;
+ case IOC_OPAL_LR_SET_START_LEN:
+ ret = opal_setup_locking_range_start_length(dev, p);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 2ae5e6b0ac21..a0df6819b0a9 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -54,6 +54,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_REVERT_LSP:
case IOC_OPAL_SET_SID_PW:
case IOC_OPAL_REACTIVATE_LSP:
+ case IOC_OPAL_LR_SET_START_LEN:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index d03e590b6501..82de38f3fbeb 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -230,5 +230,6 @@ struct opal_revert_lsp {
#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)
+#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH v2 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (13 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 6/9] sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-05 15:09 ` [PATCH v2 8/9] sed-opal: increase column attribute type size to 64 bits Ondrej Kozina
2026-02-05 15:09 ` [PATCH v2 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This ioctl is used to set up RLE (read lock enabled) and WLE (write
lock enabled) parameters of the Locking object.
In Single User Mode (SUM), if the RangeStartRangeLengthPolicy parameter
is set in the 'Reactivate' method, only Admin authority maintains the
locking range length and start (offset) attributes of Locking objects
set up for SUM. All other attributes from struct opal_user_lr_setup
(RLE - read locking enabled, WLE - write locking enabled) shall
remain in possession of the User authority associated with the Locking
object set for SUM.
With the IOC_OPAL_ENABLE_DISABLE_LR ioctl, the opal_user_lr_setup
members 'range_start' and 'range_length' of the ioctl argument are
ignored.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 24 ++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 1 +
3 files changed, 26 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 07b68cae362d..edde7fa52ab3 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3115,6 +3115,27 @@ static int opal_setup_locking_range_start_length(struct opal_dev *dev,
return ret;
}
+static int opal_enable_disable_range(struct opal_dev *dev,
+ struct opal_user_lr_setup *opal_lrs)
+{
+ const struct opal_step lr_steps[] = {
+ { start_auth_opal_session, &opal_lrs->session },
+ { setup_enable_range, opal_lrs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ ret = opal_get_key(dev, &opal_lrs->session.opal_key);
+ if (ret)
+ return ret;
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_locking_range_status(struct opal_dev *dev,
struct opal_lr_status *opal_lrst,
void __user *data)
@@ -3458,6 +3479,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_LR_SET_START_LEN:
ret = opal_setup_locking_range_start_length(dev, p);
break;
+ case IOC_OPAL_ENABLE_DISABLE_LR:
+ ret = opal_enable_disable_range(dev, p);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index a0df6819b0a9..1d63479838cf 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -55,6 +55,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_SET_SID_PW:
case IOC_OPAL_REACTIVATE_LSP:
case IOC_OPAL_LR_SET_START_LEN:
+ case IOC_OPAL_ENABLE_DISABLE_LR:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 82de38f3fbeb..bde023ae2295 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -231,5 +231,6 @@ 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)
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
+#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH v2 8/9] sed-opal: increase column attribute type size to 64 bits.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (14 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 7/9] sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-05 15:09 ` [PATCH v2 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
16 siblings, 0 replies; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
Change the column parameter in response_get_column() from u8 to u64
to support the full range of column identifiers.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index edde7fa52ab3..aec5f4708987 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1581,7 +1581,7 @@ static int setup_locking_range_start_length(struct opal_dev *dev, void *data)
static int response_get_column(const struct parsed_resp *resp,
int *iter,
- u8 column,
+ u64 column,
u64 *value)
{
const struct opal_resp_tok *tok;
@@ -1599,7 +1599,7 @@ static int response_get_column(const struct parsed_resp *resp,
n++;
if (response_get_u64(resp, n) != column) {
- pr_debug("Token %d does not match expected column %u.\n",
+ pr_debug("Token %d does not match expected column %llu.\n",
n, column);
return OPAL_INVAL_PARAM;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* [PATCH v2 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
2026-01-30 16:25 [PATCH 0/6] Extend Single User Mode (SUM) support in sed-opal Ondrej Kozina
` (15 preceding siblings ...)
2026-02-05 15:09 ` [PATCH v2 8/9] sed-opal: increase column attribute type size to 64 bits Ondrej Kozina
@ 2026-02-05 15:09 ` Ondrej Kozina
2026-02-06 9:05 ` Milan Broz
16 siblings, 1 reply; 48+ messages in thread
From: Ondrej Kozina @ 2026-02-05 15:09 UTC (permalink / raw)
To: linux-block; +Cc: Ondrej Kozina, gmazyland, jonathan.derrick, gjoyce, hare
This adds a function for retrieving the set of Locking objects enabled
for Single User Mode (SUM) and the value of the
RangeStartRangeLengthPolicy parameter.
Signed-off-by: Ondrej Kozina <okozina@redhat.com>
---
block/sed-opal.c | 157 ++++++++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 9 ++
3 files changed, 167 insertions(+)
diff --git a/block/sed-opal.c b/block/sed-opal.c
index aec5f4708987..1879bb1cd12e 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1757,6 +1757,12 @@ static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
OPAL_ADMINSP_UID, NULL, 0);
}
+static int start_anybodyLSP_opal_session(struct opal_dev *dev, void *data)
+{
+ return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
+ OPAL_LOCKINGSP_UID, NULL, 0);
+}
+
static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
{
int ret;
@@ -3388,6 +3394,154 @@ static int opal_get_geometry(struct opal_dev *dev, void __user *data)
return 0;
}
+static int get_sum_ranges(struct opal_dev *dev, void *data)
+{
+ const char *lr_uid;
+ size_t lr_uid_len;
+ u64 val;
+ const struct opal_resp_tok *tok;
+ int err, tok_n = 2;
+ struct opal_sum_ranges *sranges = data;
+ const __u8 lr_all[OPAL_MAX_LRS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ err = generic_get_columns(dev, opaluid[OPAL_LOCKING_INFO_TABLE], OPAL_SUM_SET_LIST,
+ OPAL_SUM_RANGE_POLICY);
+ if (err) {
+ pr_debug("Couldn't get locking info table columns %d to %d.\n",
+ OPAL_SUM_SET_LIST, OPAL_SUM_RANGE_POLICY);
+ return err;
+ }
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ if (!response_token_matches(tok, OPAL_STARTNAME)) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ if (response_get_u64(&dev->parsed, tok_n) != OPAL_SUM_SET_LIST) {
+ pr_debug("Token %d does not match expected column %u.\n",
+ tok_n, OPAL_SUM_SET_LIST);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ /*
+ * The OPAL_SUM_SET_LIST response contains two distinct values:
+ *
+ * - the list of individual locking ranges (UIDs) put in SUM. The list
+ * may also be empty signaling the SUM is disabled.
+ *
+ * - the Locking table UID if the entire Locking table is put in SUM.
+ */
+ if (response_token_matches(tok, OPAL_STARTLIST)) {
+ sranges->num_lrs = 0;
+
+ tok_n++;
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ while (!response_token_matches(tok, OPAL_ENDLIST)) {
+ lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
+ if (lr_uid_len != OPAL_UID_LENGTH) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+
+ if (memcmp(lr_uid, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH)) {
+ if (lr_uid[5] != LOCKING_RANGE_NON_GLOBAL) {
+ pr_debug("Unexpected byte %d at LR UUID position 5.\n",
+ lr_uid[5]);
+ return OPAL_INVAL_PARAM;
+ }
+ sranges->lr[sranges->num_lrs++] = lr_uid[7];
+ } else
+ sranges->lr[sranges->num_lrs++] = 0;
+
+ tok_n++;
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+ }
+ } else {
+ /* Only OPAL_LOCKING_TABLE UID is an alternative to OPAL_STARTLIST here. */
+ lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid);
+ if (lr_uid_len != OPAL_UID_LENGTH) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+
+ if (memcmp(lr_uid, opaluid[OPAL_LOCKING_TABLE], OPAL_UID_LENGTH)) {
+ pr_debug("Unexpected response UID.\n");
+ return OPAL_INVAL_PARAM;
+ }
+
+ /* sed-opal kernel API already provides following limit in Activate command */
+ sranges->num_lrs = OPAL_MAX_LRS;
+ memcpy(sranges->lr, lr_all, OPAL_MAX_LRS);
+ }
+ tok_n++;
+
+ tok = response_get_token(&dev->parsed, tok_n);
+ if (IS_ERR(tok))
+ return PTR_ERR(tok);
+
+ if (!response_token_matches(tok, OPAL_ENDNAME)) {
+ pr_debug("Unexpected response token type %d.\n", tok_n);
+ return OPAL_INVAL_PARAM;
+ }
+ tok_n++;
+
+ err = response_get_column(&dev->parsed, &tok_n, OPAL_SUM_RANGE_POLICY, &val);
+ if (err)
+ return err;
+
+ sranges->range_policy = val ? 1 : 0;
+
+ return 0;
+}
+
+static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opal_sum_rngs,
+ void __user *data)
+{
+ const struct opal_step admin_steps[] = {
+ { start_admin1LSP_opal_session, &opal_sum_rngs->key },
+ { get_sum_ranges, opal_sum_rngs },
+ { end_opal_session, }
+ }, anybody_steps[] = {
+ { start_anybodyLSP_opal_session, NULL },
+ { get_sum_ranges, opal_sum_rngs },
+ { end_opal_session, }
+ };
+ int ret;
+
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ if (opal_sum_rngs->key.key_len)
+ ret = execute_steps(dev, admin_steps, ARRAY_SIZE(admin_steps));
+ else
+ ret = execute_steps(dev, anybody_steps, ARRAY_SIZE(anybody_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ /* skip session info when copying back to uspace */
+ if (!ret && copy_to_user(data + offsetof(struct opal_sum_ranges, num_lrs),
+ (void *)opal_sum_rngs + offsetof(struct opal_sum_ranges, num_lrs),
+ sizeof(*opal_sum_rngs) - offsetof(struct opal_sum_ranges, num_lrs))) {
+ pr_debug("Error copying SUM ranges info to userspace\n");
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
{
void *p;
@@ -3482,6 +3636,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_ENABLE_DISABLE_LR:
ret = opal_enable_disable_range(dev, p);
break;
+ case IOC_OPAL_GET_SUM_STATUS:
+ ret = opal_get_sum_ranges(dev, p, arg);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 1d63479838cf..aa006edb612b 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -56,6 +56,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_REACTIVATE_LSP:
case IOC_OPAL_LR_SET_START_LEN:
case IOC_OPAL_ENABLE_DISABLE_LR:
+ case IOC_OPAL_GET_SUM_STATUS:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index bde023ae2295..f69d52e1bf40 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -111,6 +111,14 @@ struct opal_lr_status {
__u8 align[4];
};
+struct opal_sum_ranges {
+ struct opal_key key;
+ __u8 num_lrs;
+ __u8 lr[OPAL_MAX_LRS];
+ __u8 range_policy;
+ __u8 align[5]; /* Align to 8 byte boundary */
+};
+
struct opal_lock_unlock {
struct opal_session_info session;
__u32 l_state;
@@ -232,5 +240,6 @@ struct opal_revert_lsp {
#define IOC_OPAL_REACTIVATE_LSP _IOW('p', 242, struct opal_lr_react)
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
+#define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
#endif /* _UAPI_SED_OPAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 48+ messages in thread* Re: [PATCH v2 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.
2026-02-05 15:09 ` [PATCH v2 9/9] sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl Ondrej Kozina
@ 2026-02-06 9:05 ` Milan Broz
0 siblings, 0 replies; 48+ messages in thread
From: Milan Broz @ 2026-02-06 9:05 UTC (permalink / raw)
To: Ondrej Kozina, linux-block; +Cc: jonathan.derrick, gjoyce, hare
On 2/5/26 4:09 PM, Ondrej Kozina wrote:
> This adds a function for retrieving the set of Locking objects enabled
> for Single User Mode (SUM) and the value of the
> RangeStartRangeLengthPolicy parameter.
>
> Signed-off-by: Ondrej Kozina <okozina@redhat.com>
...
> +static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opal_sum_rngs,
> + void __user *data)
> +{
> + const struct opal_step admin_steps[] = {
> + { start_admin1LSP_opal_session, &opal_sum_rngs->key },
> + { get_sum_ranges, opal_sum_rngs },
> + { end_opal_session, }
> + }, anybody_steps[] = {
> + { start_anybodyLSP_opal_session, NULL },
> + { get_sum_ranges, opal_sum_rngs },
> + { end_opal_session, }
> + };
These two variants need some explanation.
IIRC, TCG doc says that SUM info MAY be available through anybody session.
Of course, some vendors implemented it that is it is not, and you have to use
admin session. So we need both variants, that's ok.
Buy you should document how it works for ioctl params - if admin key is set,
admin session is used, otherwise anybody session is used.
> + int ret;
> +
> + mutex_lock(&dev->dev_lock);
> + setup_opal_dev(dev);
> + if (opal_sum_rngs->key.key_len)
So, this requires admin password is at least one char, using empty password for
admin is not possible here. It make sense, but it should be documented at least.
> + ret = execute_steps(dev, admin_steps, ARRAY_SIZE(admin_steps));
> + else
> + ret = execute_steps(dev, anybody_steps, ARRAY_SIZE(anybody_steps));
> + mutex_unlock(&dev->dev_lock);
> +
Otherwise LGTM, even for other patches. If you plan to send v3, I will ack
individual patches.
Thanks,
Milan
^ permalink raw reply [flat|nested] 48+ messages in thread