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