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