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