Bug Summary

File:.build-ci/../plugins/sandisk/sandisk-nvme.c
Warning:line 673, column 2
Value stored to 'ret' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name sandisk-nvme.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -std=gnu99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-06-24-175442-590-1 -x c ../plugins/sandisk/sandisk-nvme.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2025 Sandisk Corporation or its affiliates.
4 *
5 * Author: Jeff Lien <jeff.lien@sandisk.com>
6 * Brandon Paupore <brandon.paupore@sandisk.com>
7 */
8#include <stdio.h>
9#include <string.h>
10#include <stdlib.h>
11#include <inttypes.h>
12#include <errno(*__errno_location ()).h>
13#include <limits.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include <libnvme.h>
18
19#include "common.h"
20#include "nvme-cmds.h"
21#include "nvme-print.h"
22#include "nvme.h"
23#include "plugin.h"
24#include "util/cleanup.h"
25#include "util/types.h"
26
27#define CREATE_CMD
28#include "sandisk-nvme.h"
29#include "sandisk-utils.h"
30#include "plugins/wdc/wdc-nvme-cmds.h"
31
32static __u8 ocp_C2_guid[SNDK_GUID_LENGTH16] = {
33 0x6D, 0x79, 0x9A, 0x76, 0xB4, 0xDA, 0xF6, 0xA3,
34 0xE2, 0x4D, 0xB2, 0x8A, 0xAC, 0xF3, 0x1C, 0xD1
35};
36
37static int sndk_do_cap_telemetry_log(struct libnvme_global_ctx *ctx,
38 struct libnvme_transport_handle *hdl,
39 const char *file, __u32 bs, int type,
40 int data_area)
41{
42 struct nvme_telemetry_log *log;
43 size_t full_size = 0;
44 int err = 0, output;
45 __u32 host_gen = 1;
46 int ctrl_init = 0;
47 __u8 *data_ptr = NULL((void*)0);
48 int data_written = 0, data_remaining = 0;
49 struct nvme_id_ctrl ctrl;
50 __u64 capabilities = 0;
51 bool_Bool host_behavior_changed = false0;
52
53 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
54 err = nvme_identify_ctrl(hdl, &ctrl);
55 if (err) {
56 fprintf(stderrstderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err);
57 return err;
58 }
59
60 if (!(ctrl.lpa & 0x8)) {
61 fprintf(stderrstderr, "Telemetry log pages not supported by device\n");
62 return -EINVAL22;
63 }
64
65 err = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
66 if (err)
67 return err;
68 capabilities = sndk_get_drive_capabilities(ctx, hdl);
69
70 if (data_area == 4) {
71 if (!(ctrl.lpa & 0x40)) {
72 fprintf(stderrstderr, "%s: Telemetry data area 4 not supported by device\n",
73 __func__);
74 return -EINVAL22;
75 }
76
77 err = libnvme_set_etdas(hdl, &host_behavior_changed);
78 if (err) {
79 fprintf(stderrstderr, "%s: Failed to set ETDAS bit\n", __func__);
80 return err;
81 }
82 }
83
84 if (type == SNDK_TELEMETRY_TYPE_HOST0x1) {
85 host_gen = 1;
86 ctrl_init = 0;
87 } else if (type == SNDK_TELEMETRY_TYPE_CONTROLLER0x2) {
88 if (capabilities & SNDK_DRIVE_CAP_INTERNAL_LOG0x0000000000000002) {
89 err = sndk_check_ctrl_telemetry_option_disabled(hdl);
90 if (err)
91 return err;
92 }
93 host_gen = 0;
94 ctrl_init = 1;
95 } else if (type == SNDK_TELEMETRY_TYPE_BOTH0x3) {
96 fprintf(stderrstderr,
97 "%s: BOTH type should be handled by sndk_do_cap_both_telemetry_log\n",
98 __func__);
99 return -EINVAL22;
100 } else {
101 fprintf(stderrstderr, "%s: Invalid type parameter; type = %d\n", __func__, type);
102 return -EINVAL22;
103 }
104
105 if (!file) {
106 fprintf(stderrstderr, "%s: Please provide an output file!\n", __func__);
107 return -EINVAL22;
108 }
109
110 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
111 if (output < 0) {
112 fprintf(stderrstderr, "%s: Failed to open output file %s: %s!\n",
113 __func__, file, libnvme_strerror(errno(*__errno_location ())));
114 return output;
115 }
116
117 if (ctrl_init)
118 err = libnvme_get_ctrl_telemetry(hdl, true1, &log,
119 data_area, &full_size);
120 else if (host_gen)
121 err = libnvme_get_new_host_telemetry(hdl, &log,
122 data_area, &full_size);
123 else
124 err = libnvme_get_host_telemetry(hdl, &log, data_area,
125 &full_size);
126
127 if (err < 0) {
128 perror("get-telemetry-log");
129 goto close_output;
130 } else if (err > 0) {
131 nvme_show_status(err);
132 fprintf(stderrstderr, "%s: Failed to acquire telemetry header!\n", __func__);
133 goto close_output;
134 }
135
136 /*
137 *Continuously pull data until the offset hits the end of the last
138 *block.
139 */
140 data_written = 0;
141 data_remaining = full_size;
142 data_ptr = (__u8 *)log;
143
144 while (data_remaining) {
145 data_written = write(output, data_ptr, data_remaining);
146
147 if (data_written < 0) {
148 data_remaining = data_written;
149 break;
150 } else if (data_written <= data_remaining) {
151 data_remaining -= data_written;
152 data_ptr += data_written;
153 } else {
154 /* Unexpected overwrite */
155 fprintf(stderrstderr, "Failure: Unexpected telemetry log overwrite\n" \
156 "- data_remaining = 0x%x, data_written = 0x%x\n",
157 data_remaining, data_written);
158 break;
159 }
160 }
161
162 if (fsync(output) < 0) {
163 fprintf(stderrstderr, "ERROR: %s: fsync: %s\n", __func__, libnvme_strerror(errno(*__errno_location ())));
164 err = -1;
165 }
166
167 if (host_behavior_changed) {
168 host_behavior_changed = false0;
169 err = libnvme_clear_etdas(hdl, &host_behavior_changed);
170 if (err) {
171 fprintf(stderrstderr, "%s: Failed to clear ETDAS bit\n", __func__);
172 return err;
173 }
174 }
175
176 free(log);
177close_output:
178 close(output);
179 return err;
180}
181
182static int sndk_do_cap_both_telemetry_log(struct libnvme_global_ctx *ctx,
183 struct libnvme_transport_handle *hdl,
184 const char *tar_file, __u32 bs,
185 int data_area)
186{
187 char host_file[PATH_MAX4096] = {0};
188 char controller_file[PATH_MAX4096] = {0};
189 char tar_cmd[PATH_MAX4096 * 3] = {0};
190 char *base_name;
191 int ret = 0;
192
193 base_name = strdup(tar_file);
194 if (!base_name) {
195 fprintf(stderrstderr, "%s: Memory allocation failed\n", __func__);
196 return -ENOMEM12;
197 }
198
199 /* Remove .tar extension if present */
200 char *tar_ext = strstr(base_name, ".tar");
201
202 if (tar_ext)
203 *tar_ext = '\0';
204
205 /* Create temporary files for host and controller telemetry */
206 snprintf(host_file, PATH_MAX4096, "%s_host_telemetry.bin", base_name);
207 snprintf(controller_file, PATH_MAX4096, "%s_controller_telemetry.bin",
208 base_name);
209
210 fprintf(stderrstderr, "%s: Capturing HOST telemetry to %s\n", __func__,
211 host_file);
212 ret = sndk_do_cap_telemetry_log(ctx, hdl, host_file, bs,
213 SNDK_TELEMETRY_TYPE_HOST0x1, data_area);
214 if (ret) {
215 fprintf(stderrstderr, "%s: Failed to capture HOST telemetry: %d\n",
216 __func__, ret);
217 goto cleanup;
218 }
219
220 fprintf(stderrstderr, "%s: Capturing CONTROLLER telemetry to %s\n", __func__,
221 controller_file);
222 ret = sndk_do_cap_telemetry_log(ctx, hdl, controller_file, bs,
223 SNDK_TELEMETRY_TYPE_CONTROLLER0x2,
224 data_area);
225 if (ret) {
226 fprintf(stderrstderr,
227 "%s: Failed to capture CONTROLLER telemetry: %d\n",
228 __func__, ret);
229 goto cleanup_host;
230 }
231
232 /* Create tar file containing both telemetry files */
233 fprintf(stderrstderr, "%s: Creating tar file %s\n", __func__, tar_file);
234 snprintf(tar_cmd, sizeof(tar_cmd), "tar -cf \"%s\" \"%s\" \"%s\"",
235 tar_file, host_file, controller_file);
236
237 ret = system(tar_cmd);
238 if (ret) {
239 fprintf(stderrstderr, "%s: Failed to create tar file: %s\n",
240 __func__, tar_file);
241 ret = -1;
242 } else {
243 fprintf(stderrstderr, "%s: Successfully created tar file: %s\n",
244 __func__, tar_file);
245 ret = 0;
246 }
247
248 /* Clean up temporary files */
249 unlink(controller_file);
250cleanup_host:
251 unlink(host_file);
252cleanup:
253 free(base_name);
254 return ret;
255}
256
257static __u32 sndk_dump_udui_data(struct libnvme_transport_handle *hdl,
258 __u32 dataLen, __u32 offset, __u8 *dump_data)
259{
260 int ret;
261 struct libnvme_passthru_cmd admin_cmd;
262
263 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
264 admin_cmd.opcode = SNDK_NVME_CAP_UDUI_OPCODE0xFA;
265 admin_cmd.nsid = 0xFFFFFFFF;
266 admin_cmd.addr = (__u64)(uintptr_t)dump_data;
267 admin_cmd.data_len = dataLen;
268 admin_cmd.cdw10 = ((dataLen >> 2) - 1);
269 admin_cmd.cdw12 = offset;
270 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
271 if (ret) {
272 fprintf(stderrstderr, "ERROR: SNDK: reading DUI data failed\n");
273 nvme_show_status(ret);
274 }
275
276 return ret;
277}
278
279static int sndk_do_cap_udui(struct libnvme_transport_handle *hdl, char *file,
280 __u32 xfer_size, int verbose)
281{
282 int ret = 0;
283 int output;
284 ssize_t written = 0;
285 struct nvme_telemetry_log *log;
286 __u32 udui_log_hdr_size = sizeof(struct nvme_telemetry_log);
287 __u32 chunk_size = xfer_size;
288 __u64 total_size;
289 __u64 offset = 0;
290
291 log = (struct nvme_telemetry_log *)malloc(udui_log_hdr_size);
292 if (!log) {
293 fprintf(stderrstderr,
294 "%s: ERROR: log header malloc failed : status %s, size 0x%x\n",
295 __func__, libnvme_strerror(errno(*__errno_location ())), udui_log_hdr_size);
296 return -1;
297 }
298 memset(log, 0, udui_log_hdr_size);
299
300 /* get the udui telemetry and log headers */
301 ret = sndk_dump_udui_data(hdl, udui_log_hdr_size, 0, (__u8 *)log);
302 if (ret) {
303 fprintf(stderrstderr, "%s: ERROR: SNDK: Get UDUI header failed\n", __func__);
304 nvme_show_status(ret);
305 goto out;
306 }
307
308 total_size = (le32_to_cpu(log->dalb4) + 1) * 512;
309
310 log = (struct nvme_telemetry_log *)realloc(log, chunk_size);
311
312 output = nvme_open_rawdata(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((file), (01 | 0100 | 01000), 0666);
313 if (output < 0) {
314 fprintf(stderrstderr, "%s: Failed to open output file %s: %s!\n", __func__, file,
315 libnvme_strerror(errno(*__errno_location ())));
316 goto out;
317 }
318
319 while (offset < total_size) {
320 if (chunk_size > total_size - offset)
321 chunk_size = total_size - offset;
322 ret = sndk_dump_udui_data(hdl, chunk_size, offset,
323 ((__u8 *)log));
324 if (ret) {
325 fprintf(stderrstderr,
326 "%s: ERROR: Get UDUI failed, offset = 0x%"PRIx64"l" "x"", size = %u\n",
327 __func__, (uint64_t)offset, chunk_size);
328 break;
329 }
330
331 /* write the dump data into the file */
332 written = write(output, (void *)log, chunk_size);
333 if (written != chunk_size) {
334 fprintf(stderrstderr,
335 "%s: ERROR: SNDK: Failed to flush DUI data to file!\n" \
336 "- written = %zd, offset = 0x%"PRIx64"l" "x"", chunk_size = %u\n",
337 __func__, written, (uint64_t)offset, chunk_size);
338 ret = errno(*__errno_location ());
339 break;
340 }
341
342 offset += chunk_size;
343 }
344
345 close(output);
346 nvme_show_status(ret);
347 if (verbose)
348 fprintf(stderrstderr,
349 "INFO: SNDK: Capture Device Unit Info log length = 0x%"PRIx64"l" "x""\n",
350 (uint64_t)total_size);
351
352out:
353 free(log);
354 return ret;
355}
356
357static int sndk_get_default_telemetry_da(struct libnvme_transport_handle *hdl,
358 int *data_area)
359{
360 struct nvme_id_ctrl ctrl;
361 int err;
362
363 memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
364 err = nvme_identify_ctrl(hdl, &ctrl);
365 if (err) {
366 fprintf(stderrstderr, "ERROR: SNDK: nvme_identify_ctrl() failed 0x%x\n", err);
367 return err;
368 }
369
370 if (ctrl.lpa & 0x40)
371 *data_area = 4;
372 else
373 *data_area = 3;
374
375 return 0;
376}
377
378static int sndk_vs_internal_fw_log(int argc, char **argv,
379 struct command *command,
380 struct plugin *plugin)
381{
382 const char *desc = "Internal Firmware Log.";
383 const char *file = "Output file pathname.";
384 const char *size = "Data retrieval transfer size.";
385 const char *data_area =
386 "Data area to retrieve up to. Supported for telemetry, see man page for other use cases.";
387 const char *type =
388 "Telemetry type - NONE, HOST, CONTROLLER, or BOTH:\n" \
389 " NONE - Default, capture without using NVMe telemetry.\n" \
390 " HOST - Host-initiated telemetry.\n" \
391 " CONTROLLER - Controller-initiated telemetry.\n" \
392 " BOTH - Both HOST and CONTROLLER telemetry packaged in tar file.";
393 const char *verbose = "Display more debug messages.";
394 const char *file_size =
395 "Output file size. Deprecated, see man page for supported devices.";
396 const char *offset =
397 "Output file data offset. Deprecated, see man page for supported devices.";
398 char f[PATH_MAX4096-4] = {0};
399 char fileSuffix[PATH_MAX4096] = {0};
400 __u32 xfer_size = 0;
401 int telemetry_type = 0, telemetry_data_area = 0;
402 struct SNDK_UtilsTimeInfo timeInfo;
403 __u8 timeStamp[SNDK_MAX_PATH_LEN256];
404 __u64 capabilities = 0;
405 __u32 device_id, read_vendor_id;
406 int ret = -1;
407 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
408 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
409
410 struct config {
411 char *file;
412 __u32 xfer_size;
413 int data_area;
414 __u64 file_size;
415 __u64 offset;
416 char *type;
417 bool_Bool verbose;
418 };
419
420 struct config cfg = {
421 .file = NULL((void*)0),
422 .xfer_size = 0x10000,
423 .data_area = 0,
424 .file_size = 0,
425 .offset = 0,
426 .type = NULL((void*)0),
427 .verbose = false0,
428 };
429
430 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
431 OPT_FILE("output-file", 'O', &cfg.file, file),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
432 OPT_UINT("transfer-size", 's', &cfg.xfer_size, size),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
433 OPT_UINT("data-area", 'd', &cfg.data_area, data_area),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
434 OPT_FILE("type", 't', &cfg.type, type),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
435 OPT_FLAG("verbose", 'V', &cfg.verbose, verbose),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
436 OPT_LONG("file-size", 'f', &cfg.file_size, file_size),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
437 OPT_LONG("offset", 'e', &cfg.offset, offset),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
438 OPT_END())struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"output-file", 'O', "FILE", CFG_STRING, &cfg.file
, 1, file, 0, }, {"transfer-size", 's', "NUM", CFG_POSITIVE, &
cfg.xfer_size, 1, size, 0, }, {"data-area", 'd', "NUM", CFG_POSITIVE
, &cfg.data_area, 1, data_area, 0, }, {"type", 't', "FILE"
, CFG_STRING, &cfg.type, 1, type, 0, }, {"verbose", 'V', (
(void*)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"file-size"
, 'f', "NUM", CFG_LONG, &cfg.file_size, 1, file_size, 0, }
, {"offset", 'e', "NUM", CFG_LONG, &cfg.offset, 1, offset
, 0, }, { ((void*)0) }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
;
439
440 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
441 if (ret)
442 return ret;
443
444 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
445 if (ret || !sndk_check_device(ctx, hdl))
446 goto out;
447
448 if (cfg.xfer_size) {
449 xfer_size = cfg.xfer_size;
450 } else {
451 fprintf(stderrstderr, "ERROR: SNDK: Invalid length\n");
452 goto out;
453 }
454
455 ret = sndk_get_pci_ids(ctx, hdl, &device_id, &read_vendor_id);
456
457 if (cfg.file) {
458 int verify_file;
459
460 /* verify file name and path is valid before getting dump data */
461 verify_file = nvme_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
462 if (verify_file < 0) {
463 fprintf(stderrstderr, "ERROR: SNDK: open: %s\n", libnvme_strerror(errno(*__errno_location ())));
464 goto out;
465 }
466 close(verify_file);
467 remove(cfg.file);
468 strncpy(f, cfg.file, PATH_MAX4096 - 5);
469 } else {
470 sndk_UtilsGetTime(&timeInfo);
471 memset(timeStamp, 0, sizeof(timeStamp));
472 sndk_UtilsSnprintf((char *)timeStamp, SNDK_MAX_PATH_LEN256,
473 "%02u%02u%02u_%02u%02u%02u", timeInfo.year,
474 timeInfo.month, timeInfo.dayOfMonth,
475 timeInfo.hour, timeInfo.minute,
476 timeInfo.second);
477 snprintf(fileSuffix, PATH_MAX4096, "_internal_fw_log_%s", (char *)timeStamp);
478
479 ret = sndk_get_serial_name(hdl, f, PATH_MAX4096-5, fileSuffix);
480 if (ret) {
481 fprintf(stderrstderr, "ERROR: SNDK: failed to generate file name\n");
482 goto out;
483 }
484 }
485
486 if (!cfg.file) {
487 if (strlen(f) > PATH_MAX4096 - 5) {
488 fprintf(stderrstderr, "ERROR: SNDK: file name overflow\n");
489 ret = -1;
490 goto out;
491 }
492 strcat(f, ".bin");
493 }
494 fprintf(stderrstderr, "%s: filename = %s\n", __func__, f);
495
496 if (cfg.data_area) {
497 if (cfg.data_area > 5 || cfg.data_area < 1) {
498 fprintf(stderrstderr, "ERROR: SNDK: Data area must be 1-5\n");
499 ret = -1;
500 goto out;
501 }
502 }
503
504 if (!cfg.type || !strcmp(cfg.type, "NONE") || !strcmp(cfg.type, "none")) {
505 telemetry_type = SNDK_TELEMETRY_TYPE_NONE0x0;
506 telemetry_data_area = 0;
507 } else if (!strcmp(cfg.type, "HOST") || !strcmp(cfg.type, "host")) {
508 telemetry_type = SNDK_TELEMETRY_TYPE_HOST0x1;
509 telemetry_data_area = cfg.data_area;
510 } else if (!strcmp(cfg.type, "CONTROLLER") || !strcmp(cfg.type, "controller")) {
511 telemetry_type = SNDK_TELEMETRY_TYPE_CONTROLLER0x2;
512 telemetry_data_area = cfg.data_area;
513 } else if (!strcmp(cfg.type, "BOTH") || !strcmp(cfg.type, "both")) {
514 telemetry_type = SNDK_TELEMETRY_TYPE_BOTH0x3;
515 telemetry_data_area = cfg.data_area;
516 } else {
517 fprintf(stderrstderr,
518 "ERROR: SNDK: Invalid type - Must be NONE, HOST, CONTROLLER, or BOTH\n");
519 ret = -1;
520 goto out;
521 }
522
523 capabilities = sndk_get_drive_capabilities(ctx, hdl);
524
525 if ((capabilities & SNDK_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000040000000000
| 0x0000000200000000 | 0x0000000400000000)
) &&
526 (telemetry_type != SNDK_TELEMETRY_TYPE_NONE0x0)) {
527 /* If no data area specified, get the default value */
528 if (telemetry_data_area == 0) {
529 if (sndk_get_default_telemetry_da(hdl, &telemetry_data_area)) {
530 fprintf(stderrstderr, "%s: Error determining default telemetry data area\n",
531 __func__);
532 return -EINVAL22;
533 }
534 }
535
536 if (telemetry_type == SNDK_TELEMETRY_TYPE_BOTH0x3) {
537 /* For BOTH type, ensure filename has .tar extension */
538 char tar_file[PATH_MAX4096] = {0};
539
540 if (strstr(f, ".tar") == NULL((void*)0)) {
541 char *bin_ext = strstr(f, ".bin");
542
543 if (bin_ext)
544 *bin_ext = '\0';
545
546 snprintf(tar_file, PATH_MAX4096, "%s.tar", f);
547 } else {
548 snprintf(tar_file, PATH_MAX4096, "%s", f);
549 }
550 ret = sndk_do_cap_both_telemetry_log(ctx, hdl,
551 tar_file, xfer_size,
552 telemetry_data_area);
553 } else {
554 ret = sndk_do_cap_telemetry_log(ctx, hdl, f, xfer_size,
555 telemetry_type, telemetry_data_area);
556 }
557 goto out;
558 }
559
560 if (capabilities & SNDK_DRIVE_CAP_UDUI0x0000040000000000) {
561 if (cfg.data_area) {
562 fprintf(stderrstderr,
563 "ERROR: SNDK: Data area parameter is not supported when type is NONE\n");
564 ret = -1;
565 goto out;
566 }
567 ret = sndk_do_cap_udui(hdl, f, xfer_size, cfg.verbose);
568 goto out;
569 }
570
571 /* Fallback to WDC plugin if otherwise not supported */
572 return run_wdc_vs_internal_fw_log(argc, argv, command, plugin);
573
574out:
575 return ret;
576}
577
578static int sndk_vs_nand_stats(int argc, char **argv,
579 struct command *command,
580 struct plugin *plugin)
581{
582 return run_wdc_vs_nand_stats(argc, argv, command, plugin);
583}
584
585static int sndk_vs_smart_add_log(int argc, char **argv,
586 struct command *command,
587 struct plugin *plugin)
588{
589 return run_wdc_vs_smart_add_log(argc, argv, command, plugin);
590}
591
592static int sndk_clear_pcie_correctable_errors(int argc, char **argv,
593 struct command *command,
594 struct plugin *plugin)
595{
596 return run_wdc_clear_pcie_correctable_errors(argc, argv, command, plugin);
597}
598
599static int sndk_drive_status(int argc, char **argv,
600 struct command *command,
601 struct plugin *plugin)
602{
603 return run_wdc_drive_status(argc, argv, command, plugin);
604}
605
606static int sndk_clear_assert_dump(int argc, char **argv,
607 struct command *command,
608 struct plugin *plugin)
609{
610 return run_wdc_clear_assert_dump(argc, argv, command, plugin);
611}
612
613#define SNDK_NVME_SN861_DRIVE_RESIZE_OPCODE0xD1 0xD1
614#define SNDK_NVME_SN861_DRIVE_RESIZE_BUFFER_SIZE0x1000 0x1000
615
616static int sndk_do_sn861_drive_resize(struct libnvme_transport_handle *hdl,
617 uint64_t new_size,
618 __u64 *result)
619{
620 uint8_t buffer[SNDK_NVME_SN861_DRIVE_RESIZE_BUFFER_SIZE0x1000] = {0};
621 struct libnvme_passthru_cmd admin_cmd;
622 int ret;
623
624 memset(&admin_cmd, 0, sizeof(struct libnvme_passthru_cmd));
625 admin_cmd.opcode = SNDK_NVME_SN861_DRIVE_RESIZE_OPCODE0xD1;
626 admin_cmd.cdw10 = 0x00000040;
627 admin_cmd.cdw12 = 0x00000103;
628 admin_cmd.cdw13 = 0x00000001;
629
630 memcpy(buffer, &new_size, sizeof(new_size));
631 admin_cmd.addr = (__u64)(uintptr_t)buffer;
632 admin_cmd.data_len = SNDK_NVME_SN861_DRIVE_RESIZE_BUFFER_SIZE0x1000;
633
634 ret = libnvme_exec_admin_passthru(hdl, &admin_cmd);
635 if (result)
636 *result = admin_cmd.result;
637 return ret;
638}
639
640static int sndk_drive_resize(int argc, char **argv,
641 struct command *command,
642 struct plugin *plugin)
643{
644 const char *desc = "Send a Resize command.";
645 const char *size = "The new size (in GB) to resize the drive to.";
646 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
647 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
648 uint64_t capabilities = 0;
649 int ret;
650 uint32_t device_id = -1, vendor_id = -1;
651 __u64 result;
652
653 struct config {
654 uint64_t size;
655 };
656
657 struct config cfg = {
658 .size = 0,
659 };
660
661 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"size", 's', "NUM", CFG_POSITIVE, &cfg.size, 1, size
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 0, }, {"timeout"
, 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, { ((void*)0) } }
662 OPT_UINT("size", 's', &cfg.size, size))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"size", 's', "NUM", CFG_POSITIVE, &cfg.size, 1, size
, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 0, }, {"timeout"
, 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, { ((void*)0) } }
;
663
664 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
665 if (ret)
666 return ret;
667
668 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
669 if (ret)
670 return ret;
671 sndk_check_device(ctx, hdl);
672 capabilities = sndk_get_drive_capabilities(ctx, hdl);
673 ret = sndk_get_pci_ids(ctx, hdl, &device_id, &vendor_id);
Value stored to 'ret' is never read
674
675 if ((capabilities & SNDK_DRIVE_CAP_RESIZE_SN8610x0000080000000000) == SNDK_DRIVE_CAP_RESIZE_SN8610x0000080000000000) {
676 ret = sndk_do_sn861_drive_resize(hdl, cfg.size, &result);
677
678 if (!ret) {
679 fprintf(stderrstderr, "The drive-resize command was successful. A system ");
680 fprintf(stderrstderr, "shutdown is required to complete the operation.\n");
681 } else
682 fprintf(stderrstderr, "ERROR: SNDK: %s failure, ret: %d, result: 0x%"PRIx64"l" "x""\n",
683 __func__, ret, (uint64_t)result);
684 } else {
685 /* Fallback to WDC plugin command if otherwise not supported */
686 return run_wdc_drive_resize(argc, argv, command, plugin);
687 }
688
689 nvme_show_status(ret);
690 return ret;
691}
692
693static void sndk_print_fw_act_history_log_normal(__u8 *data, int num_entries)
694{
695 int i, j;
696 char previous_fw[9];
697 char new_fw[9];
698 char commit_action_bin[8];
699 char time_str[100];
700 __u16 oldestEntryIdx = 0, entryIdx = 0;
701 uint64_t timestamp;
702 int fw_vers_len = 0;
703 const char *null_fw = "--------";
704
705 memset((void *)time_str, '\0', 100);
706
707 if (data[0] == SNDK_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
708 printf(" Firmware Activate History Log\n");
709 printf(" Power Cycle ");
710 printf("Previous New\n");
711 printf(" Entry Timestamp Count ");
712 printf("Firmware Firmware Slot Action Result\n");
713 printf(" ----- ----------------- ----------------- ");
714 printf("--------- --------- ----- ------ -------\n");
715
716 struct sndk_fw_act_history_log_format_c2 *fw_act_hist_log =
717 (struct sndk_fw_act_history_log_format_c2 *)(data);
718
719 oldestEntryIdx = SNDK_MAX_NUM_ACT_HIST_ENTRIES20;
720 if (num_entries == SNDK_MAX_NUM_ACT_HIST_ENTRIES20) {
721 /* find lowest/oldest entry */
722 for (i = 0; i < num_entries; i++) {
723 j = (i+1 == SNDK_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
724 if (le16_to_cpu(
725 fw_act_hist_log->entry[i].fw_act_hist_entries) >
726 le16_to_cpu(
727 fw_act_hist_log->entry[j].fw_act_hist_entries)) {
728 oldestEntryIdx = j;
729 break;
730 }
731 }
732 }
733 if (oldestEntryIdx == SNDK_MAX_NUM_ACT_HIST_ENTRIES20)
734 entryIdx = 0;
735 else
736 entryIdx = oldestEntryIdx;
737
738 for (i = 0; i < num_entries; i++) {
739 memset((void *)previous_fw, 0, 9);
740 memset((void *)new_fw, 0, 9);
741 memset((void *)commit_action_bin, 0, 8);
742
743 memcpy(previous_fw,
744 (char *)&
745 (fw_act_hist_log->entry[entryIdx].previous_fw_version),
746 8);
747 fw_vers_len = strlen((char *)
748 &(fw_act_hist_log->entry[entryIdx].current_fw_version));
749 if (fw_vers_len > 1)
750 memcpy(new_fw,
751 (char *)&
752 (fw_act_hist_log->entry[entryIdx].current_fw_version),
753 8);
754 else
755 memcpy(new_fw, null_fw, 8);
756
757 printf("%5"PRIu16"u""",
758 (uint16_t)le16_to_cpu(
759 fw_act_hist_log->entry[entryIdx].fw_act_hist_entries));
760
761 timestamp = (0x0000FFFFFFFFFFFF &
762 le64_to_cpu(
763 fw_act_hist_log->entry[entryIdx].timestamp));
764 printf(" ");
765 printf("%16"PRIu64"l" "u""", timestamp);
766 printf(" ");
767
768 printf("%16"PRIu64"l" "u""",
769 (uint64_t)le64_to_cpu(
770 fw_act_hist_log->entry[entryIdx].power_cycle_count));
771 printf(" ");
772 printf("%s", (char *)previous_fw);
773 printf(" ");
774 printf("%s", (char *)new_fw);
775 printf(" ");
776 printf("%2"PRIu8"u""",
777 (uint8_t)fw_act_hist_log->entry[entryIdx].slot_number);
778 printf(" ");
779 sndk_get_commit_action_bin(
780 fw_act_hist_log->entry[entryIdx].commit_action_type,
781 (char *)&commit_action_bin);
782 printf(" %s", (char *)commit_action_bin);
783 printf(" ");
784 if (!le16_to_cpu(fw_act_hist_log->entry[entryIdx].result))
785 printf("pass");
786 else
787 printf("fail #%d",
788 (uint16_t)le16_to_cpu(
789 fw_act_hist_log->entry[entryIdx].result));
790 printf("\n");
791
792 entryIdx++;
793 if (entryIdx >= SNDK_MAX_NUM_ACT_HIST_ENTRIES20)
794 entryIdx = 0;
795 }
796 } else
797 fprintf(stderrstderr, "ERROR: SNDK: %s: Unknown log page\n", __func__);
798}
799
800static void sndk_print_fw_act_history_log_json(__u8 *data, int num_entries)
801{
802 struct json_object *root = json_create_object()json_object_new_object();
803 int i, j;
804 char previous_fw[9];
805 char new_fw[9];
806 char commit_action_bin[8];
807 char fail_str[32];
808 char time_str[100];
809 char ext_time_str[20];
810 uint64_t timestamp;
811 int fw_vers_len = 0;
812
813 memset((void *)previous_fw, 0, 9);
814 memset((void *)new_fw, 0, 9);
815 memset((void *)commit_action_bin, 0, 8);
816 memset((void *)time_str, '\0', 100);
817 memset((void *)ext_time_str, 0, 20);
818 memset((void *)fail_str, 0, 11);
819 char *null_fw = "--------";
820 __u16 oldestEntryIdx = 0, entryIdx = 0;
821
822 if (data[0] == SNDK_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2) {
823 struct sndk_fw_act_history_log_format_c2 *fw_act_hist_log =
824 (struct sndk_fw_act_history_log_format_c2 *)(data);
825
826 oldestEntryIdx = SNDK_MAX_NUM_ACT_HIST_ENTRIES20;
827 if (num_entries == SNDK_MAX_NUM_ACT_HIST_ENTRIES20) {
828 /* find lowest/oldest entry */
829 for (i = 0; i < num_entries; i++) {
830 j = (i+1 == SNDK_MAX_NUM_ACT_HIST_ENTRIES20) ? 0 : i+1;
831 if (le16_to_cpu(
832 fw_act_hist_log->entry[i].fw_act_hist_entries) >
833 le16_to_cpu(
834 fw_act_hist_log->entry[j].fw_act_hist_entries)) {
835 oldestEntryIdx = j;
836 break;
837 }
838 }
839 }
840 if (oldestEntryIdx == SNDK_MAX_NUM_ACT_HIST_ENTRIES20)
841 entryIdx = 0;
842 else
843 entryIdx = oldestEntryIdx;
844
845 for (i = 0; i < num_entries; i++) {
846 memcpy(previous_fw,
847 (char *)&
848 (fw_act_hist_log->entry[entryIdx].previous_fw_version),
849 8);
850 fw_vers_len = strlen((char *)
851 &(fw_act_hist_log->entry[entryIdx].current_fw_version));
852 if (fw_vers_len > 1)
853 memcpy(new_fw,
854 (char *)&
855 (fw_act_hist_log->entry[entryIdx].current_fw_version),
856 8);
857 else
858 memcpy(new_fw, null_fw, 8);
859
860 json_object_add_value_int(root, "Entry",json_object_object_add(root, "Entry", json_object_new_int(le16_to_cpu
(fw_act_hist_log->entry[entryIdx].fw_act_hist_entries)))
861 le16_to_cpu(fw_act_hist_log->entry[entryIdx].fw_act_hist_entries))json_object_object_add(root, "Entry", json_object_new_int(le16_to_cpu
(fw_act_hist_log->entry[entryIdx].fw_act_hist_entries)))
;
862
863 timestamp = (0x0000FFFFFFFFFFFF &
864 le64_to_cpu(
865 fw_act_hist_log->entry[entryIdx].timestamp));
866 json_object_add_value_uint64(root, "Timestamp", timestamp)json_object_object_add(root, "Timestamp", json_object_new_uint64
(timestamp))
;
867
868 json_object_add_value_int(root, "Power Cycle Count",json_object_object_add(root, "Power Cycle Count", json_object_new_int
(le64_to_cpu( fw_act_hist_log->entry[entryIdx].power_cycle_count
)))
869 le64_to_cpu(json_object_object_add(root, "Power Cycle Count", json_object_new_int
(le64_to_cpu( fw_act_hist_log->entry[entryIdx].power_cycle_count
)))
870 fw_act_hist_log->entry[entryIdx].power_cycle_count))json_object_object_add(root, "Power Cycle Count", json_object_new_int
(le64_to_cpu( fw_act_hist_log->entry[entryIdx].power_cycle_count
)))
;
871 json_object_add_value_string(root, "Previous Firmware",
872 previous_fw);
873 json_object_add_value_string(root, "New Firmware",
874 new_fw);
875 json_object_add_value_int(root, "Slot",json_object_object_add(root, "Slot", json_object_new_int(fw_act_hist_log
->entry[entryIdx].slot_number))
876 fw_act_hist_log->entry[entryIdx].slot_number)json_object_object_add(root, "Slot", json_object_new_int(fw_act_hist_log
->entry[entryIdx].slot_number))
;
877
878 sndk_get_commit_action_bin(
879 fw_act_hist_log->entry[entryIdx].commit_action_type,
880 (char *)&commit_action_bin);
881 json_object_add_value_string(root, "Action", commit_action_bin);
882
883 if (!le16_to_cpu(fw_act_hist_log->entry[entryIdx].result)) {
884 json_object_add_value_string(root, "Result", "pass");
885 } else {
886 sprintf((char *)fail_str, "fail #%d",
887 (int)(le16_to_cpu(
888 fw_act_hist_log->entry[entryIdx].result)));
889 json_object_add_value_string(root, "Result", fail_str);
890 }
891
892 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
893 printf("\n");
894
895 entryIdx++;
896 if (entryIdx >= SNDK_MAX_NUM_ACT_HIST_ENTRIES20)
897 entryIdx = 0;
898 }
899 } else
900 fprintf(stderrstderr, "ERROR: SNDK: %s: Unknown log page\n", __func__);
901
902 json_free_object(root)json_object_put(root);
903}
904
905static int sndk_print_fw_act_history_log(__u8 *data, int num_entries, int fmt)
906{
907 if (!data) {
908 fprintf(stderrstderr, "ERROR: SNDK: Invalid buffer in print_fw act_history_log\n");
909 return -1;
910 }
911
912 switch (fmt) {
913 case NORMAL:
914 sndk_print_fw_act_history_log_normal(data, num_entries);
915 break;
916 case JSON:
917 sndk_print_fw_act_history_log_json(data, num_entries);
918 break;
919 }
920 return 0;
921}
922
923static int sndk_get_fw_act_history_C2(struct libnvme_global_ctx *ctx, struct libnvme_transport_handle *hdl,
924 char *format)
925{
926 struct sndk_fw_act_history_log_format_c2 *fw_act_history_log;
927 __u32 tot_entries = 0, num_entries = 0;
928 nvme_print_flags_t fmt;
929 __u8 *data;
930 int ret;
931 bool_Bool c2GuidMatch = false0;
932
933 if (!sndk_check_device(ctx, hdl))
934 return -1;
935
936 ret = validate_output_format(format, &fmt);
937 if (ret < 0) {
938 fprintf(stderrstderr, "ERROR: SNDK: invalid output format\n");
939 return ret;
940 }
941
942 data = (__u8 *)malloc(sizeof(__u8) * SNDK_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
943 if (!data) {
944 fprintf(stderrstderr, "ERROR: SNDK: malloc: %s\n", libnvme_strerror(errno(*__errno_location ())));
945 return -1;
946 }
947
948 memset(data, 0, sizeof(__u8) * SNDK_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
949
950 ret = nvme_get_log_simple(hdl,
951 SNDK_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID0xC2,
952 data, SNDK_FW_ACT_HISTORY_C2_LOG_BUF_LEN0x1000);
953
954 if (strcmp(format, "json"))
955 nvme_show_status(ret);
956
957 if (!ret) {
958 /* Get the log page data and verify the GUID */
959 fw_act_history_log = (struct sndk_fw_act_history_log_format_c2 *)(data);
960
961 c2GuidMatch = !memcmp(ocp_C2_guid,
962 fw_act_history_log->log_page_guid,
963 SNDK_GUID_LENGTH16);
964
965 if (c2GuidMatch) {
966 /* parse the data */
967 tot_entries = le32_to_cpu(fw_act_history_log->num_entries);
968
969 if (tot_entries > 0) {
970 num_entries = (tot_entries < SNDK_MAX_NUM_ACT_HIST_ENTRIES20) ?
971 tot_entries : SNDK_MAX_NUM_ACT_HIST_ENTRIES20;
972 ret = sndk_print_fw_act_history_log(data, num_entries,
973 fmt);
974 } else {
975 fprintf(stderrstderr, "INFO: SNDK: No entries found.\n");
976 ret = 0;
977 }
978 } else {
979 fprintf(stderrstderr, "ERROR: SNDK: Invalid C2 log page GUID\n");
980 ret = -1;
981 }
982 } else {
983 fprintf(stderrstderr, "ERROR: SNDK: Unable to read FW Activate History Log Page data\n");
984 ret = -1;
985 }
986
987 free(data);
988 return ret;
989}
990
991
992static int sndk_vs_fw_activate_history(int argc, char **argv,
993 struct command *command,
994 struct plugin *plugin)
995{
996 const char *desc = "Retrieve FW activate history table.";
997 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
998 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
999 uint64_t capabilities = 0;
1000 int ret;
1001
1002 struct config {
1003 char *output_format;
1004 };
1005
1006 struct config cfg = {
1007 .output_format = "normal",
1008 };
1009
1010 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 0, }, {"timeout"
, 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, { ((void*)0) } }
;
1011
1012 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1013 if (ret)
1014 return ret;
1015
1016 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
1017 if (ret)
1018 return ret;
1019 capabilities = sndk_get_drive_capabilities(ctx, hdl);
1020
1021 if (capabilities & SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_C20x0000000001000000) {
1022 ret = sndk_get_fw_act_history_C2(ctx, hdl, cfg.output_format);
1023
1024 if (ret) {
1025 fprintf(stderrstderr, "ERROR: SNDK: Failure reading the FW ");
1026 fprintf(stderrstderr, "Activate History, ret = %d\n", ret);
1027 }
1028 } else
1029 /* Fall back to the wdc plugin command */
1030 ret = run_wdc_vs_fw_activate_history(argc, argv, command, plugin);
1031
1032 return ret;
1033}
1034
1035static int sndk_do_clear_fw_activate_history_fid(struct libnvme_transport_handle *hdl)
1036{
1037 int ret = -1;
1038 __u64 result;
1039 __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */
1040
1041 ret = nvme_set_features_simple(hdl, SNDK_NVME_CLEAR_FW_ACT_HIST_VU_FID0xC1, 0, value,
1042 false0, &result);
1043
1044 nvme_show_status(ret);
1045 return ret;
1046}
1047
1048static int sndk_clear_fw_activate_history(int argc, char **argv,
1049 struct command *command,
1050 struct plugin *plugin)
1051{
1052 const char *desc = "Clear FW activate history table.";
1053 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1054 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1055 __u64 capabilities = 0;
1056 int ret;
1057
1058 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 0, }, {"timeout"
, 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, { ((void*)0) } }
;
1059
1060 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1061 if (ret)
1062 return ret;
1063
1064 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
1065 if (ret)
1066 return ret;
1067 capabilities = sndk_get_drive_capabilities(ctx, hdl);
1068
1069 if (capabilities & SNDK_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY0x0000000002000000) {
1070 ret = sndk_do_clear_fw_activate_history_fid(hdl);
1071
1072 if (ret) {
1073 fprintf(stderrstderr, "ERROR: SNDK: Failure clearing the FW ");
1074 fprintf(stderrstderr, "Activate History, ret = %d\n", ret);
1075 }
1076 } else
1077 /* Fall back to the wdc plugin command */
1078 ret = run_wdc_clear_fw_activate_history(argc, argv, command, plugin);
1079
1080 return ret;
1081}
1082
1083static int sndk_vs_telemetry_controller_option(int argc, char **argv,
1084 struct command *command,
1085 struct plugin *plugin)
1086{
1087 return run_wdc_vs_telemetry_controller_option(argc, argv, command, plugin);
1088}
1089
1090static int sndk_reason_identifier(int argc, char **argv,
1091 struct command *command,
1092 struct plugin *plugin)
1093{
1094 return run_wdc_reason_identifier(argc, argv, command, plugin);
1095}
1096
1097static int sndk_log_page_directory(int argc, char **argv,
1098 struct command *command,
1099 struct plugin *plugin)
1100{
1101 return run_wdc_log_page_directory(argc, argv, command, plugin);
1102}
1103
1104static int sndk_namespace_resize(int argc, char **argv,
1105 struct command *command,
1106 struct plugin *plugin)
1107{
1108 return run_wdc_namespace_resize(argc, argv, command, plugin);
1109}
1110
1111static int sndk_vs_drive_info(int argc, char **argv,
1112 struct command *command,
1113 struct plugin *plugin)
1114{
1115 return run_wdc_vs_drive_info(argc, argv, command, plugin);
1116}
1117
1118static int sndk_capabilities(int argc, char **argv,
1119 struct command *command,
1120 struct plugin *plugin)
1121{
1122 const char *desc = "Send a capabilities command.";
1123 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1124 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1125 uint64_t capabilities = 0;
1126 int ret;
1127
1128 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 0, }, {"timeout"
, 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, { ((void*)0) } }
;
1129
1130 ret = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1131 if (ret)
1132 return ret;
1133
1134 /* get capabilities */
1135 ret = libnvme_scan_topology(ctx, NULL((void*)0), NULL((void*)0));
1136 if (ret || !sndk_check_device(ctx, hdl))
1137 return -1;
1138
1139 capabilities = sndk_get_drive_capabilities(ctx, hdl);
1140
1141 /* print command and supported status */
1142 printf("Sandisk Plugin Capabilities for NVME device:%s\n", libnvme_transport_handle_get_name(hdl));
1143 printf("vs-internal-log : %s\n",
1144 capabilities & SNDK_DRIVE_CAP_INTERNAL_LOG_MASK(0x0000000000000002 | 0x0000000800000000 | 0x0000040000000000
| 0x0000000200000000 | 0x0000000400000000)
? "Supported" : "Not Supported");
1145 printf("vs-nand-stats : %s\n",
1146 capabilities & SNDK_DRIVE_CAP_NAND_STATS0x0000000000000200 ? "Supported" : "Not Supported");
1147 printf("vs-smart-add-log : %s\n",
1148 capabilities & SNDK_DRIVE_CAP_SMART_LOG_MASK(0x0000000000100000 | 0x0000000000000004 | 0x0000000000000008
| 0x0000000000000010)
? "Supported" : "Not Supported");
1149 printf("--C0 Log Page : %s\n",
1150 capabilities & SNDK_DRIVE_CAP_C0_LOG_PAGE0x0000000000100000 ? "Supported" : "Not Supported");
1151 printf("--C1 Log Page : %s\n",
1152 capabilities & SNDK_DRIVE_CAP_C1_LOG_PAGE0x0000000000000004 ? "Supported" : "Not Supported");
1153 printf("--C3 Log Page : %s\n",
1154 capabilities & SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
1155 printf("--CA Log Page : %s\n",
1156 capabilities & SNDK_DRIVE_CAP_CA_LOG_PAGE0x0000000000000008 ? "Supported" : "Not Supported");
1157 printf("--D0 Log Page : %s\n",
1158 capabilities & SNDK_DRIVE_CAP_D0_LOG_PAGE0x0000000000000010 ? "Supported" : "Not Supported");
1159 printf("clear-pcie-correctable-errors : %s\n",
1160 capabilities & SNDK_DRIVE_CAP_CLEAR_PCIE_MASK(0x0000000000000080 | 0x0000000000400000 | 0x0000000000800000
)
? "Supported" : "Not Supported");
1161 printf("get-drive-status : %s\n",
1162 capabilities & SNDK_DRIVE_CAP_DRIVE_STATUS0x0000000000000020 ? "Supported" : "Not Supported");
1163 printf("clear-assert-dump : %s\n",
1164 capabilities & SNDK_DRIVE_CAP_CLEAR_ASSERT0x0000000000000040 ? "Supported" : "Not Supported");
1165 printf("drive-resize : %s\n",
1166 capabilities & SNDK_DRIVE_CAP_RESIZE_MASK(0x0000000000000100 | 0x0000080000000000) ? "Supported" : "Not Supported");
1167 printf("vs-fw-activate-history : %s\n",
1168 capabilities & SNDK_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK(0x0000000000002000 | 0x0000000001000000) ? "Supported" :
1169 "Not Supported");
1170 printf("clear-fw-activate-history : %s\n",
1171 capabilities & SNDK_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK(0x0000000000004000 | 0x0000000002000000) ? "Supported" :
1172 "Not Supported");
1173 printf("vs-telemetry-controller-option: %s\n",
1174 capabilities & SNDK_DRIVE_CAP_DISABLE_CTLR_TELE_LOG0x0000000000008000 ? "Supported" : "Not Supported");
1175 printf("vs-error-reason-identifier : %s\n",
1176 capabilities & SNDK_DRIVE_CAP_REASON_ID0x0000000000010000 ? "Supported" : "Not Supported");
1177 printf("log-page-directory : %s\n",
1178 capabilities & SNDK_DRIVE_CAP_LOG_PAGE_DIR0x0000000000020000 ? "Supported" : "Not Supported");
1179 printf("namespace-resize : %s\n",
1180 capabilities & SNDK_DRIVE_CAP_NS_RESIZE0x0000000000040000 ? "Supported" : "Not Supported");
1181 printf("vs-drive-info : %s\n",
1182 capabilities & SNDK_DRIVE_CAP_INFO0x0000000000080000 ? "Supported" : "Not Supported");
1183 printf("vs-temperature-stats : %s\n",
1184 capabilities & SNDK_DRIVE_CAP_TEMP_STATS0x0000000000200000 ? "Supported" : "Not Supported");
1185 printf("cloud-SSD-plugin-version : %s\n",
1186 capabilities & SNDK_DRIVE_CAP_CLOUD_SSD_VERSION0x0000000004000000 ? "Supported" : "Not Supported");
1187 printf("vs-pcie-stats : %s\n",
1188 capabilities & SNDK_DRIVE_CAP_PCIE_STATS0x0000000008000000 ? "Supported" : "Not Supported");
1189 printf("get-error-recovery-log : %s\n",
1190 capabilities & SNDK_DRIVE_CAP_OCP_C1_LOG_PAGE0x0000002000000000 ? "Supported" : "Not Supported");
1191 printf("get-dev-capabilities-log : %s\n",
1192 capabilities & SNDK_DRIVE_CAP_OCP_C4_LOG_PAGE0x0000004000000000 ? "Supported" : "Not Supported");
1193 printf("get-unsupported-reqs-log : %s\n",
1194 capabilities & SNDK_DRIVE_CAP_OCP_C5_LOG_PAGE0x0000008000000000 ? "Supported" : "Not Supported");
1195 printf("get-latency-monitor-log : %s\n",
1196 capabilities & SNDK_DRIVE_CAP_C3_LOG_PAGE0x0000000020000000 ? "Supported" : "Not Supported");
1197 printf("cloud-boot-SSD-version : %s\n",
1198 capabilities & SNDK_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION0x0000000040000000 ? "Supported" :
1199 "Not Supported");
1200 printf("vs-cloud-log : %s\n",
1201 capabilities & SNDK_DRIVE_CAP_CLOUD_LOG_PAGE0x0000000080000000 ? "Supported" : "Not Supported");
1202 printf("vs-hw-rev-log : %s\n",
1203 capabilities & SNDK_DRIVE_CAP_HW_REV_LOG_PAGE0x0000000010000000 ? "Supported" : "Not Supported");
1204 printf("vs-device_waf : %s\n",
1205 capabilities & SNDK_DRIVE_CAP_DEVICE_WAF0x0000010000000000 ? "Supported" : "Not Supported");
1206 printf("set-latency-monitor-feature : %s\n",
1207 capabilities & SNDK_DRIVE_CAP_SET_LATENCY_MONITOR0x0000020000000000 ? "Supported" : "Not Supported");
1208 printf("capabilities : Supported\n");
1209
1210 return 0;
1211}
1212
1213static int sndk_cloud_ssd_plugin_version(int argc, char **argv,
1214 struct command *command,
1215 struct plugin *plugin)
1216{
1217 return run_wdc_cloud_ssd_plugin_version(argc, argv, command, plugin);
1218}
1219
1220static int sndk_vs_pcie_stats(int argc, char **argv,
1221 struct command *command,
1222 struct plugin *plugin)
1223{
1224 return run_wdc_vs_pcie_stats(argc, argv, command, plugin);
1225}
1226
1227static int sndk_get_latency_monitor_log(int argc, char **argv,
1228 struct command *command,
1229 struct plugin *plugin)
1230{
1231 return run_wdc_get_latency_monitor_log(argc, argv, command, plugin);
1232}
1233
1234static int sndk_get_error_recovery_log(int argc, char **argv,
1235 struct command *command,
1236 struct plugin *plugin)
1237{
1238 return run_wdc_get_error_recovery_log(argc, argv, command, plugin);
1239}
1240
1241static int sndk_get_dev_capabilities_log(int argc, char **argv,
1242 struct command *command,
1243 struct plugin *plugin)
1244{
1245 return run_wdc_get_dev_capabilities_log(argc, argv, command, plugin);
1246}
1247
1248static int sndk_get_unsupported_reqs_log(int argc, char **argv,
1249 struct command *command,
1250 struct plugin *plugin)
1251{
1252 return run_wdc_get_unsupported_reqs_log(argc, argv, command, plugin);
1253}
1254
1255static int sndk_cloud_boot_SSD_version(int argc, char **argv,
1256 struct command *command,
1257 struct plugin *plugin)
1258{
1259 return run_wdc_cloud_boot_SSD_version(argc, argv, command, plugin);
1260}
1261
1262static int sndk_vs_cloud_log(int argc, char **argv,
1263 struct command *command,
1264 struct plugin *plugin)
1265{
1266 return run_wdc_vs_cloud_log(argc, argv, command, plugin);
1267}
1268
1269static int sndk_vs_hw_rev_log(int argc, char **argv,
1270 struct command *command,
1271 struct plugin *plugin)
1272{
1273 return run_wdc_vs_hw_rev_log(argc, argv, command, plugin);
1274}
1275
1276static int sndk_vs_device_waf(int argc, char **argv,
1277 struct command *command,
1278 struct plugin *plugin)
1279{
1280 return run_wdc_vs_device_waf(argc, argv, command, plugin);
1281}
1282
1283static int sndk_set_latency_monitor_feature(int argc, char **argv,
1284 struct command *command,
1285 struct plugin *plugin)
1286{
1287 return run_wdc_set_latency_monitor_feature(argc, argv, command, plugin);
1288}
1289
1290static int sndk_vs_temperature_stats(int argc, char **argv,
1291 struct command *command,
1292 struct plugin *plugin)
1293{
1294 return run_wdc_vs_temperature_stats(argc, argv, command, plugin);
1295}
1296
1297static int sndk_cu_smart_log(int argc, char **argv,
1298 struct command *command,
1299 struct plugin *plugin)
1300{
1301 return run_wdc_cu_smart_log(argc, argv, command, plugin);
1302}