]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/examples/nvme/nvme_manage/nvme_manage.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / examples / nvme / nvme_manage / nvme_manage.c
CommitLineData
7c673cae
FG
1/*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
11fdf7f2 34#include "spdk/stdinc.h"
7c673cae
FG
35
36#include "spdk/nvme.h"
37#include "spdk/env.h"
9f95a23c 38#include "spdk/string.h"
7c673cae 39#include "spdk/util.h"
9f95a23c 40#include "spdk/opal.h"
7c673cae
FG
41
42#define MAX_DEVS 64
43
44struct dev {
45 struct spdk_pci_addr pci_addr;
11fdf7f2 46 struct spdk_nvme_ctrlr *ctrlr;
7c673cae
FG
47 const struct spdk_nvme_ctrlr_data *cdata;
48 struct spdk_nvme_ns_data *common_ns_data;
49 int outstanding_admin_cmds;
9f95a23c 50 struct spdk_opal_dev *opal_dev;
7c673cae
FG
51};
52
53static struct dev devs[MAX_DEVS];
54static int num_devs = 0;
11fdf7f2 55static int g_shm_id = -1;
7c673cae
FG
56
57#define foreach_dev(iter) \
58 for (iter = devs; iter - devs < num_devs; iter++)
59
60enum controller_display_model {
61 CONTROLLER_DISPLAY_ALL = 0x0,
62 CONTROLLER_DISPLAY_SIMPLISTIC = 0x1,
63};
64
65static int
66cmp_devs(const void *ap, const void *bp)
67{
68 const struct dev *a = ap, *b = bp;
69
70 return spdk_pci_addr_compare(&a->pci_addr, &b->pci_addr);
71}
72
73static bool
74probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
75 struct spdk_nvme_ctrlr_opts *opts)
76{
77 return true;
78}
79
80static void
81identify_common_ns_cb(void *cb_arg, const struct spdk_nvme_cpl *cpl)
82{
83 struct dev *dev = cb_arg;
84
85 if (cpl->status.sc != SPDK_NVME_SC_SUCCESS) {
86 /* Identify Namespace for NSID = FFFFFFFFh is optional, so failure is not fatal. */
11fdf7f2 87 spdk_dma_free(dev->common_ns_data);
7c673cae
FG
88 dev->common_ns_data = NULL;
89 }
90
91 dev->outstanding_admin_cmds--;
92}
93
94static void
95attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
96 struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
97{
98 struct dev *dev;
99 struct spdk_nvme_cmd cmd;
100
101 /* add to dev list */
102 dev = &devs[num_devs++];
103 spdk_pci_addr_parse(&dev->pci_addr, trid->traddr);
104 dev->ctrlr = ctrlr;
105
106 /* Retrieve controller data */
107 dev->cdata = spdk_nvme_ctrlr_get_data(dev->ctrlr);
108
11fdf7f2 109 dev->common_ns_data = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ns_data), 4096, NULL);
7c673cae
FG
110 if (dev->common_ns_data == NULL) {
111 fprintf(stderr, "common_ns_data allocation failure\n");
112 return;
113 }
114
115 /* Identify Namespace with NSID set to FFFFFFFFh to get common namespace capabilities. */
116 memset(&cmd, 0, sizeof(cmd));
117 cmd.opc = SPDK_NVME_OPC_IDENTIFY;
f67539c2 118 cmd.cdw10_bits.identify.cns = 0; /* CNS = 0 (Identify Namespace) */
7c673cae
FG
119 cmd.nsid = SPDK_NVME_GLOBAL_NS_TAG;
120
121 dev->outstanding_admin_cmds++;
122 if (spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, &cmd, dev->common_ns_data,
123 sizeof(struct spdk_nvme_ns_data), identify_common_ns_cb, dev) != 0) {
124 dev->outstanding_admin_cmds--;
11fdf7f2 125 spdk_dma_free(dev->common_ns_data);
7c673cae
FG
126 dev->common_ns_data = NULL;
127 }
128
129 while (dev->outstanding_admin_cmds) {
130 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
131 }
132}
133
134static void usage(void)
135{
136 printf("NVMe Management Options");
137 printf("\n");
138 printf("\t[1: list controllers]\n");
139 printf("\t[2: create namespace]\n");
140 printf("\t[3: delete namespace]\n");
141 printf("\t[4: attach namespace to controller]\n");
142 printf("\t[5: detach namespace from controller]\n");
143 printf("\t[6: format namespace or controller]\n");
144 printf("\t[7: firmware update]\n");
9f95a23c
TL
145 printf("\t[8: opal]\n");
146 printf("\t[9: quit]\n");
7c673cae
FG
147}
148
149static void
150display_namespace_dpc(const struct spdk_nvme_ns_data *nsdata)
151{
152 if (nsdata->dpc.pit1 || nsdata->dpc.pit2 || nsdata->dpc.pit3) {
153 if (nsdata->dpc.pit1) {
154 printf("PIT1 ");
155 }
156
157 if (nsdata->dpc.pit2) {
158 printf("PIT2 ");
159 }
160
161 if (nsdata->dpc.pit3) {
162 printf("PIT3 ");
163 }
164 } else {
165 printf("Not Supported\n");
166 return;
167 }
168
169 if (nsdata->dpc.md_start && nsdata->dpc.md_end) {
170 printf("Location: Head or Tail\n");
171 } else if (nsdata->dpc.md_start) {
172 printf("Location: Head\n");
173 } else if (nsdata->dpc.md_end) {
174 printf("Location: Tail\n");
175 } else {
176 printf("Not Supported\n");
177 }
178}
179
180static void
181display_namespace(struct spdk_nvme_ns *ns)
182{
183 const struct spdk_nvme_ns_data *nsdata;
184 uint32_t i;
185
186 nsdata = spdk_nvme_ns_get_data(ns);
187
188 printf("Namespace ID:%d\n", spdk_nvme_ns_get_id(ns));
189
190 printf("Size (in LBAs): %lld (%lldM)\n",
191 (long long)nsdata->nsze,
192 (long long)nsdata->nsze / 1024 / 1024);
193 printf("Capacity (in LBAs): %lld (%lldM)\n",
194 (long long)nsdata->ncap,
195 (long long)nsdata->ncap / 1024 / 1024);
196 printf("Utilization (in LBAs): %lld (%lldM)\n",
197 (long long)nsdata->nuse,
198 (long long)nsdata->nuse / 1024 / 1024);
199 printf("Format Progress Indicator: %s\n",
200 nsdata->fpi.fpi_supported ? "Supported" : "Not Supported");
11fdf7f2 201 if (nsdata->fpi.fpi_supported && nsdata->fpi.percentage_remaining) {
7c673cae 202 printf("Formatted Percentage: %d%%\n", 100 - nsdata->fpi.percentage_remaining);
11fdf7f2 203 }
7c673cae
FG
204 printf("Number of LBA Formats: %d\n", nsdata->nlbaf + 1);
205 printf("Current LBA Format: LBA Format #%02d\n",
206 nsdata->flbas.format);
207 for (i = 0; i <= nsdata->nlbaf; i++)
208 printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d\n",
209 i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms);
210 printf("Data Protection Capabilities:");
211 display_namespace_dpc(nsdata);
212 if (SPDK_NVME_FMT_NVM_PROTECTION_DISABLE == nsdata->dps.pit) {
213 printf("Data Protection Setting: N/A\n");
214 } else {
215 printf("Data Protection Setting: PIT%d Location: %s\n",
216 nsdata->dps.pit, nsdata->dps.md_start ? "Head" : "Tail");
217 }
218 printf("Multipath IO and Sharing: %s\n",
219 nsdata->nmic.can_share ? "Supported" : "Not Supported");
220 printf("\n");
221}
222
223static void
224display_controller(struct dev *dev, int model)
225{
226 struct spdk_nvme_ns *ns;
227 const struct spdk_nvme_ctrlr_data *cdata;
228 uint8_t str[128];
9f95a23c 229 uint32_t nsid;
7c673cae
FG
230
231 cdata = spdk_nvme_ctrlr_get_data(dev->ctrlr);
232
233 if (model == CONTROLLER_DISPLAY_SIMPLISTIC) {
234 printf("%04x:%02x:%02x.%02x ",
235 dev->pci_addr.domain, dev->pci_addr.bus, dev->pci_addr.dev, dev->pci_addr.func);
236 printf("%-40.40s %-20.20s ",
237 cdata->mn, cdata->sn);
238 printf("%5d ", cdata->cntlid);
239 printf("\n");
240 return;
241 }
242
243 printf("=====================================================\n");
244 printf("NVMe Controller: %04x:%02x:%02x.%02x\n",
245 dev->pci_addr.domain, dev->pci_addr.bus, dev->pci_addr.dev, dev->pci_addr.func);
246 printf("============================\n");
247 printf("Controller Capabilities/Features\n");
248 printf("Controller ID: %d\n", cdata->cntlid);
249 snprintf(str, sizeof(cdata->sn) + 1, "%s", cdata->sn);
250 printf("Serial Number: %s\n", str);
251 printf("\n");
252
253 printf("Admin Command Set Attributes\n");
254 printf("============================\n");
255 printf("Namespace Manage And Attach: %s\n",
256 cdata->oacs.ns_manage ? "Supported" : "Not Supported");
257 printf("Namespace Format: %s\n",
258 cdata->oacs.format ? "Supported" : "Not Supported");
259 printf("\n");
260 printf("NVM Command Set Attributes\n");
261 printf("============================\n");
262 if (cdata->fna.format_all_ns) {
263 printf("Namespace format operation applies to all namespaces\n");
264 } else {
265 printf("Namespace format operation applies to per namespace\n");
266 }
267 printf("\n");
268 printf("Namespace Attributes\n");
269 printf("============================\n");
9f95a23c
TL
270 for (nsid = spdk_nvme_ctrlr_get_first_active_ns(dev->ctrlr);
271 nsid != 0; nsid = spdk_nvme_ctrlr_get_next_active_ns(dev->ctrlr, nsid)) {
272 ns = spdk_nvme_ctrlr_get_ns(dev->ctrlr, nsid);
273 assert(ns != NULL);
7c673cae
FG
274 display_namespace(ns);
275 }
276}
277
278static void
279display_controller_list(void)
280{
281 struct dev *iter;
282
283 foreach_dev(iter) {
284 display_controller(iter, CONTROLLER_DISPLAY_ALL);
285 }
286}
287
11fdf7f2 288static char *
f67539c2 289get_line(char *buf, int buf_size, FILE *f, bool secret)
11fdf7f2 290{
f67539c2 291 char *ch;
11fdf7f2 292 size_t len;
f67539c2
TL
293 struct termios default_attr = {}, new_attr = {};
294 int ret;
295
296 if (secret) {
297 ret = tcgetattr(STDIN_FILENO, &default_attr);
298 if (ret) {
299 return NULL;
300 }
301
302 new_attr = default_attr;
303 new_attr.c_lflag &= ~ECHO; /* disable echo */
304 ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_attr);
305 if (ret) {
306 return NULL;
307 }
308 }
11fdf7f2 309
f67539c2
TL
310 ch = fgets(buf, buf_size, f);
311 if (ch == NULL) {
11fdf7f2
TL
312 return NULL;
313 }
314
f67539c2
TL
315 if (secret) {
316 ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, &default_attr); /* restore default confing */
317 if (ret) {
318 return NULL;
319 }
320 }
321
11fdf7f2
TL
322 len = strlen(buf);
323 if (len > 0 && buf[len - 1] == '\n') {
324 buf[len - 1] = '\0';
325 }
326 return buf;
327}
328
7c673cae
FG
329static struct dev *
330get_controller(void)
331{
332 struct spdk_pci_addr pci_addr;
333 char address[64];
334 char *p;
335 int ch;
336 struct dev *iter;
337
338 memset(address, 0, sizeof(address));
339
340 foreach_dev(iter) {
341 display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC);
342 }
343
11fdf7f2 344 printf("Please Input PCI Address(domain:bus:dev.func):\n");
7c673cae
FG
345
346 while ((ch = getchar()) != '\n' && ch != EOF);
f67539c2 347 p = get_line(address, 64, stdin, false);
7c673cae
FG
348 if (p == NULL) {
349 return NULL;
350 }
351
352 while (isspace(*p)) {
353 p++;
354 }
355
356 if (spdk_pci_addr_parse(&pci_addr, p) < 0) {
357 return NULL;
358 }
359
360 foreach_dev(iter) {
361 if (spdk_pci_addr_compare(&pci_addr, &iter->pci_addr) == 0) {
362 return iter;
363 }
364 }
365 return NULL;
366}
367
368static int
369get_lba_format(const struct spdk_nvme_ns_data *ns_data)
370{
371 int lbaf, i;
372
373 printf("\nSupported LBA formats:\n");
374 for (i = 0; i <= ns_data->nlbaf; i++) {
375 printf("%2d: %d data bytes", i, 1 << ns_data->lbaf[i].lbads);
376 if (ns_data->lbaf[i].ms) {
377 printf(" + %d metadata bytes", ns_data->lbaf[i].ms);
378 }
379 printf("\n");
380 }
381
382 printf("Please input LBA format index (0 - %d):\n", ns_data->nlbaf);
383 if (scanf("%d", &lbaf) != 1 || lbaf > ns_data->nlbaf) {
384 return -1;
385 }
386
387 return lbaf;
388}
389
390static void
391identify_allocated_ns_cb(void *cb_arg, const struct spdk_nvme_cpl *cpl)
392{
393 struct dev *dev = cb_arg;
394
395 dev->outstanding_admin_cmds--;
396}
397
398static uint32_t
399get_allocated_nsid(struct dev *dev)
400{
401 uint32_t nsid;
402 size_t i;
403 struct spdk_nvme_ns_list *ns_list;
404 struct spdk_nvme_cmd cmd = {0};
405
11fdf7f2 406 ns_list = spdk_dma_zmalloc(sizeof(*ns_list), 4096, NULL);
7c673cae
FG
407 if (ns_list == NULL) {
408 printf("Allocation error\n");
409 return 0;
410 }
411
412 cmd.opc = SPDK_NVME_OPC_IDENTIFY;
f67539c2 413 cmd.cdw10_bits.identify.cns = SPDK_NVME_IDENTIFY_ALLOCATED_NS_LIST;
7c673cae
FG
414 cmd.nsid = 0;
415
416 dev->outstanding_admin_cmds++;
417 if (spdk_nvme_ctrlr_cmd_admin_raw(dev->ctrlr, &cmd, ns_list, sizeof(*ns_list),
418 identify_allocated_ns_cb, dev)) {
419 printf("Identify command failed\n");
11fdf7f2 420 spdk_dma_free(ns_list);
7c673cae
FG
421 return 0;
422 }
423
424 while (dev->outstanding_admin_cmds) {
425 spdk_nvme_ctrlr_process_admin_completions(dev->ctrlr);
426 }
427
428 printf("Allocated Namespace IDs:\n");
429 for (i = 0; i < SPDK_COUNTOF(ns_list->ns_list); i++) {
430 if (ns_list->ns_list[i] == 0) {
431 break;
432 }
433 printf("%u\n", ns_list->ns_list[i]);
434 }
435
11fdf7f2 436 spdk_dma_free(ns_list);
7c673cae 437
11fdf7f2 438 printf("Please Input Namespace ID:\n");
7c673cae
FG
439 if (!scanf("%u", &nsid)) {
440 printf("Invalid Namespace ID\n");
441 nsid = 0;
442 }
443
444 return nsid;
445}
446
447static void
448ns_attach(struct dev *device, int attachment_op, int ctrlr_id, int ns_id)
449{
450 int ret = 0;
451 struct spdk_nvme_ctrlr_list *ctrlr_list;
452
11fdf7f2
TL
453 ctrlr_list = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ctrlr_list),
454 4096, NULL);
7c673cae
FG
455 if (ctrlr_list == NULL) {
456 printf("Allocation error (controller list)\n");
457 exit(1);
458 }
459
460 ctrlr_list->ctrlr_count = 1;
461 ctrlr_list->ctrlr_list[0] = ctrlr_id;
462
463 if (attachment_op == SPDK_NVME_NS_CTRLR_ATTACH) {
464 ret = spdk_nvme_ctrlr_attach_ns(device->ctrlr, ns_id, ctrlr_list);
465 } else if (attachment_op == SPDK_NVME_NS_CTRLR_DETACH) {
466 ret = spdk_nvme_ctrlr_detach_ns(device->ctrlr, ns_id, ctrlr_list);
467 }
468
469 if (ret) {
470 fprintf(stdout, "ns attach: Failed\n");
471 }
472
11fdf7f2 473 spdk_dma_free(ctrlr_list);
7c673cae
FG
474}
475
476static void
477ns_manage_add(struct dev *device, uint64_t ns_size, uint64_t ns_capacity, int ns_lbasize,
478 uint8_t ns_dps_type, uint8_t ns_dps_location, uint8_t ns_nmic)
479{
480 uint32_t nsid;
481 struct spdk_nvme_ns_data *ndata;
482
11fdf7f2 483 ndata = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ns_data), 4096, NULL);
7c673cae
FG
484 if (ndata == NULL) {
485 printf("Allocation error (namespace data)\n");
486 exit(1);
487 }
488
489 ndata->nsze = ns_size;
490 ndata->ncap = ns_capacity;
491 ndata->flbas.format = ns_lbasize;
492 if (SPDK_NVME_FMT_NVM_PROTECTION_DISABLE != ns_dps_type) {
493 ndata->dps.pit = ns_dps_type;
494 ndata->dps.md_start = ns_dps_location;
495 }
496 ndata->nmic.can_share = ns_nmic;
497 nsid = spdk_nvme_ctrlr_create_ns(device->ctrlr, ndata);
498 if (nsid == 0) {
499 fprintf(stdout, "ns manage: Failed\n");
500 } else {
501 printf("Created namespace ID %u\n", nsid);
502 }
503
11fdf7f2 504 spdk_dma_free(ndata);
7c673cae
FG
505}
506
507static void
508ns_manage_delete(struct dev *device, int ns_id)
509{
510 int ret = 0;
511
512 ret = spdk_nvme_ctrlr_delete_ns(device->ctrlr, ns_id);
513 if (ret) {
514 fprintf(stdout, "ns manage: Failed\n");
515 return;
516 }
517}
518
519static void
520nvme_manage_format(struct dev *device, int ns_id, int ses, int pi, int pil, int ms, int lbaf)
521{
522 int ret = 0;
523 struct spdk_nvme_format format = {};
524
525 format.lbaf = lbaf;
526 format.ms = ms;
527 format.pi = pi;
528 format.pil = pil;
529 format.ses = ses;
530 ret = spdk_nvme_ctrlr_format(device->ctrlr, ns_id, &format);
531 if (ret) {
532 fprintf(stdout, "nvme format: Failed\n");
533 return;
534 }
535}
536
537static void
538attach_and_detach_ns(int attachment_op)
539{
540 uint32_t nsid;
541 struct dev *ctrlr;
542
543 ctrlr = get_controller();
544 if (ctrlr == NULL) {
545 printf("Invalid controller PCI Address.\n");
546 return;
547 }
548
549 if (!ctrlr->cdata->oacs.ns_manage) {
550 printf("Controller does not support ns management\n");
551 return;
552 }
553
554 nsid = get_allocated_nsid(ctrlr);
555 if (nsid == 0) {
556 printf("Invalid Namespace ID\n");
557 return;
558 }
559
560 ns_attach(ctrlr, attachment_op, ctrlr->cdata->cntlid, nsid);
561}
562
563static void
564add_ns(void)
565{
566 uint64_t ns_size = 0;
567 uint64_t ns_capacity = 0;
568 int ns_lbasize;
11fdf7f2
TL
569 int ns_dps_type = 0;
570 int ns_dps_location = 0;
571 int ns_nmic = 0;
7c673cae
FG
572 struct dev *ctrlr = NULL;
573
574 ctrlr = get_controller();
575 if (ctrlr == NULL) {
576 printf("Invalid controller PCI Address.\n");
577 return;
578 }
579
580 if (!ctrlr->cdata->oacs.ns_manage) {
581 printf("Controller does not support ns management\n");
582 return;
583 }
584
585 if (!ctrlr->common_ns_data) {
586 printf("Controller did not return common namespace capabilities\n");
587 return;
588 }
589
590 ns_lbasize = get_lba_format(ctrlr->common_ns_data);
591 if (ns_lbasize < 0) {
592 printf("Invalid LBA format number\n");
593 return;
594 }
595
11fdf7f2
TL
596 printf("Please Input Namespace Size (in LBAs):\n");
597 if (!scanf("%" SCNu64, &ns_size)) {
7c673cae
FG
598 printf("Invalid Namespace Size\n");
599 while (getchar() != '\n');
600 return;
601 }
602
11fdf7f2
TL
603 printf("Please Input Namespace Capacity (in LBAs):\n");
604 if (!scanf("%" SCNu64, &ns_capacity)) {
7c673cae
FG
605 printf("Invalid Namespace Capacity\n");
606 while (getchar() != '\n');
607 return;
608 }
609
11fdf7f2 610 printf("Please Input Data Protection Type (0 - 3):\n");
7c673cae
FG
611 if (!scanf("%d", &ns_dps_type)) {
612 printf("Invalid Data Protection Type\n");
613 while (getchar() != '\n');
614 return;
615 }
616
617 if (SPDK_NVME_FMT_NVM_PROTECTION_DISABLE != ns_dps_type) {
11fdf7f2 618 printf("Please Input Data Protection Location (1: Head; 0: Tail):\n");
7c673cae
FG
619 if (!scanf("%d", &ns_dps_location)) {
620 printf("Invalid Data Protection Location\n");
621 while (getchar() != '\n');
622 return;
623 }
624 }
625
11fdf7f2 626 printf("Please Input Multi-path IO and Sharing Capabilities (1: Share; 0: Private):\n");
7c673cae
FG
627 if (!scanf("%d", &ns_nmic)) {
628 printf("Invalid Multi-path IO and Sharing Capabilities\n");
629 while (getchar() != '\n');
630 return;
631 }
632
633 ns_manage_add(ctrlr, ns_size, ns_capacity, ns_lbasize,
634 ns_dps_type, ns_dps_location, ns_nmic);
635}
636
637static void
638delete_ns(void)
639{
11fdf7f2 640 int ns_id;
7c673cae
FG
641 struct dev *ctrlr;
642
643 ctrlr = get_controller();
644 if (ctrlr == NULL) {
645 printf("Invalid controller PCI Address.\n");
646 return;
647 }
648
649 if (!ctrlr->cdata->oacs.ns_manage) {
650 printf("Controller does not support ns management\n");
651 return;
652 }
653
11fdf7f2 654 printf("Please Input Namespace ID:\n");
7c673cae
FG
655 if (!scanf("%d", &ns_id)) {
656 printf("Invalid Namespace ID\n");
657 while (getchar() != '\n');
658 return;
659 }
660
661 ns_manage_delete(ctrlr, ns_id);
662}
663
664static void
665format_nvm(void)
666{
11fdf7f2 667 int ns_id;
7c673cae
FG
668 int ses;
669 int pil;
670 int pi;
671 int ms;
672 int lbaf;
673 char option;
674 struct dev *ctrlr;
675 const struct spdk_nvme_ctrlr_data *cdata;
676 struct spdk_nvme_ns *ns;
677 const struct spdk_nvme_ns_data *nsdata;
678
679 ctrlr = get_controller();
680 if (ctrlr == NULL) {
681 printf("Invalid controller PCI BDF.\n");
682 return;
683 }
684
685 cdata = ctrlr->cdata;
686
687 if (!cdata->oacs.format) {
688 printf("Controller does not support Format NVM command\n");
689 return;
690 }
691
692 if (cdata->fna.format_all_ns) {
693 ns_id = SPDK_NVME_GLOBAL_NS_TAG;
694 ns = spdk_nvme_ctrlr_get_ns(ctrlr->ctrlr, 1);
695 } else {
11fdf7f2 696 printf("Please Input Namespace ID (1 - %d):\n", cdata->nn);
7c673cae
FG
697 if (!scanf("%d", &ns_id)) {
698 printf("Invalid Namespace ID\n");
699 while (getchar() != '\n');
700 return;
701 }
702 ns = spdk_nvme_ctrlr_get_ns(ctrlr->ctrlr, ns_id);
703 }
704
705 if (ns == NULL) {
706 printf("Namespace ID %d not found\n", ns_id);
707 while (getchar() != '\n');
708 return;
709 }
710
711 nsdata = spdk_nvme_ns_get_data(ns);
712
11fdf7f2 713 printf("Please Input Secure Erase Setting:\n");
7c673cae
FG
714 printf(" 0: No secure erase operation requested\n");
715 printf(" 1: User data erase\n");
716 if (cdata->fna.crypto_erase_supported) {
717 printf(" 2: Cryptographic erase\n");
718 }
719 if (!scanf("%d", &ses)) {
720 printf("Invalid Secure Erase Setting\n");
721 while (getchar() != '\n');
722 return;
723 }
724
725 lbaf = get_lba_format(nsdata);
726 if (lbaf < 0) {
727 printf("Invalid LBA format number\n");
728 return;
729 }
730
731 if (nsdata->lbaf[lbaf].ms) {
11fdf7f2 732 printf("Please Input Protection Information:\n");
7c673cae
FG
733 printf(" 0: Protection information is not enabled\n");
734 printf(" 1: Protection information is enabled, Type 1\n");
735 printf(" 2: Protection information is enabled, Type 2\n");
736 printf(" 3: Protection information is enabled, Type 3\n");
737 if (!scanf("%d", &pi)) {
738 printf("Invalid protection information\n");
739 while (getchar() != '\n');
740 return;
741 }
742
743 if (pi) {
11fdf7f2 744 printf("Please Input Protection Information Location:\n");
7c673cae
FG
745 printf(" 0: Protection information transferred as the last eight bytes of metadata\n");
746 printf(" 1: Protection information transferred as the first eight bytes of metadata\n");
747 if (!scanf("%d", &pil)) {
748 printf("Invalid protection information location\n");
749 while (getchar() != '\n');
750 return;
751 }
752 } else {
753 pil = 0;
754 }
755
11fdf7f2 756 printf("Please Input Metadata Setting:\n");
7c673cae
FG
757 printf(" 0: Metadata is transferred as part of a separate buffer\n");
758 printf(" 1: Metadata is transferred as part of an extended data LBA\n");
759 if (!scanf("%d", &ms)) {
760 printf("Invalid metadata setting\n");
761 while (getchar() != '\n');
762 return;
763 }
764 } else {
765 ms = 0;
766 pi = 0;
767 pil = 0;
768 }
769
770 printf("Warning: use this utility at your own risk.\n"
771 "This command will format your namespace and all data will be lost.\n"
772 "This command may take several minutes to complete,\n"
773 "so do not interrupt the utility until it completes.\n"
774 "Press 'Y' to continue with the format operation.\n");
775
776 while (getchar() != '\n');
777 if (!scanf("%c", &option)) {
778 printf("Invalid option\n");
779 while (getchar() != '\n');
780 return;
781 }
782
783 if (option == 'y' || option == 'Y') {
784 nvme_manage_format(ctrlr, ns_id, ses, pi, pil, ms, lbaf);
785 } else {
786 printf("NVMe format abort\n");
787 }
788}
789
790static void
791update_firmware_image(void)
792{
793 int rc;
794 int fd = -1;
795 int slot;
796 unsigned int size;
797 struct stat fw_stat;
798 char path[256];
799 void *fw_image;
800 struct dev *ctrlr;
801 const struct spdk_nvme_ctrlr_data *cdata;
11fdf7f2
TL
802 enum spdk_nvme_fw_commit_action commit_action;
803 struct spdk_nvme_status status;
7c673cae
FG
804
805 ctrlr = get_controller();
806 if (ctrlr == NULL) {
807 printf("Invalid controller PCI BDF.\n");
808 return;
809 }
810
811 cdata = ctrlr->cdata;
812
813 if (!cdata->oacs.firmware) {
814 printf("Controller does not support firmware download and commit command\n");
815 return;
816 }
817
818 printf("Please Input The Path Of Firmware Image\n");
819
f67539c2 820 if (get_line(path, sizeof(path), stdin, false) == NULL) {
7c673cae
FG
821 printf("Invalid path setting\n");
822 while (getchar() != '\n');
823 return;
824 }
825
826 fd = open(path, O_RDONLY);
827 if (fd < 0) {
828 perror("Open file failed");
829 return;
830 }
831 rc = fstat(fd, &fw_stat);
832 if (rc < 0) {
833 printf("Fstat failed\n");
834 close(fd);
835 return;
836 }
837
838 if (fw_stat.st_size % 4) {
839 printf("Firmware image size is not multiple of 4\n");
840 close(fd);
841 return;
842 }
843
844 size = fw_stat.st_size;
845
11fdf7f2 846 fw_image = spdk_dma_zmalloc(size, 4096, NULL);
7c673cae
FG
847 if (fw_image == NULL) {
848 printf("Allocation error\n");
849 close(fd);
850 return;
851 }
852
853 if (read(fd, fw_image, size) != ((ssize_t)(size))) {
854 printf("Read firmware image failed\n");
855 close(fd);
11fdf7f2 856 spdk_dma_free(fw_image);
7c673cae
FG
857 return;
858 }
859 close(fd);
860
11fdf7f2 861 printf("Please Input Slot(0 - 7):\n");
7c673cae
FG
862 if (!scanf("%d", &slot)) {
863 printf("Invalid Slot\n");
11fdf7f2 864 spdk_dma_free(fw_image);
7c673cae
FG
865 while (getchar() != '\n');
866 return;
867 }
868
11fdf7f2
TL
869 commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG;
870 rc = spdk_nvme_ctrlr_update_firmware(ctrlr->ctrlr, fw_image, size, slot, commit_action, &status);
871 if (rc == -ENXIO && status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC &&
872 status.sc == SPDK_NVME_SC_FIRMWARE_REQ_CONVENTIONAL_RESET) {
873 printf("conventional reset is needed to enable firmware !\n");
874 } else if (rc) {
7c673cae
FG
875 printf("spdk_nvme_ctrlr_update_firmware failed\n");
876 } else {
877 printf("spdk_nvme_ctrlr_update_firmware success\n");
878 }
11fdf7f2
TL
879 spdk_dma_free(fw_image);
880}
881
9f95a23c 882static void
f67539c2 883opal_dump_info(struct spdk_opal_d0_features_info *feat)
9f95a23c 884{
f67539c2 885 if (feat->tper.hdr.code) {
9f95a23c 886 printf("\nOpal TPer feature:\n");
f67539c2
TL
887 printf("ACKNACK = %s", (feat->tper.acknack ? "Y, " : "N, "));
888 printf("ASYNC = %s", (feat->tper.async ? "Y, " : "N, "));
889 printf("BufferManagement = %s\n", (feat->tper.buffer_management ? "Y, " : "N, "));
890 printf("ComIDManagement = %s", (feat->tper.comid_management ? "Y, " : "N, "));
891 printf("Streaming = %s", (feat->tper.streaming ? "Y, " : "N, "));
892 printf("Sync = %s\n", (feat->tper.sync ? "Y" : "N"));
9f95a23c
TL
893 printf("\n");
894 }
895
f67539c2 896 if (feat->locking.hdr.code) {
9f95a23c 897 printf("Opal Locking feature:\n");
f67539c2
TL
898 printf("Locked = %s", (feat->locking.locked ? "Y, " : "N, "));
899 printf("Locking Enabled = %s", (feat->locking.locking_enabled ? "Y, " : "N, "));
900 printf("Locking supported = %s\n", (feat->locking.locking_supported ? "Y" : "N"));
9f95a23c 901
f67539c2
TL
902 printf("MBR done = %s", (feat->locking.mbr_done ? "Y, " : "N, "));
903 printf("MBR enabled = %s", (feat->locking.mbr_enabled ? "Y, " : "N, "));
904 printf("Media encrypt = %s\n", (feat->locking.media_encryption ? "Y" : "N"));
9f95a23c
TL
905 printf("\n");
906 }
907
f67539c2 908 if (feat->geo.hdr.code) {
9f95a23c 909 printf("Opal Geometry feature:\n");
f67539c2
TL
910 printf("Align = %s", (feat->geo.alignment_granularity ? "Y, " : "N, "));
911 printf("Logical block size = %d, ", from_be32(&feat->geo.logical_block_size));
912 printf("Lowest aligned LBA = %ld\n", from_be64(&feat->geo.lowest_aligned_lba));
9f95a23c
TL
913 printf("\n");
914 }
915
f67539c2 916 if (feat->single_user.hdr.code) {
9f95a23c 917 printf("Opal Single User Mode feature:\n");
f67539c2
TL
918 printf("Any in SUM = %s", (feat->single_user.any ? "Y, " : "N, "));
919 printf("All in SUM = %s", (feat->single_user.all ? "Y, " : "N, "));
920 printf("Policy: %s Authority,\n", (feat->single_user.policy ? "Admin" : "Users"));
921 printf("Number of locking objects = %d\n ", from_be32(&feat->single_user.num_locking_objects));
9f95a23c
TL
922 printf("\n");
923 }
924
f67539c2 925 if (feat->datastore.hdr.code) {
9f95a23c 926 printf("Opal DataStore feature:\n");
f67539c2
TL
927 printf("Table alignment = %d, ", from_be32(&feat->datastore.alignment));
928 printf("Max number of tables = %d, ", from_be16(&feat->datastore.max_tables));
929 printf("Max size of tables = %d\n", from_be32(&feat->datastore.max_table_size));
9f95a23c
TL
930 printf("\n");
931 }
932
f67539c2 933 if (feat->v100.hdr.code) {
9f95a23c 934 printf("Opal V100 feature:\n");
f67539c2
TL
935 printf("Base comID = %d, ", from_be16(&feat->v100.base_comid));
936 printf("Number of comIDs = %d, ", from_be16(&feat->v100.number_comids));
937 printf("Range crossing = %s\n", (feat->v100.range_crossing ? "N" : "Y"));
9f95a23c
TL
938 printf("\n");
939 }
940
f67539c2 941 if (feat->v200.hdr.code) {
9f95a23c 942 printf("Opal V200 feature:\n");
f67539c2
TL
943 printf("Base comID = %d, ", from_be16(&feat->v200.base_comid));
944 printf("Number of comIDs = %d, ", from_be16(&feat->v200.num_comids));
945 printf("Initial PIN = %d,\n", feat->v200.initial_pin);
946 printf("Reverted PIN = %d, ", feat->v200.reverted_pin);
947 printf("Number of admins = %d, ", from_be16(&feat->v200.num_locking_admin_auth));
948 printf("Number of users = %d\n", from_be16(&feat->v200.num_locking_user_auth));
949 printf("\n");
9f95a23c
TL
950 }
951}
952
953static void
954opal_usage(void)
955{
956 printf("Opal General Usage:\n");
957 printf("\n");
958 printf("\t[1: scan device]\n");
f67539c2 959 printf("\t[2: init - take ownership and activate locking]\n");
9f95a23c 960 printf("\t[3: revert tper]\n");
f67539c2
TL
961 printf("\t[4: setup locking range]\n");
962 printf("\t[5: list locking ranges]\n");
963 printf("\t[6: enable user]\n");
964 printf("\t[7: set new password]\n");
965 printf("\t[8: add user to locking range]\n");
966 printf("\t[9: lock/unlock range]\n");
967 printf("\t[10: erase locking range]\n");
9f95a23c
TL
968 printf("\t[0: quit]\n");
969}
970
971static void
972opal_scan(struct dev *iter)
973{
f67539c2 974 while (getchar() != '\n');
9f95a23c 975 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
f67539c2 976 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
9f95a23c
TL
977 if (iter->opal_dev == NULL) {
978 return;
979 }
980
f67539c2
TL
981 printf("\n\nOpal Supported:\n");
982 display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC);
983 opal_dump_info(spdk_opal_get_d0_features_info(iter->opal_dev));
984 spdk_opal_dev_destruct(iter->opal_dev);
9f95a23c
TL
985 } else {
986 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n",
987 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
988 printf("%04x:%02x:%02x.%02x: Opal Not Supported\n\n\n",
989 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
990 }
991}
992
993static void
f67539c2 994opal_init(struct dev *iter)
9f95a23c 995{
f67539c2 996 char new_passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
9f95a23c
TL
997 char *passwd_p;
998 int ret;
999 int ch;
1000
1001 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
f67539c2 1002 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
9f95a23c
TL
1003 if (iter->opal_dev == NULL) {
1004 return;
1005 }
f67539c2
TL
1006 printf("Please input the new password for ownership:");
1007 while ((ch = getchar()) != '\n' && ch != EOF);
1008 passwd_p = get_line(new_passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1009 printf("\n...\n");
1010 if (passwd_p) {
1011 ret = spdk_opal_cmd_take_ownership(iter->opal_dev, passwd_p);
1012 if (ret) {
1013 printf("Take ownership failure: %d\n", ret);
1014 spdk_opal_dev_destruct(iter->opal_dev);
1015 return;
1016 }
1017
1018 ret = spdk_opal_cmd_activate_locking_sp(iter->opal_dev, passwd_p);
1019 if (ret) {
1020 printf("Locking SP activate failure: %d\n", ret);
1021 spdk_opal_dev_destruct(iter->opal_dev);
1022 return;
1023 }
1024 printf("...\nOpal Init Success\n");
1025 } else {
1026 printf("Input password invalid. Opal Init failure\n");
1027 }
1028 spdk_opal_dev_destruct(iter->opal_dev);
1029 } else {
1030 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1031 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1032 }
1033}
1034
1035static void
1036opal_locking_usage(void)
1037{
1038 printf("Choose Opal locking state:\n");
1039 printf("\n");
1040 printf("\t[1: read write lock]\n");
1041 printf("\t[2: read only]\n");
1042 printf("\t[3: read write unlock]\n");
1043}
1044
1045static void
1046opal_setup_lockingrange(struct dev *iter)
1047{
1048 char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1049 char *passwd_p;
1050 int ret;
1051 int ch;
1052 uint64_t range_start;
1053 uint64_t range_length;
1054 int locking_range_id;
1055 struct spdk_opal_locking_range_info *info;
1056
1057 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1058 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1059 if (iter->opal_dev == NULL) {
1060 return;
1061 }
1062 printf("Please input the password for setting up locking range:");
1063 while ((ch = getchar()) != '\n' && ch != EOF);
1064 passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1065 printf("\n");
1066 if (passwd_p) {
1067 printf("Specify locking range id:\n");
1068 if (!scanf("%d", &locking_range_id)) {
1069 printf("Invalid locking range id\n");
1070 spdk_opal_dev_destruct(iter->opal_dev);
1071 return;
1072 }
1073
1074 printf("range length:\n");
1075 if (!scanf("%" SCNu64, &range_length)) {
1076 printf("Invalid range length\n");
1077 spdk_opal_dev_destruct(iter->opal_dev);
1078 return;
1079 }
1080
1081 printf("range start:\n");
1082 if (!scanf("%" SCNu64, &range_start)) {
1083 printf("Invalid range start address\n");
1084 spdk_opal_dev_destruct(iter->opal_dev);
1085 return;
1086 }
1087 while (getchar() != '\n');
1088
1089 ret = spdk_opal_cmd_setup_locking_range(iter->opal_dev,
1090 OPAL_ADMIN1, locking_range_id, range_start, range_length, passwd_p);
1091 if (ret) {
1092 printf("Setup locking range failure: %d\n", ret);
1093 spdk_opal_dev_destruct(iter->opal_dev);
1094 return;
1095 }
1096
1097 ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev,
1098 passwd_p, OPAL_ADMIN1, locking_range_id);
1099 if (ret) {
1100 printf("Get locking range info failure: %d\n", ret);
1101 spdk_opal_dev_destruct(iter->opal_dev);
1102 return;
1103 }
1104 info = spdk_opal_get_locking_range_info(iter->opal_dev, locking_range_id);
1105
1106 printf("\nlocking range ID: %d\n", info->locking_range_id);
1107 printf("range start: %ld\n", info->range_start);
1108 printf("range length: %ld\n", info->range_length);
1109 printf("read lock enabled: %d\n", info->read_lock_enabled);
1110 printf("write lock enabled: %d\n", info->write_lock_enabled);
1111 printf("read locked: %d\n", info->read_locked);
1112 printf("write locked: %d\n", info->write_locked);
1113
1114 printf("...\n...\nOpal setup locking range success\n");
1115 } else {
1116 printf("Input password invalid. Opal setup locking range failure\n");
1117 }
1118 spdk_opal_dev_destruct(iter->opal_dev);
1119 } else {
1120 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1121 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1122 }
1123}
1124
1125static void
1126opal_list_locking_ranges(struct dev *iter)
1127{
1128 char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1129 char *passwd_p;
1130 int ret;
1131 int ch;
1132 int max_ranges;
1133 int i;
1134 struct spdk_opal_locking_range_info *info;
1135
1136 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1137 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1138 if (iter->opal_dev == NULL) {
1139 return;
1140 }
1141 printf("Please input password:");
1142 while ((ch = getchar()) != '\n' && ch != EOF);
1143 passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1144 printf("\n");
1145 if (passwd_p) {
1146 ret = spdk_opal_cmd_get_max_ranges(iter->opal_dev, passwd_p);
1147 if (ret <= 0) {
1148 printf("get max ranges failure: %d\n", ret);
1149 spdk_opal_dev_destruct(iter->opal_dev);
1150 return;
1151 }
1152
1153 max_ranges = ret;
1154 for (i = 0; i < max_ranges; i++) {
1155 ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev,
1156 passwd_p, OPAL_ADMIN1, i);
9f95a23c 1157 if (ret) {
f67539c2
TL
1158 printf("Get locking range info failure: %d\n", ret);
1159 spdk_opal_dev_destruct(iter->opal_dev);
9f95a23c
TL
1160 return;
1161 }
f67539c2
TL
1162 info = spdk_opal_get_locking_range_info(iter->opal_dev, i);
1163 if (info == NULL) {
1164 continue;
1165 }
1166
1167 printf("===============================================\n");
1168 printf("locking range ID: %d\t", info->locking_range_id);
1169 if (i == 0) { printf("(Global Range)"); }
1170 printf("\n===============================================\n");
1171 printf("range start: %ld\t", info->range_start);
1172 printf("range length: %ld\n", info->range_length);
1173 printf("read lock enabled: %d\t", info->read_lock_enabled);
1174 printf("write lock enabled: %d\t", info->write_lock_enabled);
1175 printf("read locked: %d\t", info->read_locked);
1176 printf("write locked: %d\n", info->write_locked);
1177 printf("\n");
9f95a23c 1178 }
f67539c2
TL
1179 } else {
1180 printf("Input password invalid. List locking ranges failure\n");
9f95a23c 1181 }
f67539c2 1182 spdk_opal_dev_destruct(iter->opal_dev);
9f95a23c
TL
1183 } else {
1184 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1185 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1186 }
1187}
1188
1189static void
f67539c2 1190opal_new_user_enable(struct dev *iter)
9f95a23c 1191{
f67539c2
TL
1192 int user_id;
1193 char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
9f95a23c 1194 char *passwd_p;
f67539c2
TL
1195 char user_pw[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1196 char *user_pw_p;
9f95a23c
TL
1197 int ret;
1198 int ch;
1199
1200 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
f67539c2 1201 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
9f95a23c
TL
1202 if (iter->opal_dev == NULL) {
1203 return;
1204 }
f67539c2
TL
1205 printf("Please input admin password:");
1206 while ((ch = getchar()) != '\n' && ch != EOF);
1207 passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1208 printf("\n");
1209 if (passwd_p) {
1210 printf("which user to enable: ");
1211 if (!scanf("%d", &user_id)) {
1212 printf("Invalid user id\n");
1213 spdk_opal_dev_destruct(iter->opal_dev);
1214 return;
1215 }
1216
1217 ret = spdk_opal_cmd_enable_user(iter->opal_dev, user_id, passwd_p);
1218 if (ret) {
1219 printf("Enable user failure error code: %d\n", ret);
1220 spdk_opal_dev_destruct(iter->opal_dev);
1221 return;
1222 }
1223 printf("Please set a new password for this user:");
9f95a23c 1224 while ((ch = getchar()) != '\n' && ch != EOF);
f67539c2
TL
1225 user_pw_p = get_line(user_pw, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1226 if (user_pw_p == NULL) {
1227 printf("Input password invalid. Enable user failure\n");
1228 spdk_opal_dev_destruct(iter->opal_dev);
1229 return;
1230 }
1231
1232 ret = spdk_opal_cmd_set_new_passwd(iter->opal_dev, user_id, user_pw_p, passwd_p, true);
1233 if (ret) {
1234 printf("Set new password failure error code: %d\n", ret);
1235 spdk_opal_dev_destruct(iter->opal_dev);
1236 return;
1237 }
1238
1239 printf("\n...\n...\nEnable User Success\n");
1240 } else {
1241 printf("Input password invalid. Enable user failure\n");
1242 }
1243 spdk_opal_dev_destruct(iter->opal_dev);
1244 } else {
1245 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1246 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1247 }
1248}
1249
1250static void
1251opal_change_password(struct dev *iter)
1252{
1253 int user_id;
1254 char old_passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1255 char *old_passwd_p;
1256 char new_passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1257 char *new_passwd_p;
1258 int ret;
1259 int ch;
1260
1261 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1262 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1263 if (iter->opal_dev == NULL) {
1264 return;
1265 }
1266 printf("user id: ");
1267 if (!scanf("%d", &user_id)) {
1268 printf("Invalid user id\n");
1269 spdk_opal_dev_destruct(iter->opal_dev);
1270 return;
1271 }
1272 printf("Password:");
1273 while ((ch = getchar()) != '\n' && ch != EOF);
1274 old_passwd_p = get_line(old_passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1275 printf("\n");
1276 if (old_passwd_p) {
1277 printf("Please input new password:\n");
1278 new_passwd_p = get_line(new_passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1279 printf("\n");
1280 if (new_passwd_p == NULL) {
1281 printf("Input password invalid. Change password failure\n");
1282 spdk_opal_dev_destruct(iter->opal_dev);
1283 return;
9f95a23c 1284 }
f67539c2
TL
1285
1286 ret = spdk_opal_cmd_set_new_passwd(iter->opal_dev, user_id, new_passwd_p, old_passwd_p, false);
1287 if (ret) {
1288 printf("Set new password failure error code: %d\n", ret);
1289 spdk_opal_dev_destruct(iter->opal_dev);
1290 return;
1291 }
1292
1293 printf("...\n...\nChange password Success\n");
1294 } else {
1295 printf("Input password invalid. Change password failure\n");
9f95a23c 1296 }
f67539c2
TL
1297 spdk_opal_dev_destruct(iter->opal_dev);
1298 } else {
1299 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1300 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1301 }
1302}
1303
1304static void
1305opal_add_user_to_locking_range(struct dev *iter)
1306{
1307 int locking_range_id, user_id;
1308 char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1309 char *passwd_p;
1310 int ret;
1311 int ch;
1312
1313 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1314 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1315 if (iter->opal_dev == NULL) {
1316 return;
1317 }
1318 printf("Please input admin password:");
1319 while ((ch = getchar()) != '\n' && ch != EOF);
1320 passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1321 printf("\n");
1322 if (passwd_p) {
1323 printf("Specify locking range id:\n");
1324 if (!scanf("%d", &locking_range_id)) {
1325 printf("Invalid locking range id\n");
1326 spdk_opal_dev_destruct(iter->opal_dev);
1327 return;
1328 }
1329
1330 printf("which user to enable:\n");
1331 if (!scanf("%d", &user_id)) {
1332 printf("Invalid user id\n");
1333 spdk_opal_dev_destruct(iter->opal_dev);
1334 return;
1335 }
1336 while (getchar() != '\n');
1337
1338 ret = spdk_opal_cmd_add_user_to_locking_range(iter->opal_dev, user_id, locking_range_id,
1339 OPAL_READONLY, passwd_p);
1340 ret += spdk_opal_cmd_add_user_to_locking_range(iter->opal_dev, user_id, locking_range_id,
1341 OPAL_READWRITE, passwd_p);
1342 if (ret) {
1343 printf("Add user to locking range error: %d\n", ret);
1344 spdk_opal_dev_destruct(iter->opal_dev);
1345 return;
1346 }
1347
1348 printf("...\n...\nAdd user to locking range Success\n");
1349 } else {
1350 printf("Input password invalid. Add user to locking range failure\n");
1351 }
1352 spdk_opal_dev_destruct(iter->opal_dev);
1353 } else {
1354 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1355 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1356 }
1357}
1358
1359static void
1360opal_user_lock_unlock_range(struct dev *iter)
1361{
1362 char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1363 char *passwd_p;
1364 int ch;
1365 int ret;
1366 int user_id;
1367 int locking_range_id;
1368 int state;
1369 enum spdk_opal_lock_state state_flag;
1370
1371 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1372 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1373 if (iter->opal_dev == NULL) {
1374 return;
1375 }
1376 printf("User id: ");
1377 if (!scanf("%d", &user_id)) {
1378 printf("Invalid user id\n");
1379 spdk_opal_dev_destruct(iter->opal_dev);
1380 return;
1381 }
1382
1383 printf("Please input password:");
1384 while ((ch = getchar()) != '\n' && ch != EOF);
1385 passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1386 printf("\n");
1387 if (passwd_p) {
1388 printf("Specify locking range id:\n");
1389 if (!scanf("%d", &locking_range_id)) {
1390 printf("Invalid locking range id\n");
1391 spdk_opal_dev_destruct(iter->opal_dev);
1392 return;
1393 }
1394
1395 opal_locking_usage();
1396 if (!scanf("%d", &state)) {
1397 printf("Invalid option\n");
1398 }
1399 switch (state) {
1400 case 1:
1401 state_flag = OPAL_RWLOCK;
1402 break;
1403 case 2:
1404 state_flag = OPAL_READONLY;
1405 break;
1406 case 3:
1407 state_flag = OPAL_READWRITE;
1408 break;
1409 default:
1410 printf("Invalid options\n");
1411 spdk_opal_dev_destruct(iter->opal_dev);
1412 return;
1413 }
1414 while (getchar() != '\n');
1415
1416 ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, user_id, state_flag,
1417 locking_range_id, passwd_p);
1418 if (ret) {
1419 printf("lock/unlock range failure: %d\n", ret);
1420 spdk_opal_dev_destruct(iter->opal_dev);
1421 return;
1422 }
1423 printf("...\n...\nLock/unlock range Success\n");
1424 } else {
1425 printf("Input password invalid. lock/unlock range failure\n");
1426 }
1427 spdk_opal_dev_destruct(iter->opal_dev);
1428 } else {
1429 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1430 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1431 }
1432}
1433
1434static void
1435opal_revert_tper(struct dev *iter)
1436{
1437 char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1438 char *passwd_p;
1439 int ret;
1440 int ch;
1441
1442 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1443 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1444 if (iter->opal_dev == NULL) {
1445 return;
1446 }
1447 printf("Please be noted this operation will erase ALL DATA on this drive\n");
1448 printf("Please don't ternminate this excecution. Otherwise undefined error may occur\n");
1449 printf("Please input password for revert TPer:");
1450 while ((ch = getchar()) != '\n' && ch != EOF);
1451 passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1452 printf("\n...\n");
1453 if (passwd_p) {
1454 ret = spdk_opal_cmd_revert_tper(iter->opal_dev, passwd_p);
1455 if (ret) {
1456 printf("Revert TPer failure: %d\n", ret);
1457 spdk_opal_dev_destruct(iter->opal_dev);
1458 return;
1459 }
1460 printf("...\nRevert TPer Success\n");
1461 } else {
1462 printf("Input password invalid. Revert TPer failure\n");
1463 }
1464 spdk_opal_dev_destruct(iter->opal_dev);
1465 } else {
1466 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1467 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1468 }
1469}
1470
1471static void
1472opal_erase_locking_range(struct dev *iter)
1473{
1474 char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1475 char *passwd_p;
1476 int ret;
1477 int ch;
1478 int locking_range_id;
1479
1480 if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1481 iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1482 if (iter->opal_dev == NULL) {
1483 return;
1484 }
1485 printf("Please be noted this operation will erase ALL DATA on this range\n");
1486 printf("Please input password for erase locking range:");
1487 while ((ch = getchar()) != '\n' && ch != EOF);
1488 passwd_p = get_line(passwd, SPDK_OPAL_MAX_PASSWORD_SIZE, stdin, true);
1489 if (passwd_p) {
1490 printf("\nSpecify locking range id:\n");
1491 if (!scanf("%d", &locking_range_id)) {
1492 printf("Invalid locking range id\n");
1493 spdk_opal_dev_destruct(iter->opal_dev);
1494 return;
1495 }
1496 printf("\n...\n");
1497 ret = spdk_opal_cmd_secure_erase_locking_range(iter->opal_dev, OPAL_ADMIN1, locking_range_id,
1498 passwd_p);
1499 if (ret) {
1500 printf("Erase locking range failure: %d\n", ret);
1501 spdk_opal_dev_destruct(iter->opal_dev);
1502 return;
1503 }
1504 printf("...\nErase locking range Success\n");
1505 } else {
1506 printf("Input password invalid. Erase locking range failure\n");
1507 }
1508 spdk_opal_dev_destruct(iter->opal_dev);
9f95a23c
TL
1509 } else {
1510 printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
1511 iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
1512 }
1513}
1514
1515static void
1516test_opal(void)
1517{
1518 int exit_flag = false;
1519 struct dev *ctrlr;
1520
1521 ctrlr = get_controller();
1522 if (ctrlr == NULL) {
1523 printf("Invalid controller PCI Address.\n");
1524 return;
1525 }
1526
1527 opal_usage();
1528 while (!exit_flag) {
1529 int cmd;
1530 if (!scanf("%d", &cmd)) {
f67539c2 1531 printf("Invalid Command: command must be number 0-9\n");
9f95a23c
TL
1532 while (getchar() != '\n');
1533 opal_usage();
1534 continue;
1535 }
1536
1537 switch (cmd) {
1538 case 0:
1539 exit_flag = true;
1540 continue;
1541 case 1:
1542 opal_scan(ctrlr);
1543 break;
1544 case 2:
f67539c2 1545 opal_init(ctrlr); /* Take ownership, Activate Locking SP */
9f95a23c
TL
1546 break;
1547 case 3:
1548 opal_revert_tper(ctrlr);
1549 break;
f67539c2
TL
1550 case 4:
1551 opal_setup_lockingrange(ctrlr);
1552 break;
1553 case 5:
1554 opal_list_locking_ranges(ctrlr);
1555 break;
1556 case 6:
1557 opal_new_user_enable(ctrlr);
1558 break;
1559 case 7:
1560 opal_change_password(ctrlr);
1561 break;
1562 case 8:
1563 opal_add_user_to_locking_range(ctrlr);
1564 break;
1565 case 9:
1566 opal_user_lock_unlock_range(ctrlr);
1567 break;
1568 case 10:
1569 opal_erase_locking_range(ctrlr);
1570 break;
9f95a23c
TL
1571
1572 default:
1573 printf("Invalid option\n");
1574 }
1575
f67539c2 1576 printf("\npress Enter to display Opal cmd menu ...\n");
9f95a23c
TL
1577 while (getchar() != '\n');
1578 opal_usage();
1579 }
1580}
1581
11fdf7f2
TL
1582static void
1583args_usage(const char *program_name)
1584{
1585 printf("%s [options]", program_name);
1586 printf("\n");
1587 printf("options:\n");
1588 printf(" -i shared memory group ID\n");
1589}
1590
1591static int
1592parse_args(int argc, char **argv)
1593{
1594 int op;
1595
1596 while ((op = getopt(argc, argv, "i:")) != -1) {
1597 switch (op) {
1598 case 'i':
9f95a23c
TL
1599 g_shm_id = spdk_strtol(optarg, 10);
1600 if (g_shm_id < 0) {
1601 fprintf(stderr, "Invalid shared memory ID\n");
1602 return g_shm_id;
1603 }
11fdf7f2
TL
1604 break;
1605 default:
1606 args_usage(argv[0]);
1607 return 1;
1608 }
1609 }
1610
1611 return 0;
7c673cae
FG
1612}
1613
1614int main(int argc, char **argv)
1615{
11fdf7f2 1616 int i, rc;
7c673cae
FG
1617 struct spdk_env_opts opts;
1618
11fdf7f2
TL
1619 rc = parse_args(argc, argv);
1620 if (rc != 0) {
1621 return rc;
1622 }
1623
7c673cae
FG
1624 spdk_env_opts_init(&opts);
1625 opts.name = "nvme_manage";
1626 opts.core_mask = "0x1";
11fdf7f2
TL
1627 opts.shm_id = g_shm_id;
1628 if (spdk_env_init(&opts) < 0) {
1629 fprintf(stderr, "Unable to initialize SPDK env\n");
1630 return 1;
1631 }
7c673cae
FG
1632
1633 if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) {
1634 fprintf(stderr, "spdk_nvme_probe() failed\n");
1635 return 1;
1636 }
1637
1638 qsort(devs, num_devs, sizeof(devs[0]), cmp_devs);
1639
1640 usage();
1641
1642 while (1) {
1643 int cmd;
1644 bool exit_flag = false;
1645
1646 if (!scanf("%d", &cmd)) {
11fdf7f2 1647 printf("Invalid Command: command must be number 1-8\n");
7c673cae 1648 while (getchar() != '\n');
11fdf7f2
TL
1649 usage();
1650 continue;
7c673cae
FG
1651 }
1652 switch (cmd) {
1653 case 1:
1654 display_controller_list();
1655 break;
1656 case 2:
1657 add_ns();
1658 break;
1659 case 3:
1660 delete_ns();
1661 break;
1662 case 4:
1663 attach_and_detach_ns(SPDK_NVME_NS_CTRLR_ATTACH);
1664 break;
1665 case 5:
1666 attach_and_detach_ns(SPDK_NVME_NS_CTRLR_DETACH);
1667 break;
1668 case 6:
1669 format_nvm();
1670 break;
1671 case 7:
1672 update_firmware_image();
1673 break;
1674 case 8:
9f95a23c
TL
1675 test_opal();
1676 break;
1677 case 9:
7c673cae
FG
1678 exit_flag = true;
1679 break;
1680 default:
1681 printf("Invalid Command\n");
1682 break;
1683 }
1684
11fdf7f2 1685 if (exit_flag) {
7c673cae 1686 break;
11fdf7f2 1687 }
7c673cae
FG
1688
1689 while (getchar() != '\n');
1690 printf("press Enter to display cmd menu ...\n");
1691 while (getchar() != '\n');
1692 usage();
1693 }
1694
1695 printf("Cleaning up...\n");
1696
1697 for (i = 0; i < num_devs; i++) {
1698 struct dev *dev = &devs[i];
1699 spdk_nvme_detach(dev->ctrlr);
1700 }
1701
1702 return 0;
1703}