From 755b4390f90aff121d5855ee2212ab665c051490 Mon Sep 17 00:00:00 2001 From: Chunyang Hui Date: Fri, 10 May 2019 23:24:07 +0800 Subject: [PATCH] Opal: Add activate locking SP method Change-Id: I4189bdefdb5a6651bb73bd32e61c16e899b2ae5a Signed-off-by: Chunyang Hui Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454211 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Changpeng Liu --- CHANGELOG.md | 3 + examples/nvme/nvme_manage/nvme_manage.c | 16 ++- include/spdk/opal.h | 1 + lib/nvme/nvme_opal.c | 125 ++++++++++++++++++++++++ lib/nvme/nvme_opal_internal.h | 7 -- 5 files changed, 140 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 110f8ce9a..c74a084a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,9 @@ Added spdk_nvme_ctrlr_get_transport_id() to get the transport ID from a previously attached controller. Nvme Opal library spdk_opal_cmd deprecated. Adding seperate command APIs. +NVMe Opal library add support for activating locking SP which will make the transaction +from "Manufactured-Inactive" state to "Manufactured" state. Upon successfully invoking +of this method, lock and unlock features will be enabled. Added spdk_nvme_ctrlr_io_cmd_raw_no_payload_build() allowing a caller to pass a completely formed command to an NVMe submission queue (buffer addresses and all). diff --git a/examples/nvme/nvme_manage/nvme_manage.c b/examples/nvme/nvme_manage/nvme_manage.c index 2c1b381f3..846640957 100644 --- a/examples/nvme/nvme_manage/nvme_manage.c +++ b/examples/nvme/nvme_manage/nvme_manage.c @@ -938,7 +938,7 @@ opal_usage(void) printf("Opal General Usage:\n"); printf("\n"); printf("\t[1: scan device]\n"); - printf("\t[2: take ownership]\n"); + printf("\t[2: init - take ownership and activate locking]\n"); printf("\t[3: revert tper]\n"); printf("\t[0: quit]\n"); } @@ -968,7 +968,7 @@ opal_scan(struct dev *iter) } static void -opal_take_ownership(struct dev *iter) +opal_init(struct dev *iter) { char new_passwd[MAX_PASSWORD_SIZE] = {0}; char *passwd_p; @@ -991,9 +991,15 @@ opal_take_ownership(struct dev *iter) spdk_opal_close(iter->opal_dev); return; } - printf("...\n...\nTake Ownership Success\n"); + + ret = spdk_opal_cmd_activate_locking_sp(iter->opal_dev, passwd_p); + if (ret) { + printf("Locking SP activate failure: %d\n", ret); + return; + } + printf("...\n...\nOpal Init Success\n"); } else { - printf("Input password invalid. Take ownership failure\n"); + printf("Input password invalid. Opal Init failure\n"); } } spdk_opal_close(iter->opal_dev); @@ -1070,7 +1076,7 @@ test_opal(void) opal_scan(ctrlr); break; case 2: - opal_take_ownership(ctrlr); + opal_init(ctrlr); /* Take ownership, Activate Locking SP */ break; case 3: opal_revert_tper(ctrlr); diff --git a/include/spdk/opal.h b/include/spdk/opal.h index 9a33eb3e6..a3a344e78 100644 --- a/include/spdk/opal.h +++ b/include/spdk/opal.h @@ -164,5 +164,6 @@ bool spdk_opal_supported(struct spdk_opal_dev *dev); int spdk_opal_cmd_scan(struct spdk_opal_dev *dev); int spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd); int spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd); +int spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd); #endif diff --git a/lib/nvme/nvme_opal.c b/lib/nvme/nvme_opal.c index 1fb8fda38..141c9a7c6 100644 --- a/lib/nvme/nvme_opal.c +++ b/lib/nvme/nvme_opal.c @@ -1113,6 +1113,86 @@ opal_generic_pw_cmd(uint8_t *key, size_t key_len, uint8_t *cpin_uid, return err; } +static int +opal_get_locking_sp_lifecycle_cb(struct spdk_opal_dev *dev) +{ + uint8_t lifecycle; + int error = 0; + + error = opal_parse_and_check_status(dev); + if (error) { + return error; + } + + lifecycle = opal_response_get_u64(&dev->parsed_resp, 4); + if (lifecycle != OPAL_MANUFACTURED_INACTIVE) { /* status before activate */ + SPDK_ERRLOG("Couldn't determine the status of the Lifecycle state\n"); + return -EINVAL; + } + + return 0; +} + +static int +opal_get_locking_sp_lifecycle(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, spdk_opal_uid[UID_LOCKINGSP], + OPAL_UID_LENGTH); + opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH); + + opal_add_tokens(&err, dev, 12, SPDK_OPAL_STARTLIST, + SPDK_OPAL_STARTLIST, + SPDK_OPAL_STARTNAME, + SPDK_OPAL_STARTCOLUMN, + SPDK_OPAL_LIFECYCLE, + SPDK_OPAL_ENDNAME, + SPDK_OPAL_STARTNAME, + SPDK_OPAL_ENDCOLUMN, + SPDK_OPAL_LIFECYCLE, + SPDK_OPAL_ENDNAME, + SPDK_OPAL_ENDLIST, + SPDK_OPAL_ENDLIST); + + if (err) { + SPDK_ERRLOG("Error Building GET Lifecycle Status command\n"); + return err; + } + + return opal_finalize_and_send(dev, 1, opal_get_locking_sp_lifecycle_cb); +} + +static int +opal_activate(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, spdk_opal_uid[UID_LOCKINGSP], + OPAL_UID_LENGTH); + opal_add_token_bytestring(&err, dev, spdk_opal_method[ACTIVATE_METHOD], + OPAL_UID_LENGTH); + + opal_add_tokens(&err, dev, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST); + + if (err) { + SPDK_ERRLOG("Error building Activate LockingSP command.\n"); + return err; + } + + /* TODO: Single User Mode for activatation */ + + return opal_finalize_and_send(dev, 1, opal_parse_and_check_status); +} + static int opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data) { @@ -1311,6 +1391,51 @@ end: return ret; } +int +spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd) +{ + struct spdk_opal_key opal_key; + int ret; + + ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL); + if (ret != 0) { + return ret; + } + + pthread_mutex_lock(&dev->mutex_lock); + ret = opal_start_adminsp_session(dev, &opal_key); + if (ret) { + SPDK_ERRLOG("Error on starting admin SP session with error %d: %s\n", ret, + opal_error_to_human(ret)); + pthread_mutex_unlock(&dev->mutex_lock); + return ret; + } + + ret = opal_get_locking_sp_lifecycle(dev); + if (ret) { + SPDK_ERRLOG("Error on getting SP lifecycle with error %d: %s\n", ret, + opal_error_to_human(ret)); + goto end; + } + + ret = opal_activate(dev); + if (ret) { + SPDK_ERRLOG("Error on activation with error %d: %s\n", ret, + opal_error_to_human(ret)); + goto end; + } + +end: + ret += opal_end_session(dev); + if (ret) { + SPDK_ERRLOG("Error on ending session with error %d: %s\n", ret, + opal_error_to_human(ret)); + } + + pthread_mutex_unlock(&dev->mutex_lock); + return ret; +} + struct spdk_opal_info * spdk_opal_get_info(struct spdk_opal_dev *dev) { diff --git a/lib/nvme/nvme_opal_internal.h b/lib/nvme/nvme_opal_internal.h index bc1527755..59dc92084 100644 --- a/lib/nvme/nvme_opal_internal.h +++ b/lib/nvme/nvme_opal_internal.h @@ -259,13 +259,6 @@ struct spdk_opal_key { uint8_t key[OPAL_KEY_MAX]; }; -struct opal_locking_range_activate_session { - struct spdk_opal_key key; - uint32_t sum; /* single user mode */ - uint8_t lockingrange_num; - uint8_t lockingrange[OPAL_MAX_LRS]; -}; - struct opal_locking_range_setup_session { uint8_t id; uint8_t _padding[7];