From 6b48e743a3563b46f054a6b4a7b7bee4d793bd9e Mon Sep 17 00:00:00 2001 From: Chunyang Hui Date: Tue, 19 Feb 2019 23:22:56 +0800 Subject: [PATCH] Opal: Add revert tper cmd option Reset the device to its factory defaults. Change-Id: I43f7dc8fb7bd5226283a4762beac0e2cf016f698 Signed-off-by: Chunyang Hui Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/445253 Tested-by: SPDK CI Jenkins Reviewed-by: Changpeng Liu Reviewed-by: Jim Harris --- CHANGELOG.md | 3 +- examples/nvme/nvme_manage/nvme_manage.c | 45 +++++++++++++-- lib/nvme/nvme_opal.c | 73 ++++++++++++++++++++++++- 3 files changed, 115 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f8563547..dc8621721 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. Add Opal take ownership command support. nvme_manage tool can be used to invoke this. +device info. Add Opal take ownership command support, revert TPer command support. +nvme_manage tool can be used to invoke this. This module should be considered experimental pending additional features and tests. ### iSCSI target diff --git a/examples/nvme/nvme_manage/nvme_manage.c b/examples/nvme/nvme_manage/nvme_manage.c index 4e2c991ae..a7dd7c99b 100644 --- a/examples/nvme/nvme_manage/nvme_manage.c +++ b/examples/nvme/nvme_manage/nvme_manage.c @@ -939,6 +939,7 @@ opal_usage(void) printf("\n"); printf("\t[1: scan device]\n"); printf("\t[2: take ownership]\n"); + printf("\t[3: revert tper]\n"); printf("\t[0: quit]\n"); } @@ -969,7 +970,7 @@ opal_scan(struct dev *iter) static void opal_take_ownership(struct dev *iter) { - char new_passwd[MAX_PASSWORD_SIZE]; + char new_passwd[MAX_PASSWORD_SIZE] = {0}; char *passwd_p; int ret; int ch; @@ -980,7 +981,6 @@ opal_take_ownership(struct dev *iter) 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); @@ -997,9 +997,43 @@ opal_take_ownership(struct dev *iter) } spdk_opal_close(iter->opal_dev); } else { - printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n", + printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\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", + } +} + +static void +opal_revert_tper(struct dev *iter) +{ + char passwd[MAX_PASSWORD_SIZE] = {0}; + 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)) { + printf("Please be noted this operation will erase ALL DATA on this drive\n"); + printf("Please input password for revert TPer:\n"); + while ((ch = getchar()) != '\n' && ch != EOF); + passwd_p = get_line(passwd, MAX_PASSWORD_SIZE, stdin); + if (passwd_p) { + ret = spdk_opal_cmd(iter->opal_dev, OPAL_CMD_REVERT_TPER, passwd_p); + if (ret) { + printf("Revert TPer failure: %d\n", ret); + return; + } + printf("...\n...\nRevert TPer Success\n"); + } else { + printf("Input password invalid. Revert TPer failure\n"); + } + } + spdk_opal_close(iter->opal_dev); + } else { + printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); } } @@ -1036,6 +1070,9 @@ test_opal(void) case 2: opal_take_ownership(ctrlr); break; + case 3: + opal_revert_tper(ctrlr); + break; default: printf("Invalid option\n"); diff --git a/lib/nvme/nvme_opal.c b/lib/nvme/nvme_opal.c index f55aa8ccb..38cfe8fdc 100644 --- a/lib/nvme/nvme_opal.c +++ b/lib/nvme/nvme_opal.c @@ -1224,6 +1224,76 @@ spdk_opal_scan(struct spdk_opal_dev *dev) return ret; } +static int +opal_revert_tper(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_ADMINSP], + OPAL_UID_LENGTH); + opal_add_token_bytestring(&err, dev, spdk_opal_method[REVERT_METHOD], + OPAL_UID_LENGTH); + opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST); + opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST); + if (err) { + SPDK_ERRLOG("Error building REVERT TPER command.\n"); + return err; + } + + return opal_finalize_and_send(dev, 1, opal_parse_and_check_status); +} + +static int +spdk_opal_revert_tper(struct spdk_opal_dev *dev, const char *passwd) +{ + int ret; + 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(passwd); + memcpy(opal_key->key, passwd, opal_key->key_len); + dev->dev_key = opal_key; + + pthread_mutex_lock(&dev->mutex_lock); + opal_setup_dev(dev, NULL); + ret = opal_discovery0(dev, NULL); + if (ret) { + SPDK_ERRLOG("Error on discovery 0 with error %d: %s\n", ret, + opal_error_to_human(ret)); + goto end; + } + + ret = opal_start_adminsp_session(dev, opal_key); + if (ret) { + opal_end_session_error(dev); + SPDK_ERRLOG("Error on starting admin SP session with error %d: %s\n", ret, + opal_error_to_human(ret)); + goto end; + } + + ret = opal_revert_tper(dev, NULL); + if (ret) { + opal_end_session_error(dev); + SPDK_ERRLOG("Error on reverting TPer with error %d: %s\n", ret, + opal_error_to_human(ret)); + goto end; + } + +end: + pthread_mutex_unlock(&dev->mutex_lock); + free(opal_key); + dev->dev_key = NULL; + return ret; +} + struct spdk_opal_info * spdk_opal_get_info(struct spdk_opal_dev *dev) { @@ -1253,9 +1323,10 @@ spdk_opal_cmd(struct spdk_opal_dev *dev, unsigned int cmd, void *arg) return spdk_opal_scan(dev); case OPAL_CMD_TAKE_OWNERSHIP: return spdk_opal_take_ownership(dev, arg); + case OPAL_CMD_REVERT_TPER: + return spdk_opal_revert_tper(dev, arg); case OPAL_CMD_LOCK_UNLOCK: case OPAL_CMD_ACTIVATE_LSP: - case OPAL_CMD_REVERT_TPER: case OPAL_CMD_SETUP_LOCKING_RANGE: default: