Skip to content

Commit 91f374c

Browse files
authored
libsed, sedcli: enable blockSID functionality per TCG BlockSID spec
This patch enables the support of BlockSID to block SID authority. The feature supports using Clear Event flag that can determine the blocking can be reset by SSD firmware during hardware reset. Signed-off-by: Winson Yung <[email protected]>
1 parent b7f83e8 commit 91f374c

File tree

8 files changed

+110
-3
lines changed

8 files changed

+110
-3
lines changed

doc/sedcli.8

+3
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ MBR Done update to TRUE will only take effect when MBR Shadow is enabled.
9191
Write data into MBR shadow region(MBR table).
9292
MBR shadow should be enabled for the PBA to take effect.
9393

94+
.IP "\fB\-B -d <device> -r {1|0}\fR or \fB\-\-block_sid --device <device> --hwreset {1|0}\fR"
95+
Issue BlockSID authentication command with Clear Event flag via --hwreset option.
96+
9497
.IP "\fB\-V\fR or \fB\-\-version\fR"
9598
Prints version of sedcli.
9699

src/lib/include/libsed.h

+6
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,12 @@ int sed_mbrdone(struct sed_device *dev, const struct sed_key *key, bool mbr);
353353
int sed_write_shadow_mbr(struct sed_device *dev, const struct sed_key *key,
354354
const uint8_t *from, uint32_t size, uint32_t offset);
355355

356+
357+
/**
358+
*
359+
*/
360+
int sed_issue_blocksid_cmd(struct sed_device *dev, bool hw_reset);
361+
356362
/**
357363
*
358364
*/

src/lib/nvme_access.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ static int send_recv_nvme_pt_ioctl(int fd, int send, uint8_t proto_id,
4444
return status;
4545
}
4646

47-
static int opal_send(int fd, uint16_t com_id, uint8_t *buf, int buf_len)
47+
int opal_send(int fd, uint8_t proto_id, uint16_t com_id, uint8_t *buf, int buf_len)
4848
{
4949
int ret;
5050

51-
ret = send_recv_nvme_pt_ioctl(fd, SEND, TCG_SECP_01, com_id, buf,
51+
ret = send_recv_nvme_pt_ioctl(fd, SEND, proto_id, com_id, buf,
5252
buf_len);
5353

5454
return ret;
@@ -89,7 +89,7 @@ int opal_send_recv(int fd, uint16_t com_id, uint8_t *req_buf,
8989
{
9090
int ret;
9191

92-
ret = opal_send(fd, com_id, req_buf, req_buf_len);
92+
ret = opal_send(fd, TCG_SECP_01, com_id, req_buf, req_buf_len);
9393
if (ret)
9494
return ret;
9595

src/lib/nvme_access.h

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
int opal_send_recv(int fd, uint16_t com_id, uint8_t *req_buf,
1313
int req_buf_len, uint8_t *resp_buf, int resp_buf_len);
1414

15+
int opal_send(int fd, uint8_t proto_id, uint16_t com_id, uint8_t *buf, int buf_len);
1516
int opal_recv(int fd, uint16_t com_id, uint8_t *buf, int buf_len);
1617

1718
#endif /* _NVME_ACCESS_H_ */

src/lib/nvme_pt_ioctl.c

+25
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444

4545
#define MIN_IO_BUFFER_LEN 2048
4646

47+
#define OPAL_BLOCKSID_COMID 5
48+
#define BLOCKSID_PAYLOAD_SZ 512
49+
4750
/* #define TPer property name strings here */
4851
#define MCPS "MaxComPacketSize"
4952

@@ -2558,3 +2561,25 @@ int opal_write_shadow_mbr_pt(struct sed_device *dev, const struct sed_key *key,
25582561
return ret;
25592562
}
25602563

2564+
int opal_block_sid_pt(struct sed_device *dev, bool hw_reset)
2565+
{
2566+
struct opal_device *device = dev->priv;
2567+
int ret;
2568+
2569+
/* Send Block SID authentication command, no
2570+
* IF_RECV response is expected. Set Hardware
2571+
* Reset in LSB of the first byte in BlockSID
2572+
* payload based on Clear Event flag user
2573+
* supplied through hwreset argument */
2574+
2575+
*(device->req_buf) = hw_reset ? 1 : 0;
2576+
2577+
ret = opal_send(dev->fd, TCG_SECP_02, OPAL_BLOCKSID_COMID,
2578+
device->req_buf, BLOCKSID_PAYLOAD_SZ);
2579+
if (ret) {
2580+
SEDCLI_DEBUG_MSG("Error in NVMe passthrough ops\n");
2581+
}
2582+
2583+
return ret;
2584+
}
2585+

src/lib/nvme_pt_ioctl.h

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
enum {
7676
TCG_SECP_00 = 0,
7777
TCG_SECP_01,
78+
TCG_SECP_02,
7879
};
7980

8081
enum opaluid {
@@ -477,6 +478,8 @@ int opal_ds_add_anybody_get(struct sed_device *dev, const struct sed_key *key);
477478
int opal_list_lr_pt(struct sed_device *dev, const struct sed_key *key,
478479
struct sed_opal_lockingranges *lrs);
479480

481+
int opal_block_sid_pt(struct sed_device *dev, bool hw_reset);
482+
480483
void opal_deinit_pt(struct sed_device *dev);
481484

482485
#endif /* _NVME_PT_IOCTL_H */

src/lib/sed.c

+12
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ typedef int (*ds_read)(struct sed_device *, enum SED_AUTHORITY, const struct sed
4747
typedef int (*ds_write)(struct sed_device *, enum SED_AUTHORITY, const struct sed_key *, const uint8_t *, uint32_t, uint32_t);
4848
typedef int (*list_lr)(struct sed_device *, const struct sed_key *,
4949
struct sed_opal_lockingranges *);
50+
typedef int (*blocksid)(struct sed_device *, bool);
5051
typedef void (*deinit)(struct sed_device *);
5152

5253
struct opal_interface {
@@ -71,6 +72,7 @@ struct opal_interface {
7172
ds_read ds_read_fn;
7273
ds_write ds_write_fn;
7374
list_lr list_lr_fn;
75+
blocksid blocksid_fn;
7476
deinit deinit_fn;
7577
};
7678

@@ -97,6 +99,7 @@ static struct opal_interface opal_if = {
9799
.ds_read_fn = NULL,
98100
.ds_write_fn = NULL,
99101
.list_lr_fn = NULL,
102+
.blocksid_fn = NULL,
100103
.deinit_fn = sedopal_deinit
101104
};
102105
#endif
@@ -123,6 +126,7 @@ static struct opal_interface nvmept_if = {
123126
.ds_read_fn = opal_ds_read,
124127
.ds_write_fn = opal_ds_write,
125128
.list_lr_fn = opal_list_lr_pt,
129+
.blocksid_fn = opal_block_sid_pt,
126130
.deinit_fn = opal_deinit_pt
127131
};
128132

@@ -369,6 +373,14 @@ int sed_list_lr(struct sed_device *dev, const struct sed_key *key,
369373
return curr_if->list_lr_fn(dev, key, lrs);
370374
}
371375

376+
int sed_issue_blocksid_cmd(struct sed_device *dev, bool hw_reset)
377+
{
378+
if (curr_if->blocksid_fn == NULL)
379+
return -EOPNOTSUPP;
380+
381+
return curr_if->blocksid_fn(dev, hw_reset);
382+
}
383+
372384
const char *sed_error_text(int sed_status)
373385
{
374386
if ((sed_status > SED_AUTHORITY_LOCKED_OUT && sed_status != SED_FAIL) || sed_status < 0) {

src/sedcli_main.c

+57
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ static int setup_global_range_handle_opts(char *opt, char **arg);
3939
static int setpw_handle_opts(char *opt, char **arg);
4040
static int mbr_control_handle_opts(char *opt, char **arg);
4141
static int write_mbr_handle_opts(char *opt, char **arg);
42+
static int blocksid_handle_opts(char *opt, char **arg);
4243

4344
static int handle_sed_discv(void);
4445
static int handle_ownership(void);
@@ -51,6 +52,7 @@ static int handle_setup_global_range(void);
5152
static int handle_setpw(void);
5253
static int handle_mbr_control(void);
5354
static int handle_write_mbr(void);
55+
static int handle_blocksid(void);
5456

5557
static cli_option sed_discv_opts[] = {
5658
{'d', "device", "Device node e.g. /dev/nvme0n1", 1, "DEVICE", CLI_OPTION_REQUIRED},
@@ -105,6 +107,12 @@ static cli_option write_mbr_opts[] = {
105107
{0}
106108
};
107109

110+
static cli_option blocksid_opts[] = {
111+
{'d', "device", "Device node e.g. /dev/nvme0n1", 1, "DEVICE", CLI_OPTION_REQUIRED},
112+
{'r', "hwreset", "Clear events by setting Hardware Reset flag. Allowed values: 1/0", 1, "FMT", CLI_OPTION_REQUIRED},
113+
{0}
114+
};
115+
108116
static cli_command sedcli_commands[] = {
109117
{
110118
.name = "discovery",
@@ -206,6 +214,17 @@ static cli_command sedcli_commands[] = {
206214
.flags = 0,
207215
.help = NULL
208216
},
217+
{
218+
.name = "block_sid",
219+
.short_name = 'B',
220+
.desc = "Issue BlockSID authentication command",
221+
.long_desc = "Issue BlockSID authentication command",
222+
.options = blocksid_opts,
223+
.command_handle_opts = blocksid_handle_opts,
224+
.handle = handle_blocksid,
225+
.flags = 0,
226+
.help = NULL
227+
},
209228
{
210229
.name = "version",
211230
.short_name = 'V',
@@ -257,6 +276,7 @@ struct sedcli_options {
257276
int enable;
258277
int done;
259278
int offset;
279+
bool hardware_reset;
260280
int non_destructive;
261281
};
262282

@@ -422,6 +442,24 @@ int write_mbr_handle_opts(char *opt, char **arg)
422442
return 0;
423443
}
424444

445+
int blocksid_handle_opts(char *opt, char **arg)
446+
{
447+
/* No reset BlockSID upon power events */
448+
int hwreset_flag = 0;
449+
450+
if (!strcmp(opt, "device")) {
451+
strncpy(opts->dev_path, arg[0], PATH_MAX - 1);
452+
} else if (!strcmp(opt, "hwreset") && strlen(arg[0]) == 1) {
453+
if ((arg[0][0] != '0') && (arg[0][0] != '1')) {
454+
return -EINVAL;
455+
}
456+
hwreset_flag = atoi(arg[0]);
457+
opts->hardware_reset = (hwreset_flag == 1) ? true : false;
458+
}
459+
460+
return 0;
461+
}
462+
425463
static void print_sed_status(int status)
426464
{
427465
const char *sed_status = NULL;
@@ -1095,6 +1133,25 @@ static int handle_write_mbr(void)
10951133
return ret;
10961134
}
10971135

1136+
static int handle_blocksid(void)
1137+
{
1138+
struct sed_device *dev = NULL;
1139+
int ret = sed_init(&dev, opts->dev_path);
1140+
1141+
if (ret) {
1142+
sedcli_printf(LOG_ERR, "Error in initializing the dev: %s\n",
1143+
opts->dev_path);
1144+
return ret;
1145+
}
1146+
1147+
ret = sed_issue_blocksid_cmd(dev, opts->hardware_reset);
1148+
1149+
print_sed_status(ret);
1150+
sed_deinit(dev);
1151+
1152+
return ret;
1153+
}
1154+
10981155
static int handle_version(void)
10991156
{
11001157
sedcli_printf(LOG_INFO, "sedcli %s\n", SEDCLI_VERSION);

0 commit comments

Comments
 (0)