xref: /spdk/examples/nvme/nvme_manage/nvme_manage.c (revision cc6920a4763d4b9a43aa40583c8397d8f14fa100)
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 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk/nvme.h"
37 #include "spdk/env.h"
38 #include "spdk/string.h"
39 #include "spdk/util.h"
40 #include "spdk/opal.h"
41 
42 #define MAX_DEVS 64
43 
44 struct dev {
45 	struct spdk_pci_addr			pci_addr;
46 	struct spdk_nvme_ctrlr			*ctrlr;
47 	const struct spdk_nvme_ctrlr_data	*cdata;
48 	struct spdk_nvme_ns_data		*common_ns_data;
49 	int					outstanding_admin_cmds;
50 	struct spdk_opal_dev			*opal_dev;
51 };
52 
53 static struct dev devs[MAX_DEVS];
54 static int num_devs = 0;
55 static int g_shm_id = -1;
56 
57 #define foreach_dev(iter) \
58 	for (iter = devs; iter - devs < num_devs; iter++)
59 
60 enum controller_display_model {
61 	CONTROLLER_DISPLAY_ALL			= 0x0,
62 	CONTROLLER_DISPLAY_SIMPLISTIC		= 0x1,
63 };
64 
65 static int
66 cmp_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 
73 static bool
74 probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
75 	 struct spdk_nvme_ctrlr_opts *opts)
76 {
77 	return true;
78 }
79 
80 static void
81 identify_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. */
87 		spdk_dma_free(dev->common_ns_data);
88 		dev->common_ns_data = NULL;
89 	}
90 
91 	dev->outstanding_admin_cmds--;
92 }
93 
94 static void
95 attach_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 
109 	dev->common_ns_data = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ns_data), 4096, NULL);
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;
118 	cmd.cdw10_bits.identify.cns = 0; /* CNS = 0 (Identify Namespace) */
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--;
125 		spdk_dma_free(dev->common_ns_data);
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 
134 static 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");
145 	printf("\t[8: opal]\n");
146 	printf("\t[9: quit]\n");
147 }
148 
149 static void
150 display_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 
180 static void
181 display_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");
201 	if (nsdata->fpi.fpi_supported && nsdata->fpi.percentage_remaining) {
202 		printf("Formatted Percentage:	%d%%\n", 100 - nsdata->fpi.percentage_remaining);
203 	}
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 
223 static void
224 display_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];
229 	uint32_t				nsid;
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");
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);
274 		display_namespace(ns);
275 	}
276 }
277 
278 static void
279 display_controller_list(void)
280 {
281 	struct dev			*iter;
282 
283 	foreach_dev(iter) {
284 		display_controller(iter, CONTROLLER_DISPLAY_ALL);
285 	}
286 }
287 
288 static char *
289 get_line(char *buf, int buf_size, FILE *f, bool secret)
290 {
291 	char *ch;
292 	size_t len;
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 	}
309 
310 	ch = fgets(buf, buf_size, f);
311 	if (ch == NULL) {
312 		return NULL;
313 	}
314 
315 	if (secret) {
316 		ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, &default_attr); /* restore default confing */
317 		if (ret) {
318 			return NULL;
319 		}
320 	}
321 
322 	len = strlen(buf);
323 	if (len > 0 && buf[len - 1] == '\n') {
324 		buf[len - 1] = '\0';
325 	}
326 	return buf;
327 }
328 
329 static struct dev *
330 get_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 
344 	printf("Please Input PCI Address(domain:bus:dev.func):\n");
345 
346 	while ((ch = getchar()) != '\n' && ch != EOF);
347 	p = get_line(address, 64, stdin, false);
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 
368 static int
369 get_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 
390 static void
391 identify_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 
398 static uint32_t
399 get_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 
406 	ns_list = spdk_dma_zmalloc(sizeof(*ns_list), 4096, NULL);
407 	if (ns_list == NULL) {
408 		printf("Allocation error\n");
409 		return 0;
410 	}
411 
412 	cmd.opc = SPDK_NVME_OPC_IDENTIFY;
413 	cmd.cdw10_bits.identify.cns = SPDK_NVME_IDENTIFY_ALLOCATED_NS_LIST;
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");
420 		spdk_dma_free(ns_list);
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 
436 	spdk_dma_free(ns_list);
437 
438 	printf("Please Input Namespace ID:\n");
439 	if (!scanf("%u", &nsid)) {
440 		printf("Invalid Namespace ID\n");
441 		nsid = 0;
442 	}
443 
444 	return nsid;
445 }
446 
447 static void
448 ns_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 
453 	ctrlr_list = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ctrlr_list),
454 				      4096, NULL);
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 
473 	spdk_dma_free(ctrlr_list);
474 }
475 
476 static void
477 ns_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 
483 	ndata = spdk_dma_zmalloc(sizeof(struct spdk_nvme_ns_data), 4096, NULL);
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 
504 	spdk_dma_free(ndata);
505 }
506 
507 static void
508 ns_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 
519 static void
520 nvme_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 
537 static void
538 attach_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 
563 static void
564 add_ns(void)
565 {
566 	uint64_t	ns_size		= 0;
567 	uint64_t	ns_capacity	= 0;
568 	int		ns_lbasize;
569 	int		ns_dps_type	= 0;
570 	int		ns_dps_location	= 0;
571 	int		ns_nmic		= 0;
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 
596 	printf("Please Input Namespace Size (in LBAs):\n");
597 	if (!scanf("%" SCNu64, &ns_size)) {
598 		printf("Invalid Namespace Size\n");
599 		while (getchar() != '\n');
600 		return;
601 	}
602 
603 	printf("Please Input Namespace Capacity (in LBAs):\n");
604 	if (!scanf("%" SCNu64, &ns_capacity)) {
605 		printf("Invalid Namespace Capacity\n");
606 		while (getchar() != '\n');
607 		return;
608 	}
609 
610 	printf("Please Input Data Protection Type (0 - 3):\n");
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) {
618 		printf("Please Input Data Protection Location (1: Head; 0: Tail):\n");
619 		if (!scanf("%d", &ns_dps_location)) {
620 			printf("Invalid Data Protection Location\n");
621 			while (getchar() != '\n');
622 			return;
623 		}
624 	}
625 
626 	printf("Please Input Multi-path IO and Sharing Capabilities (1: Share; 0: Private):\n");
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 
637 static void
638 delete_ns(void)
639 {
640 	int					ns_id;
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 
654 	printf("Please Input Namespace ID:\n");
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 
664 static void
665 format_nvm(void)
666 {
667 	int					ns_id;
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 {
696 		printf("Please Input Namespace ID (1 - %d):\n", cdata->nn);
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 
713 	printf("Please Input Secure Erase Setting:\n");
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) {
732 		printf("Please Input Protection Information:\n");
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) {
744 			printf("Please Input Protection Information Location:\n");
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 
756 		printf("Please Input Metadata Setting:\n");
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 
790 static void
791 update_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;
802 	enum spdk_nvme_fw_commit_action		commit_action;
803 	struct spdk_nvme_status			status;
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 
820 	if (get_line(path, sizeof(path), stdin, false) == NULL) {
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 
846 	fw_image = spdk_dma_zmalloc(size, 4096, NULL);
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);
856 		spdk_dma_free(fw_image);
857 		return;
858 	}
859 	close(fd);
860 
861 	printf("Please Input Slot(0 - 7):\n");
862 	if (!scanf("%d", &slot)) {
863 		printf("Invalid Slot\n");
864 		spdk_dma_free(fw_image);
865 		while (getchar() != '\n');
866 		return;
867 	}
868 
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) {
875 		printf("spdk_nvme_ctrlr_update_firmware failed\n");
876 	} else {
877 		printf("spdk_nvme_ctrlr_update_firmware success\n");
878 	}
879 	spdk_dma_free(fw_image);
880 }
881 
882 static void
883 opal_dump_info(struct spdk_opal_d0_features_info *feat)
884 {
885 	if (feat->tper.hdr.code) {
886 		printf("\nOpal TPer feature:\n");
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"));
893 		printf("\n");
894 	}
895 
896 	if (feat->locking.hdr.code) {
897 		printf("Opal Locking feature:\n");
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"));
901 
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"));
905 		printf("\n");
906 	}
907 
908 	if (feat->geo.hdr.code) {
909 		printf("Opal Geometry feature:\n");
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 = %" PRIu64 "\n", from_be64(&feat->geo.lowest_aligned_lba));
913 		printf("\n");
914 	}
915 
916 	if (feat->single_user.hdr.code) {
917 		printf("Opal Single User Mode feature:\n");
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));
922 		printf("\n");
923 	}
924 
925 	if (feat->datastore.hdr.code) {
926 		printf("Opal DataStore feature:\n");
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));
930 		printf("\n");
931 	}
932 
933 	if (feat->v100.hdr.code) {
934 		printf("Opal V100 feature:\n");
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"));
938 		printf("\n");
939 	}
940 
941 	if (feat->v200.hdr.code) {
942 		printf("Opal V200 feature:\n");
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");
950 	}
951 }
952 
953 static void
954 opal_usage(void)
955 {
956 	printf("Opal General Usage:\n");
957 	printf("\n");
958 	printf("\t[1: scan device]\n");
959 	printf("\t[2: init - take ownership and activate locking]\n");
960 	printf("\t[3: revert tper]\n");
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");
968 	printf("\t[0: quit]\n");
969 }
970 
971 static void
972 opal_scan(struct dev *iter)
973 {
974 	while (getchar() != '\n');
975 	if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
976 		iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
977 		if (iter->opal_dev == NULL) {
978 			return;
979 		}
980 
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);
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 
993 static void
994 opal_init(struct dev *iter)
995 {
996 	char new_passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
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) {
1002 		iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1003 		if (iter->opal_dev == NULL) {
1004 			return;
1005 		}
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 
1035 static void
1036 opal_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 
1045 static void
1046 opal_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: %" PRIu64 "\n", info->range_start);
1108 			printf("range length: %" PRIu64 "\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 
1125 static void
1126 opal_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);
1157 				if (ret) {
1158 					printf("Get locking range info failure: %d\n", ret);
1159 					spdk_opal_dev_destruct(iter->opal_dev);
1160 					return;
1161 				}
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: %" PRIu64 "\t", info->range_start);
1172 				printf("range length: %" PRIu64 "\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");
1178 			}
1179 		} else {
1180 			printf("Input password invalid. List locking ranges failure\n");
1181 		}
1182 		spdk_opal_dev_destruct(iter->opal_dev);
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 
1189 static void
1190 opal_new_user_enable(struct dev *iter)
1191 {
1192 	int user_id;
1193 	char passwd[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1194 	char *passwd_p;
1195 	char user_pw[SPDK_OPAL_MAX_PASSWORD_SIZE] = {0};
1196 	char *user_pw_p;
1197 	int ret;
1198 	int ch;
1199 
1200 	if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
1201 		iter->opal_dev = spdk_opal_dev_construct(iter->ctrlr);
1202 		if (iter->opal_dev == NULL) {
1203 			return;
1204 		}
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:");
1224 			while ((ch = getchar()) != '\n' && ch != EOF);
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 
1250 static void
1251 opal_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;
1284 			}
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");
1296 		}
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 
1304 static void
1305 opal_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 
1359 static void
1360 opal_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 
1434 static void
1435 opal_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 terminate this execution. 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 
1471 static void
1472 opal_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);
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 
1515 static void
1516 test_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)) {
1531 			printf("Invalid Command: command must be number 0-9\n");
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:
1545 			opal_init(ctrlr);   /* Take ownership, Activate Locking SP */
1546 			break;
1547 		case 3:
1548 			opal_revert_tper(ctrlr);
1549 			break;
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;
1571 
1572 		default:
1573 			printf("Invalid option\n");
1574 		}
1575 
1576 		printf("\npress Enter to display Opal cmd menu ...\n");
1577 		while (getchar() != '\n');
1578 		opal_usage();
1579 	}
1580 }
1581 
1582 static void
1583 args_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 
1591 static int
1592 parse_args(int argc, char **argv)
1593 {
1594 	int op;
1595 
1596 	while ((op = getopt(argc, argv, "i:")) != -1) {
1597 		switch (op) {
1598 		case 'i':
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 			}
1604 			break;
1605 		default:
1606 			args_usage(argv[0]);
1607 			return 1;
1608 		}
1609 	}
1610 
1611 	return 0;
1612 }
1613 
1614 int main(int argc, char **argv)
1615 {
1616 	int			rc;
1617 	struct spdk_env_opts	opts;
1618 	struct dev		*dev;
1619 	struct spdk_nvme_detach_ctx *detach_ctx = NULL;
1620 
1621 	rc = parse_args(argc, argv);
1622 	if (rc != 0) {
1623 		return rc;
1624 	}
1625 
1626 	spdk_env_opts_init(&opts);
1627 	opts.name = "nvme_manage";
1628 	opts.core_mask = "0x1";
1629 	opts.shm_id = g_shm_id;
1630 	if (spdk_env_init(&opts) < 0) {
1631 		fprintf(stderr, "Unable to initialize SPDK env\n");
1632 		return 1;
1633 	}
1634 
1635 	if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) {
1636 		fprintf(stderr, "spdk_nvme_probe() failed\n");
1637 		return 1;
1638 	}
1639 
1640 	qsort(devs, num_devs, sizeof(devs[0]), cmp_devs);
1641 
1642 	usage();
1643 
1644 	while (1) {
1645 		int cmd;
1646 		bool exit_flag = false;
1647 
1648 		if (!scanf("%d", &cmd)) {
1649 			printf("Invalid Command: command must be number 1-8\n");
1650 			while (getchar() != '\n');
1651 			usage();
1652 			continue;
1653 		}
1654 		switch (cmd) {
1655 		case 1:
1656 			display_controller_list();
1657 			break;
1658 		case 2:
1659 			add_ns();
1660 			break;
1661 		case 3:
1662 			delete_ns();
1663 			break;
1664 		case 4:
1665 			attach_and_detach_ns(SPDK_NVME_NS_CTRLR_ATTACH);
1666 			break;
1667 		case 5:
1668 			attach_and_detach_ns(SPDK_NVME_NS_CTRLR_DETACH);
1669 			break;
1670 		case 6:
1671 			format_nvm();
1672 			break;
1673 		case 7:
1674 			update_firmware_image();
1675 			break;
1676 		case 8:
1677 			test_opal();
1678 			break;
1679 		case 9:
1680 			exit_flag = true;
1681 			break;
1682 		default:
1683 			printf("Invalid Command\n");
1684 			break;
1685 		}
1686 
1687 		if (exit_flag) {
1688 			break;
1689 		}
1690 
1691 		while (getchar() != '\n');
1692 		printf("press Enter to display cmd menu ...\n");
1693 		while (getchar() != '\n');
1694 		usage();
1695 	}
1696 
1697 	printf("Cleaning up...\n");
1698 
1699 	foreach_dev(dev) {
1700 		spdk_nvme_detach_async(dev->ctrlr, &detach_ctx);
1701 	}
1702 
1703 	if (detach_ctx) {
1704 		spdk_nvme_detach_poll(detach_ctx);
1705 	}
1706 
1707 	return 0;
1708 }
1709