1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2016 Intel Corporation. 398416108SCunyin Chang * All rights reserved. 498416108SCunyin Chang */ 598416108SCunyin Chang 6b961d9ccSBen Walker #include "spdk/stdinc.h" 798416108SCunyin Chang 898416108SCunyin Chang #include "spdk/nvme.h" 90dd80395SBen Walker #include "spdk/env.h" 100f9dc2afSShuhei Matsumoto #include "spdk/string.h" 11b58a5d73SDaniel Verkamp #include "spdk/util.h" 1255f5b205SHui, Chunyang #include "spdk/opal.h" 1398416108SCunyin Chang 1498416108SCunyin Chang #define MAX_DEVS 64 1598416108SCunyin Chang 1698416108SCunyin Chang struct dev { 17fcb00f37SDaniel Verkamp struct spdk_pci_addr pci_addr; 1898416108SCunyin Chang struct spdk_nvme_ctrlr *ctrlr; 1998416108SCunyin Chang const struct spdk_nvme_ctrlr_data *cdata; 208f876a61SDaniel Verkamp struct spdk_nvme_ns_data *common_ns_data; 218f876a61SDaniel Verkamp int outstanding_admin_cmds; 2255f5b205SHui, Chunyang struct spdk_opal_dev *opal_dev; 2398416108SCunyin Chang }; 2498416108SCunyin Chang 2598416108SCunyin Chang static struct dev devs[MAX_DEVS]; 2698416108SCunyin Chang static int num_devs = 0; 27f07ed6efSGangCao static int g_shm_id = -1; 2898416108SCunyin Chang 2998416108SCunyin Chang #define foreach_dev(iter) \ 3098416108SCunyin Chang for (iter = devs; iter - devs < num_devs; iter++) 3198416108SCunyin Chang 3273b0afa8SCunyin Chang enum controller_display_model { 3373b0afa8SCunyin Chang CONTROLLER_DISPLAY_ALL = 0x0, 3473b0afa8SCunyin Chang CONTROLLER_DISPLAY_SIMPLISTIC = 0x1, 3573b0afa8SCunyin Chang }; 3673b0afa8SCunyin Chang 372e61a144SDaniel Verkamp static int 382e61a144SDaniel Verkamp cmp_devs(const void *ap, const void *bp) 392e61a144SDaniel Verkamp { 402e61a144SDaniel Verkamp const struct dev *a = ap, *b = bp; 412e61a144SDaniel Verkamp 42fcb00f37SDaniel Verkamp return spdk_pci_addr_compare(&a->pci_addr, &b->pci_addr); 432e61a144SDaniel Verkamp } 442e61a144SDaniel Verkamp 4598416108SCunyin Chang static bool 4632e838afSBen Walker probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, 47fcb00f37SDaniel Verkamp struct spdk_nvme_ctrlr_opts *opts) 4898416108SCunyin Chang { 4998416108SCunyin Chang return true; 5098416108SCunyin Chang } 5198416108SCunyin Chang 5298416108SCunyin Chang static void 538f876a61SDaniel Verkamp identify_common_ns_cb(void *cb_arg, const struct spdk_nvme_cpl *cpl) 548f876a61SDaniel Verkamp { 558f876a61SDaniel Verkamp struct dev *dev = cb_arg; 568f876a61SDaniel Verkamp 578f876a61SDaniel Verkamp if (cpl->status.sc != SPDK_NVME_SC_SUCCESS) { 588f876a61SDaniel Verkamp /* Identify Namespace for NSID = FFFFFFFFh is optional, so failure is not fatal. */ 598a44220bSJohn Meneghini spdk_dma_free(dev->common_ns_data); 608f876a61SDaniel Verkamp dev->common_ns_data = NULL; 618f876a61SDaniel Verkamp } 628f876a61SDaniel Verkamp 638f876a61SDaniel Verkamp dev->outstanding_admin_cmds--; 648f876a61SDaniel Verkamp } 658f876a61SDaniel Verkamp 668f876a61SDaniel Verkamp static void 6732e838afSBen Walker attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, 68fcb00f37SDaniel Verkamp struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts) 6998416108SCunyin Chang { 7098416108SCunyin Chang struct dev *dev; 718f876a61SDaniel Verkamp struct spdk_nvme_cmd cmd; 7298416108SCunyin Chang 7398416108SCunyin Chang /* add to dev list */ 74592fc6f4SGangCao dev = &devs[num_devs]; 75592fc6f4SGangCao if (spdk_pci_addr_parse(&dev->pci_addr, trid->traddr) != 0) { 76592fc6f4SGangCao fprintf(stderr, "spdk_pci_addr_parse failure\n"); 77592fc6f4SGangCao assert(false); 78592fc6f4SGangCao return; 79592fc6f4SGangCao } 80592fc6f4SGangCao num_devs++; 81592fc6f4SGangCao 8298416108SCunyin Chang dev->ctrlr = ctrlr; 838f876a61SDaniel Verkamp 848f876a61SDaniel Verkamp /* Retrieve controller data */ 858f876a61SDaniel Verkamp dev->cdata = spdk_nvme_ctrlr_get_data(dev->ctrlr); 868f876a61SDaniel Verkamp 878a44220bSJohn Meneghini dev->common_ns_data = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ns_data), 4096, NULL); 888f876a61SDaniel Verkamp if (dev->common_ns_data == NULL) { 898f876a61SDaniel Verkamp fprintf(stderr, "common_ns_data allocation failure\n"); 908f876a61SDaniel Verkamp return; 918f876a61SDaniel Verkamp } 928f876a61SDaniel Verkamp 938f876a61SDaniel Verkamp /* Identify Namespace with NSID set to FFFFFFFFh to get common namespace capabilities. */ 948f876a61SDaniel Verkamp memset(&cmd, 0, sizeof(cmd)); 958f876a61SDaniel Verkamp cmd.opc = SPDK_NVME_OPC_IDENTIFY; 961fea1fccSChangpeng Liu cmd.cdw10_bits.identify.cns = 0; /* CNS = 0 (Identify Namespace) */ 978f876a61SDaniel Verkamp cmd.nsid = SPDK_NVME_GLOBAL_NS_TAG; 988f876a61SDaniel Verkamp 998f876a61SDaniel Verkamp dev->outstanding_admin_cmds++; 1008f876a61SDaniel Verkamp if (spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, &cmd, dev->common_ns_data, 1018f876a61SDaniel Verkamp sizeof(struct spdk_nvme_ns_data), identify_common_ns_cb, dev) != 0) { 1028f876a61SDaniel Verkamp dev->outstanding_admin_cmds--; 1038a44220bSJohn Meneghini spdk_dma_free(dev->common_ns_data); 1048f876a61SDaniel Verkamp dev->common_ns_data = NULL; 1058f876a61SDaniel Verkamp } 1068f876a61SDaniel Verkamp 1078f876a61SDaniel Verkamp while (dev->outstanding_admin_cmds) { 1088f876a61SDaniel Verkamp spdk_nvme_ctrlr_process_admin_completions(ctrlr); 1098f876a61SDaniel Verkamp } 11098416108SCunyin Chang } 11198416108SCunyin Chang 1128dd1cd21SBen Walker static void 1138dd1cd21SBen Walker usage(void) 11498416108SCunyin Chang { 11598416108SCunyin Chang printf("NVMe Management Options"); 11698416108SCunyin Chang printf("\n"); 11798416108SCunyin Chang printf("\t[1: list controllers]\n"); 11898416108SCunyin Chang printf("\t[2: create namespace]\n"); 11998416108SCunyin Chang printf("\t[3: delete namespace]\n"); 12098416108SCunyin Chang printf("\t[4: attach namespace to controller]\n"); 12198416108SCunyin Chang printf("\t[5: detach namespace from controller]\n"); 122eae68857SCunyin Chang printf("\t[6: format namespace or controller]\n"); 1230f805b36SCunyin Chang printf("\t[7: firmware update]\n"); 1247250ec64SChunyang Hui printf("\t[8: opal]\n"); 12555f5b205SHui, Chunyang printf("\t[9: quit]\n"); 12698416108SCunyin Chang } 12798416108SCunyin Chang 12898416108SCunyin Chang static void 1294e91a0b0SGangCao display_namespace_dpc(const struct spdk_nvme_ns_data *nsdata) 1304e91a0b0SGangCao { 1314e91a0b0SGangCao if (nsdata->dpc.pit1 || nsdata->dpc.pit2 || nsdata->dpc.pit3) { 1324e91a0b0SGangCao if (nsdata->dpc.pit1) { 1334e91a0b0SGangCao printf("PIT1 "); 1344e91a0b0SGangCao } 1354e91a0b0SGangCao 1364e91a0b0SGangCao if (nsdata->dpc.pit2) { 1374e91a0b0SGangCao printf("PIT2 "); 1384e91a0b0SGangCao } 1394e91a0b0SGangCao 1404e91a0b0SGangCao if (nsdata->dpc.pit3) { 1414e91a0b0SGangCao printf("PIT3 "); 1424e91a0b0SGangCao } 1434e91a0b0SGangCao } else { 1444e91a0b0SGangCao printf("Not Supported\n"); 1454e91a0b0SGangCao return; 1464e91a0b0SGangCao } 1474e91a0b0SGangCao 1484e91a0b0SGangCao if (nsdata->dpc.md_start && nsdata->dpc.md_end) { 1494e91a0b0SGangCao printf("Location: Head or Tail\n"); 1504e91a0b0SGangCao } else if (nsdata->dpc.md_start) { 1514e91a0b0SGangCao printf("Location: Head\n"); 1524e91a0b0SGangCao } else if (nsdata->dpc.md_end) { 1534e91a0b0SGangCao printf("Location: Tail\n"); 1544e91a0b0SGangCao } else { 1554e91a0b0SGangCao printf("Not Supported\n"); 1564e91a0b0SGangCao } 1574e91a0b0SGangCao } 1584e91a0b0SGangCao 1594e91a0b0SGangCao static void 16098416108SCunyin Chang display_namespace(struct spdk_nvme_ns *ns) 16198416108SCunyin Chang { 16298416108SCunyin Chang const struct spdk_nvme_ns_data *nsdata; 16398416108SCunyin Chang uint32_t i; 1647bbeb80aSAnkit Kumar uint32_t format_index; 16598416108SCunyin Chang 16698416108SCunyin Chang nsdata = spdk_nvme_ns_get_data(ns); 1677bbeb80aSAnkit Kumar format_index = spdk_nvme_ns_get_format_index(nsdata); 16898416108SCunyin Chang 16998416108SCunyin Chang printf("Namespace ID:%d\n", spdk_nvme_ns_get_id(ns)); 17098416108SCunyin Chang 17198416108SCunyin Chang printf("Size (in LBAs): %lld (%lldM)\n", 17298416108SCunyin Chang (long long)nsdata->nsze, 17398416108SCunyin Chang (long long)nsdata->nsze / 1024 / 1024); 17498416108SCunyin Chang printf("Capacity (in LBAs): %lld (%lldM)\n", 17598416108SCunyin Chang (long long)nsdata->ncap, 17698416108SCunyin Chang (long long)nsdata->ncap / 1024 / 1024); 17798416108SCunyin Chang printf("Utilization (in LBAs): %lld (%lldM)\n", 17898416108SCunyin Chang (long long)nsdata->nuse, 17998416108SCunyin Chang (long long)nsdata->nuse / 1024 / 1024); 18030089f89SCunyin Chang printf("Format Progress Indicator: %s\n", 18130089f89SCunyin Chang nsdata->fpi.fpi_supported ? "Supported" : "Not Supported"); 18259970a89SDaniel Verkamp if (nsdata->fpi.fpi_supported && nsdata->fpi.percentage_remaining) { 18330089f89SCunyin Chang printf("Formatted Percentage: %d%%\n", 100 - nsdata->fpi.percentage_remaining); 18459970a89SDaniel Verkamp } 18598416108SCunyin Chang printf("Number of LBA Formats: %d\n", nsdata->nlbaf + 1); 18698416108SCunyin Chang printf("Current LBA Format: LBA Format #%02d\n", 1877bbeb80aSAnkit Kumar format_index); 18898416108SCunyin Chang for (i = 0; i <= nsdata->nlbaf; i++) 18998416108SCunyin Chang printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d\n", 19098416108SCunyin Chang i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms); 1914e91a0b0SGangCao printf("Data Protection Capabilities:"); 1924e91a0b0SGangCao display_namespace_dpc(nsdata); 1934e91a0b0SGangCao if (SPDK_NVME_FMT_NVM_PROTECTION_DISABLE == nsdata->dps.pit) { 1944e91a0b0SGangCao printf("Data Protection Setting: N/A\n"); 1954e91a0b0SGangCao } else { 1964e91a0b0SGangCao printf("Data Protection Setting: PIT%d Location: %s\n", 1974e91a0b0SGangCao nsdata->dps.pit, nsdata->dps.md_start ? "Head" : "Tail"); 1984e91a0b0SGangCao } 1994e91a0b0SGangCao printf("Multipath IO and Sharing: %s\n", 2004e91a0b0SGangCao nsdata->nmic.can_share ? "Supported" : "Not Supported"); 20198416108SCunyin Chang printf("\n"); 20298416108SCunyin Chang } 20398416108SCunyin Chang 20498416108SCunyin Chang static void 20573b0afa8SCunyin Chang display_controller(struct dev *dev, int model) 20698416108SCunyin Chang { 2078bab99fbSTomasz Zawadzki struct spdk_nvme_ns *ns; 20898416108SCunyin Chang const struct spdk_nvme_ctrlr_data *cdata; 20998416108SCunyin Chang uint8_t str[128]; 210aa09ce09SChunyang Hui uint32_t nsid; 21198416108SCunyin Chang 21298416108SCunyin Chang cdata = spdk_nvme_ctrlr_get_data(dev->ctrlr); 213173b4144SDaniel Verkamp 214173b4144SDaniel Verkamp if (model == CONTROLLER_DISPLAY_SIMPLISTIC) { 215173b4144SDaniel Verkamp printf("%04x:%02x:%02x.%02x ", 216fcb00f37SDaniel Verkamp dev->pci_addr.domain, dev->pci_addr.bus, dev->pci_addr.dev, dev->pci_addr.func); 217173b4144SDaniel Verkamp printf("%-40.40s %-20.20s ", 218173b4144SDaniel Verkamp cdata->mn, cdata->sn); 219173b4144SDaniel Verkamp printf("%5d ", cdata->cntlid); 220173b4144SDaniel Verkamp printf("\n"); 221173b4144SDaniel Verkamp return; 222173b4144SDaniel Verkamp } 223173b4144SDaniel Verkamp 22498416108SCunyin Chang printf("=====================================================\n"); 22573b0afa8SCunyin Chang printf("NVMe Controller: %04x:%02x:%02x.%02x\n", 226fcb00f37SDaniel Verkamp dev->pci_addr.domain, dev->pci_addr.bus, dev->pci_addr.dev, dev->pci_addr.func); 22773b0afa8SCunyin Chang printf("============================\n"); 22898416108SCunyin Chang printf("Controller Capabilities/Features\n"); 22998416108SCunyin Chang printf("Controller ID: %d\n", cdata->cntlid); 23098416108SCunyin Chang snprintf(str, sizeof(cdata->sn) + 1, "%s", cdata->sn); 23198416108SCunyin Chang printf("Serial Number: %s\n", str); 23298416108SCunyin Chang printf("\n"); 233173b4144SDaniel Verkamp 23498416108SCunyin Chang printf("Admin Command Set Attributes\n"); 23598416108SCunyin Chang printf("============================\n"); 23698416108SCunyin Chang printf("Namespace Manage And Attach: %s\n", 23798416108SCunyin Chang cdata->oacs.ns_manage ? "Supported" : "Not Supported"); 238eae68857SCunyin Chang printf("Namespace Format: %s\n", 239eae68857SCunyin Chang cdata->oacs.format ? "Supported" : "Not Supported"); 240eae68857SCunyin Chang printf("\n"); 241eae68857SCunyin Chang printf("NVM Command Set Attributes\n"); 242eae68857SCunyin Chang printf("============================\n"); 243eae68857SCunyin Chang if (cdata->fna.format_all_ns) { 244eae68857SCunyin Chang printf("Namespace format operation applies to all namespaces\n"); 245eae68857SCunyin Chang } else { 246eae68857SCunyin Chang printf("Namespace format operation applies to per namespace\n"); 247eae68857SCunyin Chang } 24898416108SCunyin Chang printf("\n"); 24998416108SCunyin Chang printf("Namespace Attributes\n"); 25098416108SCunyin Chang printf("============================\n"); 251aa09ce09SChunyang Hui for (nsid = spdk_nvme_ctrlr_get_first_active_ns(dev->ctrlr); 252aa09ce09SChunyang Hui nsid != 0; nsid = spdk_nvme_ctrlr_get_next_active_ns(dev->ctrlr, nsid)) { 2538bab99fbSTomasz Zawadzki ns = spdk_nvme_ctrlr_get_ns(dev->ctrlr, nsid); 2548bab99fbSTomasz Zawadzki assert(ns != NULL); 2558bab99fbSTomasz Zawadzki display_namespace(ns); 25698416108SCunyin Chang } 25798416108SCunyin Chang } 25898416108SCunyin Chang 25998416108SCunyin Chang static void 26098416108SCunyin Chang display_controller_list(void) 26198416108SCunyin Chang { 26298416108SCunyin Chang struct dev *iter; 26398416108SCunyin Chang 26498416108SCunyin Chang foreach_dev(iter) { 26573b0afa8SCunyin Chang display_controller(iter, CONTROLLER_DISPLAY_ALL); 26673b0afa8SCunyin Chang } 26773b0afa8SCunyin Chang } 26873b0afa8SCunyin Chang 26973c9bd29SIsaac Otsiabah static char * 27063133871SChunyang Hui get_line(char *buf, int buf_size, FILE *f, bool secret) 27173c9bd29SIsaac Otsiabah { 27263133871SChunyang Hui char *ch; 27373c9bd29SIsaac Otsiabah size_t len; 27463133871SChunyang Hui struct termios default_attr = {}, new_attr = {}; 27563133871SChunyang Hui int ret; 27673c9bd29SIsaac Otsiabah 27763133871SChunyang Hui if (secret) { 27863133871SChunyang Hui ret = tcgetattr(STDIN_FILENO, &default_attr); 27963133871SChunyang Hui if (ret) { 28073c9bd29SIsaac Otsiabah return NULL; 28173c9bd29SIsaac Otsiabah } 28273c9bd29SIsaac Otsiabah 28363133871SChunyang Hui new_attr = default_attr; 28463133871SChunyang Hui new_attr.c_lflag &= ~ECHO; /* disable echo */ 28563133871SChunyang Hui ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_attr); 28663133871SChunyang Hui if (ret) { 28763133871SChunyang Hui return NULL; 28863133871SChunyang Hui } 28963133871SChunyang Hui } 29063133871SChunyang Hui 29163133871SChunyang Hui ch = fgets(buf, buf_size, f); 29263133871SChunyang Hui if (ch == NULL) { 29363133871SChunyang Hui return NULL; 29463133871SChunyang Hui } 29563133871SChunyang Hui 29663133871SChunyang Hui if (secret) { 29734edd9f1SKamil Godzwon ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, &default_attr); /* restore default config */ 29863133871SChunyang Hui if (ret) { 29963133871SChunyang Hui return NULL; 30063133871SChunyang Hui } 30163133871SChunyang Hui } 30263133871SChunyang Hui 30373c9bd29SIsaac Otsiabah len = strlen(buf); 30473c9bd29SIsaac Otsiabah if (len > 0 && buf[len - 1] == '\n') { 30573c9bd29SIsaac Otsiabah buf[len - 1] = '\0'; 30673c9bd29SIsaac Otsiabah } 30773c9bd29SIsaac Otsiabah return buf; 30873c9bd29SIsaac Otsiabah } 30973c9bd29SIsaac Otsiabah 31073b0afa8SCunyin Chang static struct dev * 31173b0afa8SCunyin Chang get_controller(void) 31273b0afa8SCunyin Chang { 31303aa3af0SDaniel Verkamp struct spdk_pci_addr pci_addr; 31473b0afa8SCunyin Chang char address[64]; 31573b0afa8SCunyin Chang char *p; 31673b0afa8SCunyin Chang int ch; 31773b0afa8SCunyin Chang struct dev *iter; 31873b0afa8SCunyin Chang 31973b0afa8SCunyin Chang memset(address, 0, sizeof(address)); 32073b0afa8SCunyin Chang 32173b0afa8SCunyin Chang foreach_dev(iter) { 32273b0afa8SCunyin Chang display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC); 32373b0afa8SCunyin Chang } 32473b0afa8SCunyin Chang 32573b0afa8SCunyin Chang printf("Please Input PCI Address(domain:bus:dev.func):\n"); 32673b0afa8SCunyin Chang 32773b0afa8SCunyin Chang while ((ch = getchar()) != '\n' && ch != EOF); 32863133871SChunyang Hui p = get_line(address, 64, stdin, false); 32916986894SDaniel Verkamp if (p == NULL) { 33016986894SDaniel Verkamp return NULL; 33116986894SDaniel Verkamp } 33273b0afa8SCunyin Chang 33373b0afa8SCunyin Chang while (isspace(*p)) { 33473b0afa8SCunyin Chang p++; 33573b0afa8SCunyin Chang } 33673b0afa8SCunyin Chang 337bbd7e1c4SDaniel Verkamp if (spdk_pci_addr_parse(&pci_addr, p) < 0) { 338e3cabfafSDaniel Verkamp return NULL; 339e3cabfafSDaniel Verkamp } 340e3cabfafSDaniel Verkamp 34173b0afa8SCunyin Chang foreach_dev(iter) { 342fcb00f37SDaniel Verkamp if (spdk_pci_addr_compare(&pci_addr, &iter->pci_addr) == 0) { 34373b0afa8SCunyin Chang return iter; 34473b0afa8SCunyin Chang } 34573b0afa8SCunyin Chang } 34673b0afa8SCunyin Chang return NULL; 34773b0afa8SCunyin Chang } 34873b0afa8SCunyin Chang 3498f876a61SDaniel Verkamp static int 3508f876a61SDaniel Verkamp get_lba_format(const struct spdk_nvme_ns_data *ns_data) 3518f876a61SDaniel Verkamp { 3528f876a61SDaniel Verkamp int lbaf, i; 3538f876a61SDaniel Verkamp 3548f876a61SDaniel Verkamp printf("\nSupported LBA formats:\n"); 3558f876a61SDaniel Verkamp for (i = 0; i <= ns_data->nlbaf; i++) { 3568f876a61SDaniel Verkamp printf("%2d: %d data bytes", i, 1 << ns_data->lbaf[i].lbads); 3578f876a61SDaniel Verkamp if (ns_data->lbaf[i].ms) { 3588f876a61SDaniel Verkamp printf(" + %d metadata bytes", ns_data->lbaf[i].ms); 3598f876a61SDaniel Verkamp } 3608f876a61SDaniel Verkamp printf("\n"); 3618f876a61SDaniel Verkamp } 3628f876a61SDaniel Verkamp 3638f876a61SDaniel Verkamp printf("Please input LBA format index (0 - %d):\n", ns_data->nlbaf); 3648f876a61SDaniel Verkamp if (scanf("%d", &lbaf) != 1 || lbaf > ns_data->nlbaf) { 3658f876a61SDaniel Verkamp return -1; 3668f876a61SDaniel Verkamp } 3678f876a61SDaniel Verkamp 3688f876a61SDaniel Verkamp return lbaf; 3698f876a61SDaniel Verkamp } 3708f876a61SDaniel Verkamp 37173b0afa8SCunyin Chang static void 372fc8d73f8SDaniel Verkamp identify_allocated_ns_cb(void *cb_arg, const struct spdk_nvme_cpl *cpl) 373fc8d73f8SDaniel Verkamp { 374fc8d73f8SDaniel Verkamp struct dev *dev = cb_arg; 375fc8d73f8SDaniel Verkamp 376fc8d73f8SDaniel Verkamp dev->outstanding_admin_cmds--; 377fc8d73f8SDaniel Verkamp } 378fc8d73f8SDaniel Verkamp 379fc8d73f8SDaniel Verkamp static uint32_t 380fc8d73f8SDaniel Verkamp get_allocated_nsid(struct dev *dev) 381fc8d73f8SDaniel Verkamp { 382fc8d73f8SDaniel Verkamp uint32_t nsid; 383fc8d73f8SDaniel Verkamp size_t i; 384fc8d73f8SDaniel Verkamp struct spdk_nvme_ns_list *ns_list; 385fc8d73f8SDaniel Verkamp struct spdk_nvme_cmd cmd = {0}; 386fc8d73f8SDaniel Verkamp 3878a44220bSJohn Meneghini ns_list = spdk_dma_zmalloc(sizeof(*ns_list), 4096, NULL); 388fc8d73f8SDaniel Verkamp if (ns_list == NULL) { 389fc8d73f8SDaniel Verkamp printf("Allocation error\n"); 390fc8d73f8SDaniel Verkamp return 0; 391fc8d73f8SDaniel Verkamp } 392fc8d73f8SDaniel Verkamp 393fc8d73f8SDaniel Verkamp cmd.opc = SPDK_NVME_OPC_IDENTIFY; 3941fea1fccSChangpeng Liu cmd.cdw10_bits.identify.cns = SPDK_NVME_IDENTIFY_ALLOCATED_NS_LIST; 395fc8d73f8SDaniel Verkamp cmd.nsid = 0; 396fc8d73f8SDaniel Verkamp 397fc8d73f8SDaniel Verkamp dev->outstanding_admin_cmds++; 398fc8d73f8SDaniel Verkamp if (spdk_nvme_ctrlr_cmd_admin_raw(dev->ctrlr, &cmd, ns_list, sizeof(*ns_list), 399fc8d73f8SDaniel Verkamp identify_allocated_ns_cb, dev)) { 400fc8d73f8SDaniel Verkamp printf("Identify command failed\n"); 4018a44220bSJohn Meneghini spdk_dma_free(ns_list); 402fc8d73f8SDaniel Verkamp return 0; 403fc8d73f8SDaniel Verkamp } 404fc8d73f8SDaniel Verkamp 405fc8d73f8SDaniel Verkamp while (dev->outstanding_admin_cmds) { 406fc8d73f8SDaniel Verkamp spdk_nvme_ctrlr_process_admin_completions(dev->ctrlr); 407fc8d73f8SDaniel Verkamp } 408fc8d73f8SDaniel Verkamp 409fc8d73f8SDaniel Verkamp printf("Allocated Namespace IDs:\n"); 410b58a5d73SDaniel Verkamp for (i = 0; i < SPDK_COUNTOF(ns_list->ns_list); i++) { 411fc8d73f8SDaniel Verkamp if (ns_list->ns_list[i] == 0) { 412fc8d73f8SDaniel Verkamp break; 413fc8d73f8SDaniel Verkamp } 414fc8d73f8SDaniel Verkamp printf("%u\n", ns_list->ns_list[i]); 415fc8d73f8SDaniel Verkamp } 416fc8d73f8SDaniel Verkamp 4178a44220bSJohn Meneghini spdk_dma_free(ns_list); 418fc8d73f8SDaniel Verkamp 419fc8d73f8SDaniel Verkamp printf("Please Input Namespace ID:\n"); 420fc8d73f8SDaniel Verkamp if (!scanf("%u", &nsid)) { 421fc8d73f8SDaniel Verkamp printf("Invalid Namespace ID\n"); 422fc8d73f8SDaniel Verkamp nsid = 0; 423fc8d73f8SDaniel Verkamp } 424fc8d73f8SDaniel Verkamp 425fc8d73f8SDaniel Verkamp return nsid; 426fc8d73f8SDaniel Verkamp } 427fc8d73f8SDaniel Verkamp 428fc8d73f8SDaniel Verkamp static void 42973b0afa8SCunyin Chang ns_attach(struct dev *device, int attachment_op, int ctrlr_id, int ns_id) 43073b0afa8SCunyin Chang { 43173b0afa8SCunyin Chang int ret = 0; 43273b0afa8SCunyin Chang struct spdk_nvme_ctrlr_list *ctrlr_list; 43373b0afa8SCunyin Chang 4348a44220bSJohn Meneghini ctrlr_list = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ctrlr_list), 4352224ff21SBen Walker 4096, NULL); 43673b0afa8SCunyin Chang if (ctrlr_list == NULL) { 43773b0afa8SCunyin Chang printf("Allocation error (controller list)\n"); 43873b0afa8SCunyin Chang exit(1); 43973b0afa8SCunyin Chang } 44073b0afa8SCunyin Chang 44173b0afa8SCunyin Chang ctrlr_list->ctrlr_count = 1; 44273b0afa8SCunyin Chang ctrlr_list->ctrlr_list[0] = ctrlr_id; 44373b0afa8SCunyin Chang 44473b0afa8SCunyin Chang if (attachment_op == SPDK_NVME_NS_CTRLR_ATTACH) { 44573b0afa8SCunyin Chang ret = spdk_nvme_ctrlr_attach_ns(device->ctrlr, ns_id, ctrlr_list); 44673b0afa8SCunyin Chang } else if (attachment_op == SPDK_NVME_NS_CTRLR_DETACH) { 44773b0afa8SCunyin Chang ret = spdk_nvme_ctrlr_detach_ns(device->ctrlr, ns_id, ctrlr_list); 44873b0afa8SCunyin Chang } 44973b0afa8SCunyin Chang 45073b0afa8SCunyin Chang if (ret) { 45173b0afa8SCunyin Chang fprintf(stdout, "ns attach: Failed\n"); 45273b0afa8SCunyin Chang } 45373b0afa8SCunyin Chang 4548a44220bSJohn Meneghini spdk_dma_free(ctrlr_list); 45573b0afa8SCunyin Chang } 45673b0afa8SCunyin Chang 45773b0afa8SCunyin Chang static void 4584e91a0b0SGangCao ns_manage_add(struct dev *device, uint64_t ns_size, uint64_t ns_capacity, int ns_lbasize, 4594e91a0b0SGangCao uint8_t ns_dps_type, uint8_t ns_dps_location, uint8_t ns_nmic) 46073b0afa8SCunyin Chang { 4614957d264SDaniel Verkamp uint32_t nsid; 46273b0afa8SCunyin Chang struct spdk_nvme_ns_data *ndata; 46373b0afa8SCunyin Chang 4648a44220bSJohn Meneghini ndata = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ns_data), 4096, NULL); 46573b0afa8SCunyin Chang if (ndata == NULL) { 46673b0afa8SCunyin Chang printf("Allocation error (namespace data)\n"); 46773b0afa8SCunyin Chang exit(1); 46873b0afa8SCunyin Chang } 46973b0afa8SCunyin Chang 47073b0afa8SCunyin Chang ndata->nsze = ns_size; 47173b0afa8SCunyin Chang ndata->ncap = ns_capacity; 4727bbeb80aSAnkit Kumar ndata->flbas.format = ns_lbasize & 0xF; 4737bbeb80aSAnkit Kumar ndata->flbas.msb_format = (ns_lbasize >> 4) & 0x3; 4744e91a0b0SGangCao if (SPDK_NVME_FMT_NVM_PROTECTION_DISABLE != ns_dps_type) { 4754e91a0b0SGangCao ndata->dps.pit = ns_dps_type; 4764e91a0b0SGangCao ndata->dps.md_start = ns_dps_location; 4774e91a0b0SGangCao } 4784e91a0b0SGangCao ndata->nmic.can_share = ns_nmic; 4794957d264SDaniel Verkamp nsid = spdk_nvme_ctrlr_create_ns(device->ctrlr, ndata); 4804957d264SDaniel Verkamp if (nsid == 0) { 48173b0afa8SCunyin Chang fprintf(stdout, "ns manage: Failed\n"); 4824957d264SDaniel Verkamp } else { 4834957d264SDaniel Verkamp printf("Created namespace ID %u\n", nsid); 48473b0afa8SCunyin Chang } 48573b0afa8SCunyin Chang 4868a44220bSJohn Meneghini spdk_dma_free(ndata); 48773b0afa8SCunyin Chang } 48873b0afa8SCunyin Chang 48973b0afa8SCunyin Chang static void 49073b0afa8SCunyin Chang ns_manage_delete(struct dev *device, int ns_id) 49173b0afa8SCunyin Chang { 49273b0afa8SCunyin Chang int ret = 0; 49373b0afa8SCunyin Chang 49473b0afa8SCunyin Chang ret = spdk_nvme_ctrlr_delete_ns(device->ctrlr, ns_id); 49573b0afa8SCunyin Chang if (ret) { 49673b0afa8SCunyin Chang fprintf(stdout, "ns manage: Failed\n"); 49773b0afa8SCunyin Chang return; 49898416108SCunyin Chang } 49998416108SCunyin Chang } 50098416108SCunyin Chang 50198416108SCunyin Chang static void 502eae68857SCunyin Chang nvme_manage_format(struct dev *device, int ns_id, int ses, int pi, int pil, int ms, int lbaf) 503eae68857SCunyin Chang { 504eae68857SCunyin Chang int ret = 0; 505eae68857SCunyin Chang struct spdk_nvme_format format = {}; 506eae68857SCunyin Chang 5077bbeb80aSAnkit Kumar format.lbaf = lbaf & 0xF; 508eae68857SCunyin Chang format.ms = ms; 509eae68857SCunyin Chang format.pi = pi; 510eae68857SCunyin Chang format.pil = pil; 511eae68857SCunyin Chang format.ses = ses; 5127bbeb80aSAnkit Kumar format.lbafu = (lbaf >> 4) & 0x3; 513eae68857SCunyin Chang ret = spdk_nvme_ctrlr_format(device->ctrlr, ns_id, &format); 514eae68857SCunyin Chang if (ret) { 515eae68857SCunyin Chang fprintf(stdout, "nvme format: Failed\n"); 516eae68857SCunyin Chang return; 517eae68857SCunyin Chang } 518eae68857SCunyin Chang } 519eae68857SCunyin Chang 520eae68857SCunyin Chang static void 52198416108SCunyin Chang attach_and_detach_ns(int attachment_op) 52298416108SCunyin Chang { 523fc8d73f8SDaniel Verkamp uint32_t nsid; 52498416108SCunyin Chang struct dev *ctrlr; 52598416108SCunyin Chang 52698416108SCunyin Chang ctrlr = get_controller(); 52798416108SCunyin Chang if (ctrlr == NULL) { 52873b0afa8SCunyin Chang printf("Invalid controller PCI Address.\n"); 52998416108SCunyin Chang return; 53098416108SCunyin Chang } 53198416108SCunyin Chang 532ce13ccf8SDaniel Verkamp if (!ctrlr->cdata->oacs.ns_manage) { 533ce13ccf8SDaniel Verkamp printf("Controller does not support ns management\n"); 534ce13ccf8SDaniel Verkamp return; 535ce13ccf8SDaniel Verkamp } 536ce13ccf8SDaniel Verkamp 537fc8d73f8SDaniel Verkamp nsid = get_allocated_nsid(ctrlr); 538fc8d73f8SDaniel Verkamp if (nsid == 0) { 53998416108SCunyin Chang printf("Invalid Namespace ID\n"); 54098416108SCunyin Chang return; 54198416108SCunyin Chang } 54298416108SCunyin Chang 543fc8d73f8SDaniel Verkamp ns_attach(ctrlr, attachment_op, ctrlr->cdata->cntlid, nsid); 54498416108SCunyin Chang } 54598416108SCunyin Chang 54698416108SCunyin Chang static void 54798416108SCunyin Chang add_ns(void) 54898416108SCunyin Chang { 5494e91a0b0SGangCao uint64_t ns_size = 0; 5504e91a0b0SGangCao uint64_t ns_capacity = 0; 5518f876a61SDaniel Verkamp int ns_lbasize; 5524e91a0b0SGangCao int ns_dps_type = 0; 5534e91a0b0SGangCao int ns_dps_location = 0; 5544e91a0b0SGangCao int ns_nmic = 0; 5554e91a0b0SGangCao struct dev *ctrlr = NULL; 55698416108SCunyin Chang 55798416108SCunyin Chang ctrlr = get_controller(); 55898416108SCunyin Chang if (ctrlr == NULL) { 55973b0afa8SCunyin Chang printf("Invalid controller PCI Address.\n"); 56098416108SCunyin Chang return; 56198416108SCunyin Chang } 56298416108SCunyin Chang 563ce13ccf8SDaniel Verkamp if (!ctrlr->cdata->oacs.ns_manage) { 564ce13ccf8SDaniel Verkamp printf("Controller does not support ns management\n"); 565ce13ccf8SDaniel Verkamp return; 566ce13ccf8SDaniel Verkamp } 567ce13ccf8SDaniel Verkamp 5688f876a61SDaniel Verkamp if (!ctrlr->common_ns_data) { 5698f876a61SDaniel Verkamp printf("Controller did not return common namespace capabilities\n"); 5708f876a61SDaniel Verkamp return; 5718f876a61SDaniel Verkamp } 5728f876a61SDaniel Verkamp 5738f876a61SDaniel Verkamp ns_lbasize = get_lba_format(ctrlr->common_ns_data); 5748f876a61SDaniel Verkamp if (ns_lbasize < 0) { 5758f876a61SDaniel Verkamp printf("Invalid LBA format number\n"); 5768f876a61SDaniel Verkamp return; 5778f876a61SDaniel Verkamp } 5788f876a61SDaniel Verkamp 57998416108SCunyin Chang printf("Please Input Namespace Size (in LBAs):\n"); 580121d632cSJim Harris if (!scanf("%" SCNu64, &ns_size)) { 58198416108SCunyin Chang printf("Invalid Namespace Size\n"); 58298416108SCunyin Chang while (getchar() != '\n'); 58398416108SCunyin Chang return; 58498416108SCunyin Chang } 58598416108SCunyin Chang 58698416108SCunyin Chang printf("Please Input Namespace Capacity (in LBAs):\n"); 587121d632cSJim Harris if (!scanf("%" SCNu64, &ns_capacity)) { 58898416108SCunyin Chang printf("Invalid Namespace Capacity\n"); 58998416108SCunyin Chang while (getchar() != '\n'); 59098416108SCunyin Chang return; 59198416108SCunyin Chang } 59298416108SCunyin Chang 5934e91a0b0SGangCao printf("Please Input Data Protection Type (0 - 3):\n"); 5944e91a0b0SGangCao if (!scanf("%d", &ns_dps_type)) { 5954e91a0b0SGangCao printf("Invalid Data Protection Type\n"); 5964e91a0b0SGangCao while (getchar() != '\n'); 5974e91a0b0SGangCao return; 5984e91a0b0SGangCao } 5994e91a0b0SGangCao 6004e91a0b0SGangCao if (SPDK_NVME_FMT_NVM_PROTECTION_DISABLE != ns_dps_type) { 6014e91a0b0SGangCao printf("Please Input Data Protection Location (1: Head; 0: Tail):\n"); 6024e91a0b0SGangCao if (!scanf("%d", &ns_dps_location)) { 6034e91a0b0SGangCao printf("Invalid Data Protection Location\n"); 6044e91a0b0SGangCao while (getchar() != '\n'); 6054e91a0b0SGangCao return; 6064e91a0b0SGangCao } 6074e91a0b0SGangCao } 6084e91a0b0SGangCao 6094e91a0b0SGangCao printf("Please Input Multi-path IO and Sharing Capabilities (1: Share; 0: Private):\n"); 6104e91a0b0SGangCao if (!scanf("%d", &ns_nmic)) { 6114e91a0b0SGangCao printf("Invalid Multi-path IO and Sharing Capabilities\n"); 6124e91a0b0SGangCao while (getchar() != '\n'); 6134e91a0b0SGangCao return; 6144e91a0b0SGangCao } 6154e91a0b0SGangCao 6164e91a0b0SGangCao ns_manage_add(ctrlr, ns_size, ns_capacity, ns_lbasize, 6174e91a0b0SGangCao ns_dps_type, ns_dps_location, ns_nmic); 61898416108SCunyin Chang } 61998416108SCunyin Chang 62098416108SCunyin Chang static void 62198416108SCunyin Chang delete_ns(void) 62298416108SCunyin Chang { 62398416108SCunyin Chang int ns_id; 62498416108SCunyin Chang struct dev *ctrlr; 62598416108SCunyin Chang 62698416108SCunyin Chang ctrlr = get_controller(); 62798416108SCunyin Chang if (ctrlr == NULL) { 62873b0afa8SCunyin Chang printf("Invalid controller PCI Address.\n"); 62998416108SCunyin Chang return; 63098416108SCunyin Chang } 63198416108SCunyin Chang 632ce13ccf8SDaniel Verkamp if (!ctrlr->cdata->oacs.ns_manage) { 633ce13ccf8SDaniel Verkamp printf("Controller does not support ns management\n"); 634ce13ccf8SDaniel Verkamp return; 635ce13ccf8SDaniel Verkamp } 636ce13ccf8SDaniel Verkamp 63798416108SCunyin Chang printf("Please Input Namespace ID:\n"); 63898416108SCunyin Chang if (!scanf("%d", &ns_id)) { 63998416108SCunyin Chang printf("Invalid Namespace ID\n"); 64098416108SCunyin Chang while (getchar() != '\n'); 64198416108SCunyin Chang return; 64298416108SCunyin Chang } 64398416108SCunyin Chang 64498416108SCunyin Chang ns_manage_delete(ctrlr, ns_id); 64598416108SCunyin Chang } 64698416108SCunyin Chang 647eae68857SCunyin Chang static void 648eae68857SCunyin Chang format_nvm(void) 649eae68857SCunyin Chang { 650eae68857SCunyin Chang int ns_id; 651eae68857SCunyin Chang int ses; 652eae68857SCunyin Chang int pil; 653eae68857SCunyin Chang int pi; 654eae68857SCunyin Chang int ms; 655eae68857SCunyin Chang int lbaf; 656eae68857SCunyin Chang char option; 657eae68857SCunyin Chang struct dev *ctrlr; 6584fe88e43SDaniel Verkamp const struct spdk_nvme_ctrlr_data *cdata; 6596a3735e3SDaniel Verkamp struct spdk_nvme_ns *ns; 6606a3735e3SDaniel Verkamp const struct spdk_nvme_ns_data *nsdata; 661eae68857SCunyin Chang 662eae68857SCunyin Chang ctrlr = get_controller(); 663eae68857SCunyin Chang if (ctrlr == NULL) { 664eae68857SCunyin Chang printf("Invalid controller PCI BDF.\n"); 665eae68857SCunyin Chang return; 666eae68857SCunyin Chang } 6674fe88e43SDaniel Verkamp 6684fe88e43SDaniel Verkamp cdata = ctrlr->cdata; 6694fe88e43SDaniel Verkamp 6704fe88e43SDaniel Verkamp if (!cdata->oacs.format) { 671eae68857SCunyin Chang printf("Controller does not support Format NVM command\n"); 672eae68857SCunyin Chang return; 673eae68857SCunyin Chang } 674eae68857SCunyin Chang 6754fe88e43SDaniel Verkamp if (cdata->fna.format_all_ns) { 6765bb16e86SDaniel Verkamp ns_id = SPDK_NVME_GLOBAL_NS_TAG; 6776a3735e3SDaniel Verkamp ns = spdk_nvme_ctrlr_get_ns(ctrlr->ctrlr, 1); 678eae68857SCunyin Chang } else { 6794fe88e43SDaniel Verkamp printf("Please Input Namespace ID (1 - %d):\n", cdata->nn); 680eae68857SCunyin Chang if (!scanf("%d", &ns_id)) { 681eae68857SCunyin Chang printf("Invalid Namespace ID\n"); 682eae68857SCunyin Chang while (getchar() != '\n'); 683eae68857SCunyin Chang return; 684eae68857SCunyin Chang } 6856a3735e3SDaniel Verkamp ns = spdk_nvme_ctrlr_get_ns(ctrlr->ctrlr, ns_id); 686eae68857SCunyin Chang } 687eae68857SCunyin Chang 6886a3735e3SDaniel Verkamp if (ns == NULL) { 6896a3735e3SDaniel Verkamp printf("Namespace ID %d not found\n", ns_id); 6906a3735e3SDaniel Verkamp while (getchar() != '\n'); 6916a3735e3SDaniel Verkamp return; 6926a3735e3SDaniel Verkamp } 6936a3735e3SDaniel Verkamp 6946a3735e3SDaniel Verkamp nsdata = spdk_nvme_ns_get_data(ns); 6956a3735e3SDaniel Verkamp 696eae68857SCunyin Chang printf("Please Input Secure Erase Setting:\n"); 697eae68857SCunyin Chang printf(" 0: No secure erase operation requested\n"); 698eae68857SCunyin Chang printf(" 1: User data erase\n"); 6994fe88e43SDaniel Verkamp if (cdata->fna.crypto_erase_supported) { 700eae68857SCunyin Chang printf(" 2: Cryptographic erase\n"); 7014fe88e43SDaniel Verkamp } 702eae68857SCunyin Chang if (!scanf("%d", &ses)) { 703eae68857SCunyin Chang printf("Invalid Secure Erase Setting\n"); 704eae68857SCunyin Chang while (getchar() != '\n'); 705eae68857SCunyin Chang return; 706eae68857SCunyin Chang } 707eae68857SCunyin Chang 7088f876a61SDaniel Verkamp lbaf = get_lba_format(nsdata); 7098f876a61SDaniel Verkamp if (lbaf < 0) { 7104fe88e43SDaniel Verkamp printf("Invalid LBA format number\n"); 7114fe88e43SDaniel Verkamp return; 7124fe88e43SDaniel Verkamp } 7134fe88e43SDaniel Verkamp 7144fe88e43SDaniel Verkamp if (nsdata->lbaf[lbaf].ms) { 7154fe88e43SDaniel Verkamp printf("Please Input Protection Information:\n"); 7164fe88e43SDaniel Verkamp printf(" 0: Protection information is not enabled\n"); 7174fe88e43SDaniel Verkamp printf(" 1: Protection information is enabled, Type 1\n"); 7184fe88e43SDaniel Verkamp printf(" 2: Protection information is enabled, Type 2\n"); 7194fe88e43SDaniel Verkamp printf(" 3: Protection information is enabled, Type 3\n"); 7204fe88e43SDaniel Verkamp if (!scanf("%d", &pi)) { 7214fe88e43SDaniel Verkamp printf("Invalid protection information\n"); 7224fe88e43SDaniel Verkamp while (getchar() != '\n'); 7234fe88e43SDaniel Verkamp return; 7244fe88e43SDaniel Verkamp } 7254fe88e43SDaniel Verkamp 7264fe88e43SDaniel Verkamp if (pi) { 7274fe88e43SDaniel Verkamp printf("Please Input Protection Information Location:\n"); 7284fe88e43SDaniel Verkamp printf(" 0: Protection information transferred as the last eight bytes of metadata\n"); 7294fe88e43SDaniel Verkamp printf(" 1: Protection information transferred as the first eight bytes of metadata\n"); 7304fe88e43SDaniel Verkamp if (!scanf("%d", &pil)) { 7314fe88e43SDaniel Verkamp printf("Invalid protection information location\n"); 7324fe88e43SDaniel Verkamp while (getchar() != '\n'); 7334fe88e43SDaniel Verkamp return; 7344fe88e43SDaniel Verkamp } 7354fe88e43SDaniel Verkamp } else { 7364fe88e43SDaniel Verkamp pil = 0; 7374fe88e43SDaniel Verkamp } 7384fe88e43SDaniel Verkamp 7394fe88e43SDaniel Verkamp printf("Please Input Metadata Setting:\n"); 7404fe88e43SDaniel Verkamp printf(" 0: Metadata is transferred as part of a separate buffer\n"); 7414fe88e43SDaniel Verkamp printf(" 1: Metadata is transferred as part of an extended data LBA\n"); 7424fe88e43SDaniel Verkamp if (!scanf("%d", &ms)) { 7434fe88e43SDaniel Verkamp printf("Invalid metadata setting\n"); 7444fe88e43SDaniel Verkamp while (getchar() != '\n'); 7454fe88e43SDaniel Verkamp return; 7464fe88e43SDaniel Verkamp } 7474fe88e43SDaniel Verkamp } else { 7484fe88e43SDaniel Verkamp ms = 0; 7494fe88e43SDaniel Verkamp pi = 0; 7504fe88e43SDaniel Verkamp pil = 0; 7514fe88e43SDaniel Verkamp } 7524fe88e43SDaniel Verkamp 753eae68857SCunyin Chang printf("Warning: use this utility at your own risk.\n" 754eae68857SCunyin Chang "This command will format your namespace and all data will be lost.\n" 755eae68857SCunyin Chang "This command may take several minutes to complete,\n" 756eae68857SCunyin Chang "so do not interrupt the utility until it completes.\n" 757eae68857SCunyin Chang "Press 'Y' to continue with the format operation.\n"); 758eae68857SCunyin Chang 759eae68857SCunyin Chang while (getchar() != '\n'); 760eae68857SCunyin Chang if (!scanf("%c", &option)) { 761eae68857SCunyin Chang printf("Invalid option\n"); 762eae68857SCunyin Chang while (getchar() != '\n'); 763eae68857SCunyin Chang return; 764eae68857SCunyin Chang } 765eae68857SCunyin Chang 766eae68857SCunyin Chang if (option == 'y' || option == 'Y') { 767eae68857SCunyin Chang nvme_manage_format(ctrlr, ns_id, ses, pi, pil, ms, lbaf); 768eae68857SCunyin Chang } else { 769eae68857SCunyin Chang printf("NVMe format abort\n"); 770eae68857SCunyin Chang } 771eae68857SCunyin Chang } 772eae68857SCunyin Chang 7730f805b36SCunyin Chang static void 7740f805b36SCunyin Chang update_firmware_image(void) 7750f805b36SCunyin Chang { 7760f805b36SCunyin Chang int rc; 7770f805b36SCunyin Chang int fd = -1; 7780f805b36SCunyin Chang int slot; 7790f805b36SCunyin Chang unsigned int size; 7800f805b36SCunyin Chang struct stat fw_stat; 7810f805b36SCunyin Chang char path[256]; 7820f805b36SCunyin Chang void *fw_image; 7830f805b36SCunyin Chang struct dev *ctrlr; 7840f805b36SCunyin Chang const struct spdk_nvme_ctrlr_data *cdata; 7856fb1ce42SIsaac Otsiabah enum spdk_nvme_fw_commit_action commit_action; 7866fb1ce42SIsaac Otsiabah struct spdk_nvme_status status; 7870f805b36SCunyin Chang 7880f805b36SCunyin Chang ctrlr = get_controller(); 7890f805b36SCunyin Chang if (ctrlr == NULL) { 7900f805b36SCunyin Chang printf("Invalid controller PCI BDF.\n"); 7910f805b36SCunyin Chang return; 7920f805b36SCunyin Chang } 7930f805b36SCunyin Chang 7940f805b36SCunyin Chang cdata = ctrlr->cdata; 7950f805b36SCunyin Chang 7960f805b36SCunyin Chang if (!cdata->oacs.firmware) { 7970f805b36SCunyin Chang printf("Controller does not support firmware download and commit command\n"); 7980f805b36SCunyin Chang return; 7990f805b36SCunyin Chang } 8000f805b36SCunyin Chang 8010f805b36SCunyin Chang printf("Please Input The Path Of Firmware Image\n"); 8020f805b36SCunyin Chang 80363133871SChunyang Hui if (get_line(path, sizeof(path), stdin, false) == NULL) { 8040f805b36SCunyin Chang printf("Invalid path setting\n"); 8050f805b36SCunyin Chang while (getchar() != '\n'); 8060f805b36SCunyin Chang return; 8070f805b36SCunyin Chang } 8080f805b36SCunyin Chang 8090f805b36SCunyin Chang fd = open(path, O_RDONLY); 8100f805b36SCunyin Chang if (fd < 0) { 8110f805b36SCunyin Chang perror("Open file failed"); 8120f805b36SCunyin Chang return; 8130f805b36SCunyin Chang } 8140f805b36SCunyin Chang rc = fstat(fd, &fw_stat); 8150f805b36SCunyin Chang if (rc < 0) { 8160f805b36SCunyin Chang printf("Fstat failed\n"); 8170f805b36SCunyin Chang close(fd); 8180f805b36SCunyin Chang return; 8190f805b36SCunyin Chang } 8200f805b36SCunyin Chang 8210f805b36SCunyin Chang if (fw_stat.st_size % 4) { 8220f805b36SCunyin Chang printf("Firmware image size is not multiple of 4\n"); 8230f805b36SCunyin Chang close(fd); 8240f805b36SCunyin Chang return; 8250f805b36SCunyin Chang } 8260f805b36SCunyin Chang 8270f805b36SCunyin Chang size = fw_stat.st_size; 8280f805b36SCunyin Chang 8298a44220bSJohn Meneghini fw_image = spdk_dma_zmalloc(size, 4096, NULL); 8300f805b36SCunyin Chang if (fw_image == NULL) { 8310f805b36SCunyin Chang printf("Allocation error\n"); 8320f805b36SCunyin Chang close(fd); 8330f805b36SCunyin Chang return; 8340f805b36SCunyin Chang } 8350f805b36SCunyin Chang 8360f805b36SCunyin Chang if (read(fd, fw_image, size) != ((ssize_t)(size))) { 8370f805b36SCunyin Chang printf("Read firmware image failed\n"); 8380f805b36SCunyin Chang close(fd); 8398a44220bSJohn Meneghini spdk_dma_free(fw_image); 8400f805b36SCunyin Chang return; 8410f805b36SCunyin Chang } 8420f805b36SCunyin Chang close(fd); 8430f805b36SCunyin Chang 8440f805b36SCunyin Chang printf("Please Input Slot(0 - 7):\n"); 8450f805b36SCunyin Chang if (!scanf("%d", &slot)) { 8460f805b36SCunyin Chang printf("Invalid Slot\n"); 8478a44220bSJohn Meneghini spdk_dma_free(fw_image); 8480f805b36SCunyin Chang while (getchar() != '\n'); 8490f805b36SCunyin Chang return; 8500f805b36SCunyin Chang } 8510f805b36SCunyin Chang 8526fb1ce42SIsaac Otsiabah commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG; 8536fb1ce42SIsaac Otsiabah rc = spdk_nvme_ctrlr_update_firmware(ctrlr->ctrlr, fw_image, size, slot, commit_action, &status); 8546fb1ce42SIsaac Otsiabah if (rc == -ENXIO && status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC && 8556fb1ce42SIsaac Otsiabah status.sc == SPDK_NVME_SC_FIRMWARE_REQ_CONVENTIONAL_RESET) { 8566fb1ce42SIsaac Otsiabah printf("conventional reset is needed to enable firmware !\n"); 8576fb1ce42SIsaac Otsiabah } else if (rc) { 8580f805b36SCunyin Chang printf("spdk_nvme_ctrlr_update_firmware failed\n"); 8590f805b36SCunyin Chang } else { 8600f805b36SCunyin Chang printf("spdk_nvme_ctrlr_update_firmware success\n"); 8610f805b36SCunyin Chang } 8628a44220bSJohn Meneghini spdk_dma_free(fw_image); 8630f805b36SCunyin Chang } 8640f805b36SCunyin Chang 8657250ec64SChunyang Hui static void 86601ddd112SChangpeng Liu opal_dump_info(struct spdk_opal_d0_features_info *feat) 86755f5b205SHui, Chunyang { 86801ddd112SChangpeng Liu if (feat->tper.hdr.code) { 86955f5b205SHui, Chunyang printf("\nOpal TPer feature:\n"); 87001ddd112SChangpeng Liu printf("ACKNACK = %s", (feat->tper.acknack ? "Y, " : "N, ")); 87101ddd112SChangpeng Liu printf("ASYNC = %s", (feat->tper.async ? "Y, " : "N, ")); 87201ddd112SChangpeng Liu printf("BufferManagement = %s\n", (feat->tper.buffer_management ? "Y, " : "N, ")); 87301ddd112SChangpeng Liu printf("ComIDManagement = %s", (feat->tper.comid_management ? "Y, " : "N, ")); 87401ddd112SChangpeng Liu printf("Streaming = %s", (feat->tper.streaming ? "Y, " : "N, ")); 87501ddd112SChangpeng Liu printf("Sync = %s\n", (feat->tper.sync ? "Y" : "N")); 87655f5b205SHui, Chunyang printf("\n"); 87755f5b205SHui, Chunyang } 87855f5b205SHui, Chunyang 87901ddd112SChangpeng Liu if (feat->locking.hdr.code) { 88055f5b205SHui, Chunyang printf("Opal Locking feature:\n"); 88101ddd112SChangpeng Liu printf("Locked = %s", (feat->locking.locked ? "Y, " : "N, ")); 88201ddd112SChangpeng Liu printf("Locking Enabled = %s", (feat->locking.locking_enabled ? "Y, " : "N, ")); 88301ddd112SChangpeng Liu printf("Locking supported = %s\n", (feat->locking.locking_supported ? "Y" : "N")); 88455f5b205SHui, Chunyang 88501ddd112SChangpeng Liu printf("MBR done = %s", (feat->locking.mbr_done ? "Y, " : "N, ")); 88601ddd112SChangpeng Liu printf("MBR enabled = %s", (feat->locking.mbr_enabled ? "Y, " : "N, ")); 88701ddd112SChangpeng Liu printf("Media encrypt = %s\n", (feat->locking.media_encryption ? "Y" : "N")); 88855f5b205SHui, Chunyang printf("\n"); 88955f5b205SHui, Chunyang } 89055f5b205SHui, Chunyang 89101ddd112SChangpeng Liu if (feat->geo.hdr.code) { 89255f5b205SHui, Chunyang printf("Opal Geometry feature:\n"); 89301ddd112SChangpeng Liu printf("Align = %s", (feat->geo.alignment_granularity ? "Y, " : "N, ")); 89401ddd112SChangpeng Liu printf("Logical block size = %d, ", from_be32(&feat->geo.logical_block_size)); 895bb19c18fSNick Connolly printf("Lowest aligned LBA = %" PRIu64 "\n", from_be64(&feat->geo.lowest_aligned_lba)); 89655f5b205SHui, Chunyang printf("\n"); 89755f5b205SHui, Chunyang } 89855f5b205SHui, Chunyang 89901ddd112SChangpeng Liu if (feat->single_user.hdr.code) { 90055f5b205SHui, Chunyang printf("Opal Single User Mode feature:\n"); 90101ddd112SChangpeng Liu printf("Any in SUM = %s", (feat->single_user.any ? "Y, " : "N, ")); 90201ddd112SChangpeng Liu printf("All in SUM = %s", (feat->single_user.all ? "Y, " : "N, ")); 90301ddd112SChangpeng Liu printf("Policy: %s Authority,\n", (feat->single_user.policy ? "Admin" : "Users")); 90401ddd112SChangpeng Liu printf("Number of locking objects = %d\n ", from_be32(&feat->single_user.num_locking_objects)); 90555f5b205SHui, Chunyang printf("\n"); 90655f5b205SHui, Chunyang } 90755f5b205SHui, Chunyang 90801ddd112SChangpeng Liu if (feat->datastore.hdr.code) { 90955f5b205SHui, Chunyang printf("Opal DataStore feature:\n"); 91001ddd112SChangpeng Liu printf("Table alignment = %d, ", from_be32(&feat->datastore.alignment)); 91101ddd112SChangpeng Liu printf("Max number of tables = %d, ", from_be16(&feat->datastore.max_tables)); 91201ddd112SChangpeng Liu printf("Max size of tables = %d\n", from_be32(&feat->datastore.max_table_size)); 91355f5b205SHui, Chunyang printf("\n"); 91455f5b205SHui, Chunyang } 91555f5b205SHui, Chunyang 91601ddd112SChangpeng Liu if (feat->v100.hdr.code) { 91755f5b205SHui, Chunyang printf("Opal V100 feature:\n"); 91801ddd112SChangpeng Liu printf("Base comID = %d, ", from_be16(&feat->v100.base_comid)); 91901ddd112SChangpeng Liu printf("Number of comIDs = %d, ", from_be16(&feat->v100.number_comids)); 92001ddd112SChangpeng Liu printf("Range crossing = %s\n", (feat->v100.range_crossing ? "N" : "Y")); 92155f5b205SHui, Chunyang printf("\n"); 92255f5b205SHui, Chunyang } 92355f5b205SHui, Chunyang 92401ddd112SChangpeng Liu if (feat->v200.hdr.code) { 92555f5b205SHui, Chunyang printf("Opal V200 feature:\n"); 92601ddd112SChangpeng Liu printf("Base comID = %d, ", from_be16(&feat->v200.base_comid)); 92701ddd112SChangpeng Liu printf("Number of comIDs = %d, ", from_be16(&feat->v200.num_comids)); 92801ddd112SChangpeng Liu printf("Initial PIN = %d,\n", feat->v200.initial_pin); 92901ddd112SChangpeng Liu printf("Reverted PIN = %d, ", feat->v200.reverted_pin); 93001ddd112SChangpeng Liu printf("Number of admins = %d, ", from_be16(&feat->v200.num_locking_admin_auth)); 93101ddd112SChangpeng Liu printf("Number of users = %d\n", from_be16(&feat->v200.num_locking_user_auth)); 932defe09d3SChunyang Hui printf("\n"); 93355f5b205SHui, Chunyang } 93455f5b205SHui, Chunyang } 93555f5b205SHui, Chunyang 93655f5b205SHui, Chunyang static void 9377250ec64SChunyang Hui opal_usage(void) 93855f5b205SHui, Chunyang { 9397250ec64SChunyang Hui printf("Opal General Usage:\n"); 9407250ec64SChunyang Hui printf("\n"); 9417250ec64SChunyang Hui printf("\t[1: scan device]\n"); 942755b4390SChunyang Hui printf("\t[2: init - take ownership and activate locking]\n"); 9430fae4f64SChunyang Hui printf("\t[3: revert tper]\n"); 9440fae4f64SChunyang Hui printf("\t[4: setup locking range]\n"); 9450fae4f64SChunyang Hui printf("\t[5: list locking ranges]\n"); 9460fae4f64SChunyang Hui printf("\t[6: enable user]\n"); 9470fae4f64SChunyang Hui printf("\t[7: set new password]\n"); 9480fae4f64SChunyang Hui printf("\t[8: add user to locking range]\n"); 9490fae4f64SChunyang Hui printf("\t[9: lock/unlock range]\n"); 9500fae4f64SChunyang Hui printf("\t[10: erase locking range]\n"); 9517250ec64SChunyang Hui printf("\t[0: quit]\n"); 9527250ec64SChunyang Hui } 95355f5b205SHui, Chunyang 9547250ec64SChunyang Hui static void 9557250ec64SChunyang Hui opal_scan(struct dev *iter) 9567250ec64SChunyang Hui { 957defe09d3SChunyang Hui while (getchar() != '\n'); 95855f5b205SHui, Chunyang if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 959c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 96055f5b205SHui, Chunyang if (iter->opal_dev == NULL) { 96155f5b205SHui, Chunyang return; 96255f5b205SHui, Chunyang } 9637250ec64SChunyang Hui 96455f5b205SHui, Chunyang printf("\n\nOpal Supported:\n"); 96555f5b205SHui, Chunyang display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC); 96601ddd112SChangpeng Liu opal_dump_info(spdk_opal_get_d0_features_info(iter->opal_dev)); 967c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 96855f5b205SHui, Chunyang } else { 96955f5b205SHui, Chunyang printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n", 97055f5b205SHui, Chunyang iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 97155f5b205SHui, Chunyang printf("%04x:%02x:%02x.%02x: Opal Not Supported\n\n\n", 97255f5b205SHui, Chunyang iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 97355f5b205SHui, Chunyang } 97455f5b205SHui, Chunyang } 9757250ec64SChunyang Hui 9767250ec64SChunyang Hui static void 977755b4390SChunyang Hui opal_init(struct dev *iter) 9787250ec64SChunyang Hui { 9790cd8b292SChangpeng Liu char new_passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 9807250ec64SChunyang Hui char *passwd_p; 9817250ec64SChunyang Hui int ret; 9827250ec64SChunyang Hui int ch; 9837250ec64SChunyang Hui 9847250ec64SChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 985c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 9867250ec64SChunyang Hui if (iter->opal_dev == NULL) { 9877250ec64SChunyang Hui return; 9887250ec64SChunyang Hui } 989defe09d3SChunyang Hui printf("Please input the new password for ownership:"); 9907250ec64SChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 9910cd8b292SChangpeng Liu passwd_p = get_line(new_passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 992defe09d3SChunyang Hui printf("\n...\n"); 9937250ec64SChunyang Hui if (passwd_p) { 9949f988238SChunyang Hui ret = spdk_opal_cmd_take_ownership(iter->opal_dev, passwd_p); 9957250ec64SChunyang Hui if (ret) { 9967250ec64SChunyang Hui printf("Take ownership failure: %d\n", ret); 997c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 9987250ec64SChunyang Hui return; 9997250ec64SChunyang Hui } 1000755b4390SChunyang Hui 1001755b4390SChunyang Hui ret = spdk_opal_cmd_activate_locking_sp(iter->opal_dev, passwd_p); 1002755b4390SChunyang Hui if (ret) { 1003755b4390SChunyang Hui printf("Locking SP activate failure: %d\n", ret); 1004c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 1005755b4390SChunyang Hui return; 1006755b4390SChunyang Hui } 1007defe09d3SChunyang Hui printf("...\nOpal Init Success\n"); 10087250ec64SChunyang Hui } else { 1009755b4390SChunyang Hui printf("Input password invalid. Opal Init failure\n"); 10107250ec64SChunyang Hui } 1011c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 10127250ec64SChunyang Hui } else { 10136b48e743SChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 10147250ec64SChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 10156b48e743SChunyang Hui } 10166b48e743SChunyang Hui } 10176b48e743SChunyang Hui 10186b48e743SChunyang Hui static void 1019505dbf59SChunyang Hui opal_locking_usage(void) 1020505dbf59SChunyang Hui { 1021505dbf59SChunyang Hui printf("Choose Opal locking state:\n"); 1022505dbf59SChunyang Hui printf("\n"); 1023505dbf59SChunyang Hui printf("\t[1: read write lock]\n"); 1024505dbf59SChunyang Hui printf("\t[2: read only]\n"); 1025505dbf59SChunyang Hui printf("\t[3: read write unlock]\n"); 1026505dbf59SChunyang Hui } 1027505dbf59SChunyang Hui 1028505dbf59SChunyang Hui static void 1029fbd2f3fdSChunyang Hui opal_setup_lockingrange(struct dev *iter) 1030505dbf59SChunyang Hui { 10310cd8b292SChangpeng Liu char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 1032505dbf59SChunyang Hui char *passwd_p; 1033505dbf59SChunyang Hui int ret; 1034505dbf59SChunyang Hui int ch; 1035fbd2f3fdSChunyang Hui uint64_t range_start; 1036fbd2f3fdSChunyang Hui uint64_t range_length; 10378522624dSChunyang Hui int locking_range_id; 1038fbd2f3fdSChunyang Hui struct spdk_opal_locking_range_info *info; 1039505dbf59SChunyang Hui 1040505dbf59SChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1041c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 1042505dbf59SChunyang Hui if (iter->opal_dev == NULL) { 1043505dbf59SChunyang Hui return; 1044505dbf59SChunyang Hui } 1045defe09d3SChunyang Hui printf("Please input the password for setting up locking range:"); 1046505dbf59SChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 10470cd8b292SChangpeng Liu passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1048defe09d3SChunyang Hui printf("\n"); 1049505dbf59SChunyang Hui if (passwd_p) { 1050fbd2f3fdSChunyang Hui printf("Specify locking range id:\n"); 10518522624dSChunyang Hui if (!scanf("%d", &locking_range_id)) { 1052fbd2f3fdSChunyang Hui printf("Invalid locking range id\n"); 1053c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 105407f43264SChunyang Hui return; 1055fbd2f3fdSChunyang Hui } 1056fbd2f3fdSChunyang Hui 1057fbd2f3fdSChunyang Hui printf("range length:\n"); 1058a2664e74STomasz Zawadzki if (!scanf("%" SCNu64, &range_length)) { 1059fbd2f3fdSChunyang Hui printf("Invalid range length\n"); 1060c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 106107f43264SChunyang Hui return; 1062fbd2f3fdSChunyang Hui } 1063fbd2f3fdSChunyang Hui 1064fbd2f3fdSChunyang Hui printf("range start:\n"); 1065a2664e74STomasz Zawadzki if (!scanf("%" SCNu64, &range_start)) { 1066fbd2f3fdSChunyang Hui printf("Invalid range start address\n"); 1067c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 106807f43264SChunyang Hui return; 1069505dbf59SChunyang Hui } 1070defe09d3SChunyang Hui while (getchar() != '\n'); 1071505dbf59SChunyang Hui 1072fbd2f3fdSChunyang Hui ret = spdk_opal_cmd_setup_locking_range(iter->opal_dev, 10738522624dSChunyang Hui OPAL_ADMIN1, locking_range_id, range_start, range_length, passwd_p); 1074505dbf59SChunyang Hui if (ret) { 1075fbd2f3fdSChunyang Hui printf("Setup locking range failure: %d\n", ret); 1076c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 1077505dbf59SChunyang Hui return; 1078505dbf59SChunyang Hui } 1079505dbf59SChunyang Hui 1080fbd2f3fdSChunyang Hui ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev, 10818522624dSChunyang Hui passwd_p, OPAL_ADMIN1, locking_range_id); 1082fbd2f3fdSChunyang Hui if (ret) { 1083fbd2f3fdSChunyang Hui printf("Get locking range info failure: %d\n", ret); 1084c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 1085fbd2f3fdSChunyang Hui return; 1086fbd2f3fdSChunyang Hui } 10878522624dSChunyang Hui info = spdk_opal_get_locking_range_info(iter->opal_dev, locking_range_id); 1088fbd2f3fdSChunyang Hui 1089defe09d3SChunyang Hui printf("\nlocking range ID: %d\n", info->locking_range_id); 1090bb19c18fSNick Connolly printf("range start: %" PRIu64 "\n", info->range_start); 1091bb19c18fSNick Connolly printf("range length: %" PRIu64 "\n", info->range_length); 1092fbd2f3fdSChunyang Hui printf("read lock enabled: %d\n", info->read_lock_enabled); 1093fbd2f3fdSChunyang Hui printf("write lock enabled: %d\n", info->write_lock_enabled); 1094fbd2f3fdSChunyang Hui printf("read locked: %d\n", info->read_locked); 1095fbd2f3fdSChunyang Hui printf("write locked: %d\n", info->write_locked); 1096fbd2f3fdSChunyang Hui 1097505dbf59SChunyang Hui printf("...\n...\nOpal setup locking range success\n"); 1098505dbf59SChunyang Hui } else { 1099505dbf59SChunyang Hui printf("Input password invalid. Opal setup locking range failure\n"); 1100505dbf59SChunyang Hui } 1101c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 1102505dbf59SChunyang Hui } else { 1103505dbf59SChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 1104505dbf59SChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 1105505dbf59SChunyang Hui } 1106505dbf59SChunyang Hui } 1107505dbf59SChunyang Hui 1108505dbf59SChunyang Hui static void 1109fbd2f3fdSChunyang Hui opal_list_locking_ranges(struct dev *iter) 1110fbd2f3fdSChunyang Hui { 11110cd8b292SChangpeng Liu char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 1112fbd2f3fdSChunyang Hui char *passwd_p; 1113fbd2f3fdSChunyang Hui int ret; 1114fbd2f3fdSChunyang Hui int ch; 1115fbd2f3fdSChunyang Hui int max_ranges; 1116fbd2f3fdSChunyang Hui int i; 1117fbd2f3fdSChunyang Hui struct spdk_opal_locking_range_info *info; 1118fbd2f3fdSChunyang Hui 1119fbd2f3fdSChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1120c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 1121fbd2f3fdSChunyang Hui if (iter->opal_dev == NULL) { 1122fbd2f3fdSChunyang Hui return; 1123fbd2f3fdSChunyang Hui } 1124defe09d3SChunyang Hui printf("Please input password:"); 1125fbd2f3fdSChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 11260cd8b292SChangpeng Liu passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1127defe09d3SChunyang Hui printf("\n"); 1128fbd2f3fdSChunyang Hui if (passwd_p) { 1129fbd2f3fdSChunyang Hui ret = spdk_opal_cmd_get_max_ranges(iter->opal_dev, passwd_p); 1130a3363de3SChangpeng Liu if (ret <= 0) { 1131fbd2f3fdSChunyang Hui printf("get max ranges failure: %d\n", ret); 1132c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 1133fbd2f3fdSChunyang Hui return; 1134fbd2f3fdSChunyang Hui } 1135fbd2f3fdSChunyang Hui 1136a3363de3SChangpeng Liu max_ranges = ret; 1137fbd2f3fdSChunyang Hui for (i = 0; i < max_ranges; i++) { 1138fbd2f3fdSChunyang Hui ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev, 11398522624dSChunyang Hui passwd_p, OPAL_ADMIN1, i); 1140fbd2f3fdSChunyang Hui if (ret) { 1141fbd2f3fdSChunyang Hui printf("Get locking range info failure: %d\n", ret); 1142c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 1143fbd2f3fdSChunyang Hui return; 1144fbd2f3fdSChunyang Hui } 1145fbd2f3fdSChunyang Hui info = spdk_opal_get_locking_range_info(iter->opal_dev, i); 1146fbd2f3fdSChunyang Hui if (info == NULL) { 1147fbd2f3fdSChunyang Hui continue; 1148fbd2f3fdSChunyang Hui } 1149fbd2f3fdSChunyang Hui 1150fbd2f3fdSChunyang Hui printf("===============================================\n"); 1151fbd2f3fdSChunyang Hui printf("locking range ID: %d\t", info->locking_range_id); 1152fbd2f3fdSChunyang Hui if (i == 0) { printf("(Global Range)"); } 1153fbd2f3fdSChunyang Hui printf("\n===============================================\n"); 1154bb19c18fSNick Connolly printf("range start: %" PRIu64 "\t", info->range_start); 1155bb19c18fSNick Connolly printf("range length: %" PRIu64 "\n", info->range_length); 1156fbd2f3fdSChunyang Hui printf("read lock enabled: %d\t", info->read_lock_enabled); 1157fbd2f3fdSChunyang Hui printf("write lock enabled: %d\t", info->write_lock_enabled); 1158fbd2f3fdSChunyang Hui printf("read locked: %d\t", info->read_locked); 1159fbd2f3fdSChunyang Hui printf("write locked: %d\n", info->write_locked); 1160fbd2f3fdSChunyang Hui printf("\n"); 1161fbd2f3fdSChunyang Hui } 1162fbd2f3fdSChunyang Hui } else { 1163fbd2f3fdSChunyang Hui printf("Input password invalid. List locking ranges failure\n"); 1164fbd2f3fdSChunyang Hui } 1165c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 1166fbd2f3fdSChunyang Hui } else { 1167fbd2f3fdSChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 1168fbd2f3fdSChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 1169fbd2f3fdSChunyang Hui } 1170fbd2f3fdSChunyang Hui } 1171fbd2f3fdSChunyang Hui 1172fbd2f3fdSChunyang Hui static void 11738522624dSChunyang Hui opal_new_user_enable(struct dev *iter) 11748522624dSChunyang Hui { 11758522624dSChunyang Hui int user_id; 11760cd8b292SChangpeng Liu char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 11778522624dSChunyang Hui char *passwd_p; 11780cd8b292SChangpeng Liu char user_pw[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 11798522624dSChunyang Hui char *user_pw_p; 11808522624dSChunyang Hui int ret; 11818522624dSChunyang Hui int ch; 11828522624dSChunyang Hui 11838522624dSChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1184c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 11858522624dSChunyang Hui if (iter->opal_dev == NULL) { 11868522624dSChunyang Hui return; 11878522624dSChunyang Hui } 1188defe09d3SChunyang Hui printf("Please input admin password:"); 11898522624dSChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 11900cd8b292SChangpeng Liu passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1191defe09d3SChunyang Hui printf("\n"); 11928522624dSChunyang Hui if (passwd_p) { 11938522624dSChunyang Hui printf("which user to enable: "); 11948522624dSChunyang Hui if (!scanf("%d", &user_id)) { 11958522624dSChunyang Hui printf("Invalid user id\n"); 1196c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 11978522624dSChunyang Hui return; 11988522624dSChunyang Hui } 11998522624dSChunyang Hui 12008522624dSChunyang Hui ret = spdk_opal_cmd_enable_user(iter->opal_dev, user_id, passwd_p); 12018522624dSChunyang Hui if (ret) { 12028522624dSChunyang Hui printf("Enable user failure error code: %d\n", ret); 1203c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12048522624dSChunyang Hui return; 12058522624dSChunyang Hui } 1206defe09d3SChunyang Hui printf("Please set a new password for this user:"); 12078522624dSChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 12080cd8b292SChangpeng Liu user_pw_p = get_line(user_pw, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 12098522624dSChunyang Hui if (user_pw_p == NULL) { 12108522624dSChunyang Hui printf("Input password invalid. Enable user failure\n"); 1211c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12128522624dSChunyang Hui return; 12138522624dSChunyang Hui } 12148522624dSChunyang Hui 12158522624dSChunyang Hui ret = spdk_opal_cmd_set_new_passwd(iter->opal_dev, user_id, user_pw_p, passwd_p, true); 12168522624dSChunyang Hui if (ret) { 12178522624dSChunyang Hui printf("Set new password failure error code: %d\n", ret); 1218c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12198522624dSChunyang Hui return; 12208522624dSChunyang Hui } 12218522624dSChunyang Hui 1222defe09d3SChunyang Hui printf("\n...\n...\nEnable User Success\n"); 12238522624dSChunyang Hui } else { 12248522624dSChunyang Hui printf("Input password invalid. Enable user failure\n"); 12258522624dSChunyang Hui } 1226c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12278522624dSChunyang Hui } else { 12288522624dSChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 12298522624dSChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 12308522624dSChunyang Hui } 12318522624dSChunyang Hui } 12328522624dSChunyang Hui 12338522624dSChunyang Hui static void 12348522624dSChunyang Hui opal_change_password(struct dev *iter) 12358522624dSChunyang Hui { 12368522624dSChunyang Hui int user_id; 12370cd8b292SChangpeng Liu char old_passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 12388522624dSChunyang Hui char *old_passwd_p; 12390cd8b292SChangpeng Liu char new_passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 12408522624dSChunyang Hui char *new_passwd_p; 12418522624dSChunyang Hui int ret; 12428522624dSChunyang Hui int ch; 12438522624dSChunyang Hui 12448522624dSChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1245c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 12468522624dSChunyang Hui if (iter->opal_dev == NULL) { 12478522624dSChunyang Hui return; 12488522624dSChunyang Hui } 12498522624dSChunyang Hui printf("user id: "); 12508522624dSChunyang Hui if (!scanf("%d", &user_id)) { 12518522624dSChunyang Hui printf("Invalid user id\n"); 1252c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12538522624dSChunyang Hui return; 12548522624dSChunyang Hui } 1255defe09d3SChunyang Hui printf("Password:"); 12568522624dSChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 12570cd8b292SChangpeng Liu old_passwd_p = get_line(old_passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1258defe09d3SChunyang Hui printf("\n"); 12598522624dSChunyang Hui if (old_passwd_p) { 12608522624dSChunyang Hui printf("Please input new password:\n"); 12610cd8b292SChangpeng Liu new_passwd_p = get_line(new_passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1262defe09d3SChunyang Hui printf("\n"); 12638522624dSChunyang Hui if (new_passwd_p == NULL) { 12648522624dSChunyang Hui printf("Input password invalid. Change password failure\n"); 1265c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12668522624dSChunyang Hui return; 12678522624dSChunyang Hui } 12688522624dSChunyang Hui 12698522624dSChunyang Hui ret = spdk_opal_cmd_set_new_passwd(iter->opal_dev, user_id, new_passwd_p, old_passwd_p, false); 12708522624dSChunyang Hui if (ret) { 12718522624dSChunyang Hui printf("Set new password failure error code: %d\n", ret); 1272c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12738522624dSChunyang Hui return; 12748522624dSChunyang Hui } 12758522624dSChunyang Hui 12768522624dSChunyang Hui printf("...\n...\nChange password Success\n"); 12778522624dSChunyang Hui } else { 12788522624dSChunyang Hui printf("Input password invalid. Change password failure\n"); 12798522624dSChunyang Hui } 1280c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 12818522624dSChunyang Hui } else { 12828522624dSChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 12838522624dSChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 12848522624dSChunyang Hui } 12858522624dSChunyang Hui } 12868522624dSChunyang Hui 12878522624dSChunyang Hui static void 12888522624dSChunyang Hui opal_add_user_to_locking_range(struct dev *iter) 12898522624dSChunyang Hui { 12908522624dSChunyang Hui int locking_range_id, user_id; 12910cd8b292SChangpeng Liu char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 12928522624dSChunyang Hui char *passwd_p; 12938522624dSChunyang Hui int ret; 12948522624dSChunyang Hui int ch; 12958522624dSChunyang Hui 12968522624dSChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1297c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 12988522624dSChunyang Hui if (iter->opal_dev == NULL) { 12998522624dSChunyang Hui return; 13008522624dSChunyang Hui } 1301defe09d3SChunyang Hui printf("Please input admin password:"); 13028522624dSChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 13030cd8b292SChangpeng Liu passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1304defe09d3SChunyang Hui printf("\n"); 13058522624dSChunyang Hui if (passwd_p) { 13068522624dSChunyang Hui printf("Specify locking range id:\n"); 13078522624dSChunyang Hui if (!scanf("%d", &locking_range_id)) { 13088522624dSChunyang Hui printf("Invalid locking range id\n"); 1309c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 13108522624dSChunyang Hui return; 13118522624dSChunyang Hui } 13128522624dSChunyang Hui 13138522624dSChunyang Hui printf("which user to enable:\n"); 13148522624dSChunyang Hui if (!scanf("%d", &user_id)) { 13158522624dSChunyang Hui printf("Invalid user id\n"); 1316c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 13178522624dSChunyang Hui return; 13188522624dSChunyang Hui } 1319defe09d3SChunyang Hui while (getchar() != '\n'); 13208522624dSChunyang Hui 13218522624dSChunyang Hui ret = spdk_opal_cmd_add_user_to_locking_range(iter->opal_dev, user_id, locking_range_id, 1322b2947f52SChangpeng Liu OPAL_READONLY, passwd_p); 13238522624dSChunyang Hui ret += spdk_opal_cmd_add_user_to_locking_range(iter->opal_dev, user_id, locking_range_id, 1324b2947f52SChangpeng Liu OPAL_READWRITE, passwd_p); 13258522624dSChunyang Hui if (ret) { 13268522624dSChunyang Hui printf("Add user to locking range error: %d\n", ret); 1327c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 13288522624dSChunyang Hui return; 13298522624dSChunyang Hui } 13308522624dSChunyang Hui 13318522624dSChunyang Hui printf("...\n...\nAdd user to locking range Success\n"); 13328522624dSChunyang Hui } else { 13338522624dSChunyang Hui printf("Input password invalid. Add user to locking range failure\n"); 13348522624dSChunyang Hui } 1335c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 13368522624dSChunyang Hui } else { 13378522624dSChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 13388522624dSChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 13398522624dSChunyang Hui } 13408522624dSChunyang Hui } 13418522624dSChunyang Hui 13428522624dSChunyang Hui static void 13438522624dSChunyang Hui opal_user_lock_unlock_range(struct dev *iter) 13448522624dSChunyang Hui { 13450cd8b292SChangpeng Liu char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 13468522624dSChunyang Hui char *passwd_p; 13478522624dSChunyang Hui int ch; 13488522624dSChunyang Hui int ret; 13498522624dSChunyang Hui int user_id; 13508522624dSChunyang Hui int locking_range_id; 13518522624dSChunyang Hui int state; 13528522624dSChunyang Hui enum spdk_opal_lock_state state_flag; 13538522624dSChunyang Hui 13548522624dSChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1355c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 13568522624dSChunyang Hui if (iter->opal_dev == NULL) { 13578522624dSChunyang Hui return; 13588522624dSChunyang Hui } 13598522624dSChunyang Hui printf("User id: "); 13608522624dSChunyang Hui if (!scanf("%d", &user_id)) { 13618522624dSChunyang Hui printf("Invalid user id\n"); 1362c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 13638522624dSChunyang Hui return; 13648522624dSChunyang Hui } 13658522624dSChunyang Hui 1366defe09d3SChunyang Hui printf("Please input password:"); 13678522624dSChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 13680cd8b292SChangpeng Liu passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1369defe09d3SChunyang Hui printf("\n"); 13708522624dSChunyang Hui if (passwd_p) { 13718522624dSChunyang Hui printf("Specify locking range id:\n"); 13728522624dSChunyang Hui if (!scanf("%d", &locking_range_id)) { 13738522624dSChunyang Hui printf("Invalid locking range id\n"); 1374c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 13758522624dSChunyang Hui return; 13768522624dSChunyang Hui } 13778522624dSChunyang Hui 13788522624dSChunyang Hui opal_locking_usage(); 13798522624dSChunyang Hui if (!scanf("%d", &state)) { 13808522624dSChunyang Hui printf("Invalid option\n"); 13818522624dSChunyang Hui } 13828522624dSChunyang Hui switch (state) { 13838522624dSChunyang Hui case 1: 13848522624dSChunyang Hui state_flag = OPAL_RWLOCK; 13858522624dSChunyang Hui break; 13868522624dSChunyang Hui case 2: 13878522624dSChunyang Hui state_flag = OPAL_READONLY; 13888522624dSChunyang Hui break; 13898522624dSChunyang Hui case 3: 13908522624dSChunyang Hui state_flag = OPAL_READWRITE; 13918522624dSChunyang Hui break; 13928522624dSChunyang Hui default: 13938522624dSChunyang Hui printf("Invalid options\n"); 1394c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 13958522624dSChunyang Hui return; 13968522624dSChunyang Hui } 1397defe09d3SChunyang Hui while (getchar() != '\n'); 13988522624dSChunyang Hui 13998522624dSChunyang Hui ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, user_id, state_flag, 14008522624dSChunyang Hui locking_range_id, passwd_p); 14018522624dSChunyang Hui if (ret) { 14028522624dSChunyang Hui printf("lock/unlock range failure: %d\n", ret); 1403c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 14048522624dSChunyang Hui return; 14058522624dSChunyang Hui } 14068522624dSChunyang Hui printf("...\n...\nLock/unlock range Success\n"); 14078522624dSChunyang Hui } else { 14088522624dSChunyang Hui printf("Input password invalid. lock/unlock range failure\n"); 14098522624dSChunyang Hui } 1410c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 14118522624dSChunyang Hui } else { 14128522624dSChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 14138522624dSChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 14148522624dSChunyang Hui } 14158522624dSChunyang Hui } 14168522624dSChunyang Hui 14178522624dSChunyang Hui static void 14186b48e743SChunyang Hui opal_revert_tper(struct dev *iter) 14196b48e743SChunyang Hui { 14200cd8b292SChangpeng Liu char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 14216b48e743SChunyang Hui char *passwd_p; 14226b48e743SChunyang Hui int ret; 14236b48e743SChunyang Hui int ch; 14246b48e743SChunyang Hui 14256b48e743SChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1426c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 14276b48e743SChunyang Hui if (iter->opal_dev == NULL) { 14286b48e743SChunyang Hui return; 14296b48e743SChunyang Hui } 14306b48e743SChunyang Hui printf("Please be noted this operation will erase ALL DATA on this drive\n"); 1431b7876f9aSJosh Soref printf("Please don't terminate this execution. Otherwise undefined error may occur\n"); 1432defe09d3SChunyang Hui printf("Please input password for revert TPer:"); 14336b48e743SChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 14340cd8b292SChangpeng Liu passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 1435defe09d3SChunyang Hui printf("\n...\n"); 14366b48e743SChunyang Hui if (passwd_p) { 14379f988238SChunyang Hui ret = spdk_opal_cmd_revert_tper(iter->opal_dev, passwd_p); 14386b48e743SChunyang Hui if (ret) { 14396b48e743SChunyang Hui printf("Revert TPer failure: %d\n", ret); 1440c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 14416b48e743SChunyang Hui return; 14426b48e743SChunyang Hui } 1443defe09d3SChunyang Hui printf("...\nRevert TPer Success\n"); 14446b48e743SChunyang Hui } else { 14456b48e743SChunyang Hui printf("Input password invalid. Revert TPer failure\n"); 14466b48e743SChunyang Hui } 1447c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 14486b48e743SChunyang Hui } else { 14496b48e743SChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 14507250ec64SChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 14517250ec64SChunyang Hui } 14527250ec64SChunyang Hui } 14537250ec64SChunyang Hui 14547250ec64SChunyang Hui static void 14550fae4f64SChunyang Hui opal_erase_locking_range(struct dev *iter) 14560fae4f64SChunyang Hui { 14570cd8b292SChangpeng Liu char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0}; 14580fae4f64SChunyang Hui char *passwd_p; 14590fae4f64SChunyang Hui int ret; 14600fae4f64SChunyang Hui int ch; 14610fae4f64SChunyang Hui int locking_range_id; 14620fae4f64SChunyang Hui 14630fae4f64SChunyang Hui if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { 1464c61b70c3SChangpeng Liu iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr); 14650fae4f64SChunyang Hui if (iter->opal_dev == NULL) { 14660fae4f64SChunyang Hui return; 14670fae4f64SChunyang Hui } 14680fae4f64SChunyang Hui printf("Please be noted this operation will erase ALL DATA on this range\n"); 14690fae4f64SChunyang Hui printf("Please input password for erase locking range:"); 14700fae4f64SChunyang Hui while ((ch = getchar()) != '\n' && ch != EOF); 14710cd8b292SChangpeng Liu passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true); 14720fae4f64SChunyang Hui if (passwd_p) { 14730fae4f64SChunyang Hui printf("\nSpecify locking range id:\n"); 14740fae4f64SChunyang Hui if (!scanf("%d", &locking_range_id)) { 14750fae4f64SChunyang Hui printf("Invalid locking range id\n"); 1476c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 14770fae4f64SChunyang Hui return; 14780fae4f64SChunyang Hui } 14790fae4f64SChunyang Hui printf("\n...\n"); 1480ebb01092SChangpeng Liu ret = spdk_opal_cmd_secure_erase_locking_range(iter->opal_dev, OPAL_ADMIN1, locking_range_id, 1481ebb01092SChangpeng Liu passwd_p); 14820fae4f64SChunyang Hui if (ret) { 14830fae4f64SChunyang Hui printf("Erase locking range failure: %d\n", ret); 1484c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 14850fae4f64SChunyang Hui return; 14860fae4f64SChunyang Hui } 14870fae4f64SChunyang Hui printf("...\nErase locking range Success\n"); 14880fae4f64SChunyang Hui } else { 14890fae4f64SChunyang Hui printf("Input password invalid. Erase locking range failure\n"); 14900fae4f64SChunyang Hui } 1491c61b70c3SChangpeng Liu spdk_opal_dev_destruct(iter->opal_dev); 14920fae4f64SChunyang Hui } else { 14930fae4f64SChunyang Hui printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", 14940fae4f64SChunyang Hui iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); 14950fae4f64SChunyang Hui } 14960fae4f64SChunyang Hui } 14970fae4f64SChunyang Hui 14980fae4f64SChunyang Hui static void 14997250ec64SChunyang Hui test_opal(void) 15007250ec64SChunyang Hui { 15017250ec64SChunyang Hui int exit_flag = false; 15027250ec64SChunyang Hui struct dev *ctrlr; 15037250ec64SChunyang Hui 15047250ec64SChunyang Hui ctrlr = get_controller(); 15057250ec64SChunyang Hui if (ctrlr == NULL) { 15067250ec64SChunyang Hui printf("Invalid controller PCI Address.\n"); 15077250ec64SChunyang Hui return; 15087250ec64SChunyang Hui } 15097250ec64SChunyang Hui 15107250ec64SChunyang Hui opal_usage(); 15117250ec64SChunyang Hui while (!exit_flag) { 15127250ec64SChunyang Hui int cmd; 15137250ec64SChunyang Hui if (!scanf("%d", &cmd)) { 1514505dbf59SChunyang Hui printf("Invalid Command: command must be number 0-9\n"); 15157250ec64SChunyang Hui while (getchar() != '\n'); 15167250ec64SChunyang Hui opal_usage(); 15177250ec64SChunyang Hui continue; 15187250ec64SChunyang Hui } 15197250ec64SChunyang Hui 15207250ec64SChunyang Hui switch (cmd) { 15217250ec64SChunyang Hui case 0: 15227250ec64SChunyang Hui exit_flag = true; 15237250ec64SChunyang Hui continue; 15247250ec64SChunyang Hui case 1: 15257250ec64SChunyang Hui opal_scan(ctrlr); 15267250ec64SChunyang Hui break; 15277250ec64SChunyang Hui case 2: 1528755b4390SChunyang Hui opal_init(ctrlr); /* Take ownership, Activate Locking SP */ 15297250ec64SChunyang Hui break; 15306b48e743SChunyang Hui case 3: 15310fae4f64SChunyang Hui opal_revert_tper(ctrlr); 1532fbd2f3fdSChunyang Hui break; 1533fbd2f3fdSChunyang Hui case 4: 15340fae4f64SChunyang Hui opal_setup_lockingrange(ctrlr); 1535505dbf59SChunyang Hui break; 15368522624dSChunyang Hui case 5: 15370fae4f64SChunyang Hui opal_list_locking_ranges(ctrlr); 15388522624dSChunyang Hui break; 15398522624dSChunyang Hui case 6: 15400fae4f64SChunyang Hui opal_new_user_enable(ctrlr); 15418522624dSChunyang Hui break; 15428522624dSChunyang Hui case 7: 15430fae4f64SChunyang Hui opal_change_password(ctrlr); 15448522624dSChunyang Hui break; 15458522624dSChunyang Hui case 8: 15460fae4f64SChunyang Hui opal_add_user_to_locking_range(ctrlr); 15478522624dSChunyang Hui break; 1548505dbf59SChunyang Hui case 9: 15490fae4f64SChunyang Hui opal_user_lock_unlock_range(ctrlr); 15500fae4f64SChunyang Hui break; 15510fae4f64SChunyang Hui case 10: 15520fae4f64SChunyang Hui opal_erase_locking_range(ctrlr); 15536b48e743SChunyang Hui break; 15547250ec64SChunyang Hui 15557250ec64SChunyang Hui default: 15567250ec64SChunyang Hui printf("Invalid option\n"); 15577250ec64SChunyang Hui } 15587250ec64SChunyang Hui 1559defe09d3SChunyang Hui printf("\npress Enter to display Opal cmd menu ...\n"); 15607250ec64SChunyang Hui while (getchar() != '\n'); 15617250ec64SChunyang Hui opal_usage(); 15627250ec64SChunyang Hui } 156355f5b205SHui, Chunyang } 156455f5b205SHui, Chunyang 1565f07ed6efSGangCao static void 1566f07ed6efSGangCao args_usage(const char *program_name) 1567f07ed6efSGangCao { 1568f07ed6efSGangCao printf("%s [options]", program_name); 1569f07ed6efSGangCao printf("\n"); 1570f07ed6efSGangCao printf("options:\n"); 1571f07ed6efSGangCao printf(" -i shared memory group ID\n"); 1572f07ed6efSGangCao } 1573f07ed6efSGangCao 1574f07ed6efSGangCao static int 1575f07ed6efSGangCao parse_args(int argc, char **argv) 1576f07ed6efSGangCao { 1577f07ed6efSGangCao int op; 1578f07ed6efSGangCao 1579f07ed6efSGangCao while ((op = getopt(argc, argv, "i:")) != -1) { 1580f07ed6efSGangCao switch (op) { 1581f07ed6efSGangCao case 'i': 15820f9dc2afSShuhei Matsumoto g_shm_id = spdk_strtol(optarg, 10); 15830f9dc2afSShuhei Matsumoto if (g_shm_id < 0) { 15840f9dc2afSShuhei Matsumoto fprintf(stderr, "Invalid shared memory ID\n"); 15850f9dc2afSShuhei Matsumoto return g_shm_id; 15860f9dc2afSShuhei Matsumoto } 1587f07ed6efSGangCao break; 1588f07ed6efSGangCao default: 1589f07ed6efSGangCao args_usage(argv[0]); 1590f07ed6efSGangCao return 1; 1591f07ed6efSGangCao } 1592f07ed6efSGangCao } 1593f07ed6efSGangCao 1594f07ed6efSGangCao return 0; 1595f07ed6efSGangCao } 1596f07ed6efSGangCao 15978dd1cd21SBen Walker int 15988dd1cd21SBen Walker main(int argc, char **argv) 159998416108SCunyin Chang { 160047d4ead9SShuhei Matsumoto int rc; 160118d26e42SBen Walker struct spdk_env_opts opts; 160247d4ead9SShuhei Matsumoto struct dev *dev; 16030a903c91SShuhei Matsumoto struct spdk_nvme_detach_ctx *detach_ctx = NULL; 160498416108SCunyin Chang 1605f07ed6efSGangCao rc = parse_args(argc, argv); 1606f07ed6efSGangCao if (rc != 0) { 1607f07ed6efSGangCao return rc; 1608f07ed6efSGangCao } 1609f07ed6efSGangCao 1610*57fd99b9SJim Harris opts.opts_size = sizeof(opts); 161118d26e42SBen Walker spdk_env_opts_init(&opts); 161218d26e42SBen Walker opts.name = "nvme_manage"; 161318d26e42SBen Walker opts.core_mask = "0x1"; 1614f07ed6efSGangCao opts.shm_id = g_shm_id; 1615095f4254SLance Hartmann if (spdk_env_init(&opts) < 0) { 1616095f4254SLance Hartmann fprintf(stderr, "Unable to initialize SPDK env\n"); 1617095f4254SLance Hartmann return 1; 1618095f4254SLance Hartmann } 161998416108SCunyin Chang 1620df46c41aSBen Walker if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) { 162198416108SCunyin Chang fprintf(stderr, "spdk_nvme_probe() failed\n"); 16229ec9c8b3SChangpeng Liu spdk_env_fini(); 162398416108SCunyin Chang return 1; 162498416108SCunyin Chang } 162598416108SCunyin Chang 16262e61a144SDaniel Verkamp qsort(devs, num_devs, sizeof(devs[0]), cmp_devs); 16272e61a144SDaniel Verkamp 162898416108SCunyin Chang usage(); 162998416108SCunyin Chang 163098416108SCunyin Chang while (1) { 163198416108SCunyin Chang int cmd; 163298416108SCunyin Chang bool exit_flag = false; 163398416108SCunyin Chang 163498416108SCunyin Chang if (!scanf("%d", &cmd)) { 16352716cd2aSlu fan printf("Invalid Command: command must be number 1-8\n"); 163698416108SCunyin Chang while (getchar() != '\n'); 16372716cd2aSlu fan usage(); 16382716cd2aSlu fan continue; 163998416108SCunyin Chang } 164098416108SCunyin Chang switch (cmd) { 164198416108SCunyin Chang case 1: 164298416108SCunyin Chang display_controller_list(); 164398416108SCunyin Chang break; 164498416108SCunyin Chang case 2: 164598416108SCunyin Chang add_ns(); 164698416108SCunyin Chang break; 164798416108SCunyin Chang case 3: 164898416108SCunyin Chang delete_ns(); 164998416108SCunyin Chang break; 165098416108SCunyin Chang case 4: 165198416108SCunyin Chang attach_and_detach_ns(SPDK_NVME_NS_CTRLR_ATTACH); 165298416108SCunyin Chang break; 165398416108SCunyin Chang case 5: 165498416108SCunyin Chang attach_and_detach_ns(SPDK_NVME_NS_CTRLR_DETACH); 165598416108SCunyin Chang break; 165698416108SCunyin Chang case 6: 1657eae68857SCunyin Chang format_nvm(); 1658eae68857SCunyin Chang break; 1659eae68857SCunyin Chang case 7: 16600f805b36SCunyin Chang update_firmware_image(); 16610f805b36SCunyin Chang break; 16620f805b36SCunyin Chang case 8: 166355f5b205SHui, Chunyang test_opal(); 166455f5b205SHui, Chunyang break; 166555f5b205SHui, Chunyang case 9: 166698416108SCunyin Chang exit_flag = true; 166798416108SCunyin Chang break; 166898416108SCunyin Chang default: 166998416108SCunyin Chang printf("Invalid Command\n"); 167098416108SCunyin Chang break; 167198416108SCunyin Chang } 167298416108SCunyin Chang 167359970a89SDaniel Verkamp if (exit_flag) { 167498416108SCunyin Chang break; 167559970a89SDaniel Verkamp } 167698416108SCunyin Chang 167798416108SCunyin Chang while (getchar() != '\n'); 167898416108SCunyin Chang printf("press Enter to display cmd menu ...\n"); 167998416108SCunyin Chang while (getchar() != '\n'); 168098416108SCunyin Chang usage(); 168198416108SCunyin Chang } 168298416108SCunyin Chang 168398416108SCunyin Chang printf("Cleaning up...\n"); 168498416108SCunyin Chang 168547d4ead9SShuhei Matsumoto foreach_dev(dev) { 16860a903c91SShuhei Matsumoto spdk_nvme_detach_async(dev->ctrlr, &detach_ctx); 16870a903c91SShuhei Matsumoto } 16880a903c91SShuhei Matsumoto 16894fe4040aSShuhei Matsumoto if (detach_ctx) { 16904fe4040aSShuhei Matsumoto spdk_nvme_detach_poll(detach_ctx); 169198416108SCunyin Chang } 169298416108SCunyin Chang 16939ec9c8b3SChangpeng Liu spdk_env_fini(); 16949ec9c8b3SChangpeng Liu 169518d26e42SBen Walker return 0; 169698416108SCunyin Chang } 1697