Opal: add take ownership cmd options
Also make some modification for invoking process in nvme_manage tool. Change-Id: Ib54db43d7336d3e839e7d9317c292b9a57b38f80 Signed-off-by: Chunyang Hui <chunyang.hui@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/445059 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
1dd07870e3
commit
7250ec64db
@ -100,7 +100,8 @@ is specified, use that specified nbd device. If it's not specified, pick availab
|
||||
### Opal
|
||||
|
||||
Add Opal scan support for NVMe to check whether it supports SED Opal and dump
|
||||
device info. nvme_manage tool can be used to invoke this.
|
||||
device info. Add Opal take ownership command support. nvme_manage tool can be used to invoke this.
|
||||
This module should be considered experimental pending additional features and tests.
|
||||
|
||||
### iSCSI target
|
||||
|
||||
|
@ -142,7 +142,7 @@ static void usage(void)
|
||||
printf("\t[5: detach namespace from controller]\n");
|
||||
printf("\t[6: format namespace or controller]\n");
|
||||
printf("\t[7: firmware update]\n");
|
||||
printf("\t[8: opal scan]\n");
|
||||
printf("\t[8: opal]\n");
|
||||
printf("\t[9: quit]\n");
|
||||
}
|
||||
|
||||
@ -853,7 +853,8 @@ update_firmware_image(void)
|
||||
spdk_dma_free(fw_image);
|
||||
}
|
||||
|
||||
static void spdk_dump_opal_info(struct spdk_opal_info *opal)
|
||||
static void
|
||||
opal_dump_info(struct spdk_opal_info *opal)
|
||||
{
|
||||
if (!opal->opal_ssc_dev) {
|
||||
SPDK_ERRLOG("This device is not Opal enabled. Not Supported!\n");
|
||||
@ -929,21 +930,29 @@ static void spdk_dump_opal_info(struct spdk_opal_info *opal)
|
||||
}
|
||||
|
||||
static void
|
||||
test_opal(void)
|
||||
opal_usage(void)
|
||||
{
|
||||
struct dev *iter;
|
||||
printf("Opal General Usage:\n");
|
||||
printf("\n");
|
||||
printf("\t[1: scan device]\n");
|
||||
printf("\t[2: take ownership]\n");
|
||||
printf("\t[0: quit]\n");
|
||||
}
|
||||
|
||||
foreach_dev(iter) {
|
||||
static void
|
||||
opal_scan(struct dev *iter)
|
||||
{
|
||||
if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
|
||||
iter->opal_dev = spdk_opal_init_dev(iter->ctrlr);
|
||||
if (iter->opal_dev == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spdk_opal_supported(iter->opal_dev)) {
|
||||
printf("\n\nOpal Supported:\n");
|
||||
display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC);
|
||||
spdk_opal_scan(iter->opal_dev);
|
||||
spdk_dump_opal_info(spdk_opal_get_info(iter->opal_dev));
|
||||
opal_dump_info(spdk_opal_get_info(iter->opal_dev));
|
||||
}
|
||||
spdk_opal_close(iter->opal_dev);
|
||||
} else {
|
||||
@ -952,6 +961,87 @@ test_opal(void)
|
||||
printf("%04x:%02x:%02x.%02x: Opal Not Supported\n\n\n",
|
||||
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
opal_take_ownership(struct dev *iter)
|
||||
{
|
||||
char new_passwd[MAX_PASSWORD_SIZE];
|
||||
char *passwd_p;
|
||||
int ret;
|
||||
int ch;
|
||||
|
||||
if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
|
||||
iter->opal_dev = spdk_opal_init_dev(iter->ctrlr);
|
||||
if (iter->opal_dev == NULL) {
|
||||
return;
|
||||
}
|
||||
if (spdk_opal_supported(iter->opal_dev)) {
|
||||
memset(new_passwd, 0, sizeof(new_passwd));
|
||||
printf("Please input the new password for ownership:\n");
|
||||
while ((ch = getchar()) != '\n' && ch != EOF);
|
||||
passwd_p = get_line(new_passwd, MAX_PASSWORD_SIZE, stdin);
|
||||
if (passwd_p) {
|
||||
ret = spdk_opal_cmd(iter->opal_dev, OPAL_CMD_TAKE_OWNERSHIP, passwd_p);
|
||||
if (ret) {
|
||||
printf("Take ownership failure: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
printf("...\n...\nTake Ownership Success\n");
|
||||
} else {
|
||||
printf("Input password invalid. Take ownership failure\n");
|
||||
}
|
||||
}
|
||||
spdk_opal_close(iter->opal_dev);
|
||||
} else {
|
||||
printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n",
|
||||
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
|
||||
printf("%04x:%02x:%02x.%02x: Opal Not Supported\n\n\n",
|
||||
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_opal(void)
|
||||
{
|
||||
int exit_flag = false;
|
||||
struct dev *ctrlr;
|
||||
|
||||
ctrlr = get_controller();
|
||||
if (ctrlr == NULL) {
|
||||
printf("Invalid controller PCI Address.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
opal_usage();
|
||||
while (!exit_flag) {
|
||||
int cmd;
|
||||
if (!scanf("%d", &cmd)) {
|
||||
printf("Invalid Command: command must be number 0-2\n");
|
||||
while (getchar() != '\n');
|
||||
opal_usage();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
exit_flag = true;
|
||||
continue;
|
||||
case 1:
|
||||
opal_scan(ctrlr);
|
||||
break;
|
||||
case 2:
|
||||
opal_take_ownership(ctrlr);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Invalid option\n");
|
||||
}
|
||||
|
||||
while (getchar() != '\n');
|
||||
printf("press Enter to display Opal cmd menu ...\n");
|
||||
while (getchar() != '\n');
|
||||
opal_usage();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@
|
||||
|
||||
#define SPDK_OPAL_NOT_SUPPORTED 0xFF
|
||||
|
||||
#define MAX_PASSWORD_SIZE 32 /* in byte */
|
||||
|
||||
/*
|
||||
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||
* 5.1.5 Method Status Codes
|
||||
@ -84,6 +86,7 @@ enum spdk_opal_cmd {
|
||||
OPAL_CMD_ERASE_LOCKING_RANGE,
|
||||
OPAL_CMD_SECURE_ERASE_LOCKING_RANGE,
|
||||
OPAL_CMD_INITIAL_SETUP,
|
||||
OPAL_CMD_SCAN,
|
||||
};
|
||||
|
||||
struct spdk_opal_info {
|
||||
@ -136,10 +139,12 @@ struct spdk_opal_dev;
|
||||
|
||||
struct spdk_opal_dev *spdk_opal_init_dev(void *dev_handler);
|
||||
|
||||
void spdk_opal_scan(struct spdk_opal_dev *dev);
|
||||
int spdk_opal_scan(struct spdk_opal_dev *dev);
|
||||
void spdk_opal_close(struct spdk_opal_dev *dev);
|
||||
struct spdk_opal_info *spdk_opal_get_info(struct spdk_opal_dev *dev);
|
||||
|
||||
bool spdk_opal_supported(struct spdk_opal_dev *dev);
|
||||
|
||||
int spdk_opal_cmd(struct spdk_opal_dev *dev, unsigned int cmd, void *arg);
|
||||
|
||||
#endif
|
||||
|
@ -129,6 +129,97 @@ opal_add_token_u8(int *err, struct spdk_opal_dev *dev, uint8_t token)
|
||||
dev->cmd[dev->cmd_pos++] = token;
|
||||
}
|
||||
|
||||
static void
|
||||
opal_add_short_atom_header(struct spdk_opal_dev *dev, bool bytestring,
|
||||
bool has_sign, size_t len)
|
||||
{
|
||||
uint8_t atom;
|
||||
int err = 0;
|
||||
|
||||
atom = SPDK_SHORT_ATOM_ID;
|
||||
atom |= bytestring ? SPDK_SHORT_ATOM_BYTESTRING_FLAG : 0;
|
||||
atom |= has_sign ? SPDK_SHORT_ATOM_SIGN_FLAG : 0;
|
||||
atom |= len & SPDK_SHORT_ATOM_LEN_MASK;
|
||||
|
||||
opal_add_token_u8(&err, dev, atom);
|
||||
}
|
||||
|
||||
static void
|
||||
opal_add_medium_atom_header(struct spdk_opal_dev *dev, bool bytestring,
|
||||
bool has_sign, size_t len)
|
||||
{
|
||||
uint8_t header;
|
||||
|
||||
header = SPDK_MEDIUM_ATOM_ID;
|
||||
header |= bytestring ? SPDK_MEDIUM_ATOM_BYTESTRING_FLAG : 0;
|
||||
header |= has_sign ? SPDK_MEDIUM_ATOM_SIGN_FLAG : 0;
|
||||
header |= (len >> 8) & SPDK_MEDIUM_ATOM_LEN_MASK;
|
||||
dev->cmd[dev->cmd_pos++] = header;
|
||||
dev->cmd[dev->cmd_pos++] = len;
|
||||
}
|
||||
|
||||
static void
|
||||
opal_add_token_bytestring(int *err, struct spdk_opal_dev *dev,
|
||||
const uint8_t *bytestring, size_t len)
|
||||
{
|
||||
size_t header_len = 1;
|
||||
bool is_short_atom = true;
|
||||
|
||||
if (*err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len & ~SPDK_SHORT_ATOM_LEN_MASK) {
|
||||
header_len = 2;
|
||||
is_short_atom = false;
|
||||
}
|
||||
|
||||
if (len >= IO_BUFFER_LENGTH - dev->cmd_pos - header_len) {
|
||||
SPDK_ERRLOG("Error adding bytestring: end of buffer.\n");
|
||||
*err = -ERANGE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_short_atom) {
|
||||
opal_add_short_atom_header(dev, true, false, len);
|
||||
} else {
|
||||
opal_add_medium_atom_header(dev, true, false, len);
|
||||
}
|
||||
|
||||
memcpy(&dev->cmd[dev->cmd_pos], bytestring, len);
|
||||
dev->cmd_pos += len;
|
||||
}
|
||||
|
||||
static void
|
||||
opal_add_token_u64(int *err, struct spdk_opal_dev *dev, uint64_t number)
|
||||
{
|
||||
int startat = 0;
|
||||
|
||||
/* add header first */
|
||||
if (number <= SPDK_TINY_ATOM_DATA_MASK) {
|
||||
dev->cmd[dev->cmd_pos++] = (uint8_t) number & SPDK_TINY_ATOM_DATA_MASK;
|
||||
} else {
|
||||
if (number < 0x100) {
|
||||
dev->cmd[dev->cmd_pos++] = 0x81; /* short atom, 1 byte length */
|
||||
startat = 0;
|
||||
} else if (number < 0x10000) {
|
||||
dev->cmd[dev->cmd_pos++] = 0x82; /* short atom, 2 byte length */
|
||||
startat = 1;
|
||||
} else if (number < 0x100000000) {
|
||||
dev->cmd[dev->cmd_pos++] = 0x84; /* short atom, 4 byte length */
|
||||
startat = 3;
|
||||
} else {
|
||||
dev->cmd[dev->cmd_pos++] = 0x88; /* short atom, 8 byte length */
|
||||
startat = 7;
|
||||
}
|
||||
|
||||
/* add number value */
|
||||
for (int i = startat; i > -1; i--) {
|
||||
dev->cmd[dev->cmd_pos++] = (uint8_t)((number >> (i * 8)) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eod)
|
||||
{
|
||||
@ -367,7 +458,6 @@ opal_response_token_matches(const struct spdk_opal_resp_token *token,
|
||||
if (!token ||
|
||||
token->type != OPAL_DTA_TOKENID_TOKEN ||
|
||||
token->pos[0] != match) {
|
||||
SPDK_ERRLOG("Token not matching\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -417,6 +507,31 @@ opal_response_get_u64(const struct spdk_opal_resp_parsed *resp, int index)
|
||||
return resp->resp_tokens[index].stored.unsigned_num;
|
||||
}
|
||||
|
||||
static size_t
|
||||
opal_response_get_string(const struct spdk_opal_resp_parsed *resp, int n,
|
||||
const char **store)
|
||||
{
|
||||
*store = NULL;
|
||||
if (!resp) {
|
||||
SPDK_ERRLOG("Response is NULL\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (n > resp->num) {
|
||||
SPDK_ERRLOG("Response has %d tokens. Can't access %d\n",
|
||||
resp->num, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (resp->resp_tokens[n].type != OPAL_DTA_TOKENID_BYTESTRING) {
|
||||
SPDK_ERRLOG("Token is not a byte string!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*store = resp->resp_tokens[n].pos + 1;
|
||||
return resp->resp_tokens[n].len - 1;
|
||||
}
|
||||
|
||||
static int
|
||||
opal_response_status(const struct spdk_opal_resp_parsed *resp)
|
||||
{
|
||||
@ -789,10 +904,276 @@ opal_check_support(struct spdk_opal_dev *dev)
|
||||
void
|
||||
spdk_opal_close(struct spdk_opal_dev *dev)
|
||||
{
|
||||
pthread_mutex_destroy(&dev->mutex_lock);
|
||||
free(dev->opal_info);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_start_session_cb(struct spdk_opal_dev *dev)
|
||||
{
|
||||
uint32_t hsn, tsn;
|
||||
int error = 0;
|
||||
|
||||
error = opal_parse_and_check_status(dev);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
hsn = opal_response_get_u64(&dev->parsed_resp, 4);
|
||||
tsn = opal_response_get_u64(&dev->parsed_resp, 5);
|
||||
|
||||
if (hsn == 0 && tsn == 0) {
|
||||
SPDK_ERRLOG("Couldn't authenticate session\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
dev->hsn = hsn;
|
||||
dev->tsn = tsn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
opal_start_generic_session(struct spdk_opal_dev *dev,
|
||||
enum opal_uid_enum auth,
|
||||
enum opal_uid_enum sp_type,
|
||||
const char *key,
|
||||
uint8_t key_len)
|
||||
{
|
||||
uint32_t hsn;
|
||||
int err = 0;
|
||||
|
||||
if (key == NULL && auth != UID_ANYBODY) {
|
||||
return OPAL_INVAL_PARAM;
|
||||
}
|
||||
|
||||
opal_clear_cmd(dev);
|
||||
|
||||
opal_set_comid(dev, dev->comid);
|
||||
hsn = GENERIC_HOST_SESSION_NUM;
|
||||
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
|
||||
opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_SMUID],
|
||||
OPAL_UID_LENGTH);
|
||||
opal_add_token_bytestring(&err, dev, spdk_opal_method[STARTSESSION_METHOD],
|
||||
OPAL_UID_LENGTH);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
|
||||
opal_add_token_u64(&err, dev, hsn);
|
||||
opal_add_token_bytestring(&err, dev, spdk_opal_uid[sp_type], OPAL_UID_LENGTH);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_TRUE); /* Write */
|
||||
|
||||
switch (auth) {
|
||||
case UID_ANYBODY:
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||
break;
|
||||
case UID_ADMIN1:
|
||||
case UID_SID:
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
|
||||
opal_add_token_u8(&err, dev, 0); /* HostChallenge */
|
||||
opal_add_token_bytestring(&err, dev, key, key_len);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
|
||||
opal_add_token_u8(&err, dev, 3); /* HostSignAuth */
|
||||
opal_add_token_bytestring(&err, dev, spdk_opal_uid[auth],
|
||||
OPAL_UID_LENGTH);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||
break;
|
||||
default:
|
||||
SPDK_ERRLOG("Cannot start Admin SP session with auth %d\n", auth);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
SPDK_ERRLOG("Error building start adminsp session command.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return opal_finalize_and_send(dev, 1, opal_start_session_cb);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
opal_start_anybody_adminsp_session(struct spdk_opal_dev *dev, void *data)
|
||||
{
|
||||
return opal_start_generic_session(dev, UID_ANYBODY,
|
||||
UID_ADMINSP, NULL, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_get_msid_cpin_pin_cb(struct spdk_opal_dev *dev)
|
||||
{
|
||||
const char *msid_pin;
|
||||
size_t strlen;
|
||||
int error = 0;
|
||||
|
||||
error = opal_parse_and_check_status(dev);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
strlen = opal_response_get_string(&dev->parsed_resp, 4, &msid_pin);
|
||||
if (!msid_pin) {
|
||||
SPDK_ERRLOG("Couldn't extract PIN from response\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->prev_d_len = strlen;
|
||||
dev->prev_data = calloc(1, strlen);
|
||||
if (!dev->prev_data) {
|
||||
SPDK_ERRLOG("memory allocation error\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(dev->prev_data, msid_pin, strlen);
|
||||
|
||||
SPDK_DEBUGLOG(SPDK_LOG_OPAL, "MSID = %p\n", dev->prev_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
opal_get_msid_cpin_pin(struct spdk_opal_dev *dev, void *data)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
opal_clear_cmd(dev);
|
||||
opal_set_comid(dev, dev->comid);
|
||||
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
|
||||
opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_C_PIN_MSID],
|
||||
OPAL_UID_LENGTH);
|
||||
opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
|
||||
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
|
||||
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTCOLUMN);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_PIN);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
|
||||
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDCOLUMN);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_PIN);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
|
||||
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||
|
||||
if (err) {
|
||||
SPDK_ERRLOG("Error building Get MSID CPIN PIN command.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return opal_finalize_and_send(dev, 1, opal_get_msid_cpin_pin_cb);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_start_adminsp_session(struct spdk_opal_dev *dev, void *data)
|
||||
{
|
||||
int ret;
|
||||
uint8_t *key = dev->prev_data;
|
||||
|
||||
if (!key) {
|
||||
const struct spdk_opal_key *okey = data;
|
||||
if (okey == NULL) {
|
||||
SPDK_ERRLOG("No key found for auth session\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = opal_start_generic_session(dev, UID_SID,
|
||||
UID_ADMINSP,
|
||||
okey->key,
|
||||
okey->key_len);
|
||||
} else {
|
||||
ret = opal_start_generic_session(dev, UID_SID,
|
||||
UID_ADMINSP,
|
||||
key, dev->prev_d_len);
|
||||
free(key);
|
||||
dev->prev_data = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
opal_generic_pw_cmd(uint8_t *key, size_t key_len, uint8_t *cpin_uid,
|
||||
struct spdk_opal_dev *dev)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
opal_clear_cmd(dev);
|
||||
opal_set_comid(dev, dev->comid);
|
||||
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
|
||||
opal_add_token_bytestring(&err, dev, cpin_uid, OPAL_UID_LENGTH);
|
||||
opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD],
|
||||
OPAL_UID_LENGTH);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_VALUES);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_PIN);
|
||||
opal_add_token_bytestring(&err, dev, key, key_len);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
|
||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data)
|
||||
{
|
||||
uint8_t cpin_uid[OPAL_UID_LENGTH];
|
||||
const char *new_passwd = data;
|
||||
struct spdk_opal_key *opal_key;
|
||||
|
||||
opal_key = calloc(1, sizeof(struct spdk_opal_key));
|
||||
if (!opal_key) {
|
||||
SPDK_ERRLOG("Memory allocation failed for spdk_opal_key\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
opal_key->key_len = strlen(new_passwd);
|
||||
memcpy(opal_key->key, new_passwd, opal_key->key_len);
|
||||
dev->dev_key = opal_key;
|
||||
|
||||
memcpy(cpin_uid, spdk_opal_uid[UID_C_PIN_SID], OPAL_UID_LENGTH);
|
||||
|
||||
if (opal_generic_pw_cmd(opal_key->key, opal_key->key_len, cpin_uid, dev)) {
|
||||
SPDK_ERRLOG("Error building Set SID cpin\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status);
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_opal_take_ownership(struct spdk_opal_dev *dev, char *new_passwd)
|
||||
{
|
||||
const struct spdk_opal_step owner_steps[] = {
|
||||
{ opal_discovery0, },
|
||||
{ opal_start_anybody_adminsp_session, },
|
||||
{ opal_get_msid_cpin_pin, },
|
||||
{ opal_end_session, },
|
||||
{ opal_start_adminsp_session, },
|
||||
{ opal_set_sid_cpin_pin, new_passwd },
|
||||
{ opal_end_session, },
|
||||
{ NULL, }
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!dev) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&dev->mutex_lock);
|
||||
opal_setup_dev(dev, owner_steps);
|
||||
ret = opal_next(dev);
|
||||
pthread_mutex_unlock(&dev->mutex_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct spdk_opal_dev *
|
||||
spdk_opal_init_dev(void *dev_handler)
|
||||
{
|
||||
@ -819,10 +1200,18 @@ spdk_opal_init_dev(void *dev_handler)
|
||||
SPDK_INFOLOG(SPDK_LOG_OPAL, "Opal is not supported on this device\n");
|
||||
dev->supported = false;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&dev->mutex_lock, NULL)) {
|
||||
SPDK_ERRLOG("Mutex init failed\n");
|
||||
free(dev->opal_info);
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
spdk_opal_scan(struct spdk_opal_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
@ -831,8 +1220,8 @@ spdk_opal_scan(struct spdk_opal_dev *dev)
|
||||
if (ret) {
|
||||
SPDK_ERRLOG("check opal support failed: %d\n", ret);
|
||||
spdk_opal_close(dev);
|
||||
return;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct spdk_opal_info *
|
||||
@ -847,5 +1236,33 @@ spdk_opal_supported(struct spdk_opal_dev *dev)
|
||||
return dev->supported;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_opal_cmd(struct spdk_opal_dev *dev, unsigned int cmd, void *arg)
|
||||
{
|
||||
if (!dev) {
|
||||
SPDK_ERRLOG("Device null\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!dev->supported) {
|
||||
SPDK_ERRLOG("Device not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case OPAL_CMD_SCAN:
|
||||
return spdk_opal_scan(dev);
|
||||
case OPAL_CMD_TAKE_OWNERSHIP:
|
||||
return spdk_opal_take_ownership(dev, arg);
|
||||
case OPAL_CMD_LOCK_UNLOCK:
|
||||
case OPAL_CMD_ACTIVATE_LSP:
|
||||
case OPAL_CMD_REVERT_TPER:
|
||||
case OPAL_CMD_SETUP_LOCKING_RANGE:
|
||||
|
||||
default:
|
||||
SPDK_ERRLOG("NOT SUPPORTED\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Log component for opal submodule */
|
||||
SPDK_LOG_REGISTER_COMPONENT("opal", SPDK_LOG_OPAL)
|
||||
|
@ -325,6 +325,8 @@ struct spdk_opal_dev {
|
||||
struct spdk_opal_info *opal_info;
|
||||
|
||||
uint64_t timeout; /* seconds */
|
||||
|
||||
pthread_mutex_t mutex_lock; /* some structs are accessed by current thread only */
|
||||
};
|
||||
|
||||
enum opal_lock_state {
|
||||
|
Loading…
Reference in New Issue
Block a user