Bug Summary

File:.build-ci/../plugins/ocp/ocp-telemetry-decode.c
Warning:line 1802, column 55
Addition of a null pointer (from variable 'ptelemetry_buffer') and a nonzero integer value results in undefined behavior

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ocp-telemetry-decode.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 static -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/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I src -I ../src -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I shared -I ../shared -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -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 -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-08-08-045408-589-1 -x c ../plugins/ocp/ocp-telemetry-decode.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/* Copyright (c) 2024 Western Digital Corporation or its affiliates.
3 *
4 * Authors: Jeff Lien <jeff.lien@wdc.com>,
5 */
6#include <libnvme.h>
7
8#include "common.h"
9#include "nvme.h"
10#include "plugin.h"
11#include "nvme-print.h"
12
13#include "ocp-telemetry-decode.h"
14
15
16void print_vu_event_data(__u32 size, __u8 *data)
17{
18 int j;
19 __u16 vu_event_id = *(__u16 *)data;
20
21 printf(" VU Event ID : 0x%02x\n", le16_to_cpu(vu_event_id));
22 printf(" VU Data : 0x");
23 for (j = 2; j < size; j++)
24 printf("%x", data[j]);
25 printf("\n\n");
26}
27
28void print_stats_desc(struct telemetry_stats_desc *stat_desc)
29{
30 int j;
31 /* Get the statistics Identifier string name and data size */
32 __u16 stat_id = stat_desc->id;
33 __u32 stat_data_sz = ((stat_desc->size) * 4);
34
35 printf("Statistics Identifier : 0x%x, %s\n",
36 stat_id, telemetry_stat_id_to_string(stat_id));
37 printf("Statistics info : 0x%x\n", stat_desc->info);
38 printf("NS info : 0x%x\n", stat_desc->ns_info);
39 printf("Statistic Data Size : 0x%x\n", le16_to_cpu(stat_data_sz));
40 printf("Namespace ID[15:0] : 0x%x\n", stat_desc->nsid);
41
42 if (stat_data_sz > 0) {
43 printf("%s : 0x",
44 telemetry_stat_id_to_string(stat_id));
45 for (j = 0; j < stat_data_sz; j++)
46 printf("%02x", stat_desc->data[j]);
47 printf("\n");
48 }
49 printf("\n");
50}
51
52void print_telemetry_fifo_event(__u8 class_type,
53 __u16 id, __u8 size_dw, __u8 *data)
54{
55 int j;
56 const char *class_str = NULL((void*)0);
57 __u32 size = size_dw * 4;
58 char time_str[40];
59 uint64_t timestamp = 0;
60
61 memset((void *)time_str, '\0', 40);
62
63 if (class_type) {
64 class_str = telemetry_event_class_to_string(class_type);
65 printf("Event Class : %s\n", class_str);
66 printf(" Size : 0x%02x\n", size);
67 }
68
69 switch (class_type) {
70 case TELEMETRY_TIMESTAMP_CLASS:
71 timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(*(uint64_t *)data));
72
73 memset((void *)time_str, 0, 9);
74 sprintf((char *)time_str, "%04d:%02d:%02d", (int)(le64_to_cpu(timestamp)/3600),
75 (int)((le64_to_cpu(timestamp%3600)/60)),
76 (int)(le64_to_cpu(timestamp%60)));
77
78 printf(" Event ID : 0x%04x %s\n", id, telemetry_ts_event_to_string(id));
79 printf(" Timestamp : %s\n", time_str);
80 if (size > 8) {
81 printf(" VU Data : 0x");
82 for (j = 8; j < size; j++)
83 printf("%02x", data[j]);
84 printf("\n\n");
85 }
86 break;
87
88 case TELEMETRY_PCIE_CLASS:
89 printf(" Event ID : 0x%04x %s\n",
90 id, telemetry_pcie_event_id_to_string(id));
91 printf(" State : 0x%02x %s\n",
92 data[0], telemetry_pcie_state_data_to_string(data[0]));
93 printf(" Speed : 0x%02x %s\n",
94 data[1], telemetry_pcie_speed_data_to_string(data[1]));
95 printf(" Width : 0x%02x %s\n",
96 data[2], telemetry_pcie_width_data_to_string(data[2]));
97 if (size > 4) {
98 printf(" VU Data : ");
99 for (j = 4; j < size; j++)
100 printf("%x", data[j]);
101 printf("\n\n");
102 }
103 break;
104
105 case TELEMETRY_NVME_CLASS:
106 printf(" Event ID : 0x%04x %s\n",
107 id, telemetry_nvme_event_id_to_string(id));
108 if ((id == ADMIN_QUEUE_NONZERO_STATUS) ||
109 (id == IO_QUEUE_NONZERO_STATUS)) {
110 printf(" Cmd Op Code : 0x%02x\n", data[0]);
111 __u16 status;
112 __u16 cmd_id;
113 __u16 sq_id;
114
115 memcpy(&status, &data[1], sizeof(status));
116 memcpy(&cmd_id, &data[3], sizeof(cmd_id));
117 memcpy(&sq_id, &data[5], sizeof(sq_id));
118
119 printf(" Status Code : 0x%04x\n", le16_to_cpu(status));
120 printf(" Cmd ID : 0x%04x\n", le16_to_cpu(cmd_id));
121 printf(" SQ ID : 0x%04x\n", le16_to_cpu(sq_id));
122 printf(" LID,FID,Other Cmd Reserved : 0x%02x\n", data[7]);
123 } else if (id == CC_REGISTER_CHANGED) {
124 __u32 cc_reg_data = *(__u32 *)data;
125
126 printf(" CC Reg Data : 0x%08x\n",
127 le32_to_cpu(cc_reg_data));
128 } else if (id == CSTS_REGISTER_CHANGED) {
129 __u32 csts_reg_data = *(__u32 *)data;
130
131 printf(" CSTS Reg Data : 0x%08x\n",
132 le32_to_cpu(csts_reg_data));
133 } else if (id == OOB_COMMAND) {
134 printf(" Cmd Op Code : 0x%02x\n", data[0]);
135 __u16 status;
136 memcpy(&status, &data[1], sizeof(status));
137
138 printf(" Admin Cmd Status : 0x%04x\n", le16_to_cpu(status));
139 printf(" NVMe MI SC : 0x%02x\n", data[3]);
140 printf(" Byte1 Req Msg : 0x%02x\n", data[4]);
141 printf(" Byte2 Req Msg : 0x%02x\n", data[5]);
142 } else if (id == OOB_AER_EVENT_MSG_TRANS) {
143 __u64 aem = *(__u64 *)data;
144
145 printf(" AEM : 0x%016"PRIx64"l" "x""\n",
146 le64_to_cpu(aem));
147 }
148 if (size > 8)
149 print_vu_event_data((size-8), (__u8 *)&data[8]);
150 break;
151
152 case TELEMETRY_RESET_CLASS:
153 printf(" Event ID : 0x%04x %s\n",
154 id, telemetry_reset_event_id_to_string(id));
155 if (size)
156 print_vu_event_data(size, data);
157 break;
158
159 case TELEMETRY_BOOT_SEQ_CLASS:
160 printf(" Event ID : 0x%04x %s\n",
161 id, telemetry_boot_seq_event_id_to_string(id));
162 if (size)
163 print_vu_event_data(size, data);
164 break;
165
166 case TELEMETRY_FW_ASSERT_CLASS:
167 printf(" Event ID : 0x%04x %s\n",
168 id, telemetry_fw_assert_event_id_to_string(id));
169 if (size)
170 print_vu_event_data(size, data);
171 break;
172
173 case TELEMETRY_TEMPERATURE_CLASS:
174 printf(" Event ID : 0x%04x %s\n",
175 id, telemetry_temperature_event_id_to_string(id));
176 if (size)
177 print_vu_event_data(size, data);
178 break;
179
180 case TELEMETRY_MEDIA_DBG_CLASS:
181 printf(" Event ID : 0x%04x %s\n",
182 id, telemetry_media_debug_event_id_to_string(id));
183 if (size)
184 print_vu_event_data(size, data);
185 break;
186
187 case TELEMETRY_MEDIA_WEAR_CLASS:
188 printf(" Event ID : 0x%04x %s\n",
189 id, telemetry_media_wear_event_id_to_string(id));
190 __u32 host_tb_written = *(__u32 *)&data[0];
191 __u32 media_tb_written = *(__u32 *)&data[4];
192 __u32 media_tb_erased = *(__u32 *)&data[8];
193
194 printf(" Host TB Written : 0x%04x\n",
195 le16_to_cpu(host_tb_written));
196 printf(" Media TB Written : 0x%04x\n",
197 le16_to_cpu(media_tb_written));
198 printf(" Media TB Erased : 0x%04x\n",
199 le16_to_cpu(media_tb_erased));
200
201 if (size > 12)
202 print_vu_event_data((size-12), (__u8 *)&data[12]);
203 break;
204
205 case TELEMETRY_STAT_SNAPSHOT_CLASS:
206 printf(" Statistic ID : 0x%02x %s\n",
207 id, telemetry_stat_id_to_string(id));
208 print_stats_desc((struct telemetry_stats_desc *)data);
209 break;
210
211 case TELEMETRY_VIRTUAL_FIFO_EVENT_CLASS:
212 printf(" Event ID : 0x%04x %s\n",
213 id, telemetry_virtual_fifo_event_id_to_string(id));
214
215 __u16 vu_event_id = *(__u16 *)data;
216
217 printf(" VU Virtual FIFO Event ID : 0x%02x\n", le16_to_cpu(vu_event_id));
218 printf("\n");
219 break;
220
221 default:
222 /*
223 * printf("Unknown Event Class Type\n");
224 * printf("Data : 0x");
225 * for (j = 0; j < size; j++)
226 * printf("%x", data[j]);
227 * printf("\n\n");
228 */
229 break;
230 }
231}
232
233struct statistic_entry statistic_identifiers_map[] = {
234 { 0x00, "Error, this entry does not exist." },
235 { 0x01, "Outstanding Admin Commands" },
236 { 0x02, "Host Write Bandwidth"},
237 { 0x03, "GC Write Bandwidth"},
238 { 0x04, "Active Namespaces"},
239 { 0x05, "Internal Write Workload"},
240 { 0x06, "Internal Read Workload"},
241 { 0x07, "Internal Write Queue Depth"},
242 { 0x08, "Internal Read Queue Depth"},
243 { 0x09, "Pending Trim LBA Count"},
244 { 0x0A, "Host Trim LBA Request Count"},
245 { 0x0B, "Current NVMe Power State"},
246 { 0x0C, "Current DSSD Power State"},
247 { 0x0D, "Program Fail Count"},
248 { 0x0E, "Erase Fail Count"},
249 { 0x0F, "Read Disturb Writes"},
250 { 0x10, "Retention Writes"},
251 { 0x11, "Wear Leveling Writes"},
252 { 0x12, "Read Recovery Writes"},
253 { 0x13, "GC Writes"},
254 { 0x14, "SRAM Correctable Count"},
255 { 0x15, "DRAM Correctable Count"},
256 { 0x16, "SRAM Uncorrectable Count"},
257 { 0x17, "DRAM Uncorrectable Count"},
258 { 0x18, "Data Integrity Error Count"},
259 { 0x19, "Read Retry Error Count"},
260 { 0x1A, "PERST Events Count"},
261 { 0x1B, "Max Die Bad Block"},
262 { 0x1C, "Max NAND Channel Bad Block"},
263 { 0x1D, "Minimum NAND Channel Bad Block"},
264 { 0x1E, "Physical Media Units Written"},
265 { 0x1F, "Physical Media Units Read"},
266 { 0x20, "Bad User NAND Blocks"},
267 { 0x21, "Bad System NAND Blocks"},
268 { 0x22, "XOR Recovery Count"},
269 { 0x23, "Uncorrectable Read Error Count"},
270 { 0x24, "Soft ECC Error Count"},
271 { 0x25, "End to End Correction Counts"},
272 { 0x26, "System Data % Used"},
273 { 0x27, "Refresh Counts"},
274 { 0x28, "User Data Erase Counts"},
275 { 0x29, "Thermal Throttling Status and Count"},
276 { 0x2A, "DSSD Specification Version"},
277 { 0x2B, "PCIe Correctable Error Count"},
278 { 0x2C, "Incomplete Shutdowns"},
279 { 0x2D, "% Free Blocks"},
280 { 0x2E, "Capacitor Health"},
281 { 0x2F, "NVM Express Base Errata Version"},
282 { 0x30, "NVM Command Set Errata Version"},
283 { 0x31, "NVM Express Management Interface Errata Version"},
284 { 0x32, "Unaligned I/O"},
285 { 0x33, "Security Version Number"},
286 { 0x34, "Total NUSE"},
287 { 0x35, "PLP Start Count"},
288 { 0x36, "Endurance Estimate"},
289 { 0x37, "PCIe Link Retraining Count"},
290 { 0x38, "Power State Change Count"},
291 { 0x39, "Lowest Permitted Firmware Revision"},
292 { 0x3A, "Log Page Version"},
293 { 0x3B, "Media Dies Offline"},
294 { 0x3C, "Max Temperature Recorded"},
295 { 0x3D, "NAND Avg. Erase Count"},
296 { 0x3E, "Command Timeouts"},
297 { 0x3F, "System Area Program Fail Count"},
298 { 0x40, "System Area Read Fail Count"},
299 { 0x41, "System Area Erase Fail Count"},
300 { 0x42, "Max Peak Power Capability"},
301 { 0x43, "Current Average Power"},
302 { 0x44, "Lifetime Power Consumed"},
303 { 0x45, "Error / Assert Count"},
304 { 0x46, "Device Busy Time"},
305 { 0x47, "Critical Warning"},
306 { 0x48, "Composite Temperature"},
307 { 0x49, "Available Spare"},
308 { 0x4A, "Available Spare Threshold"},
309 { 0x4B, "Percentage Used"},
310 { 0x4C, "Endurance Group Critical Warning Summary"},
311 { 0x4D, "Data Units Read"},
312 { 0x4E, "Data Units Written"},
313 { 0x4F, "Host Read Commands"},
314 { 0x50, "Host Write Commands"},
315 { 0x51, "Controller Busy Time"},
316 { 0x52, "Power Cycles"},
317 { 0x53, "Power On Hours"},
318 { 0x54, "Unsafe Shutdowns"},
319 { 0x55, "Media and Data Integrity Errors"},
320 { 0x56, "Number of Error Information Log Entries"},
321 { 0x57, "Warning Composite Temperature Time"},
322 { 0x58, "Critical Composite Temperature Time"},
323 { 0x59, "Temperature Sensor 1"},
324 { 0x5A, "Temperature Sensor 2"},
325 { 0x5B, "Temperature Sensor 3"},
326 { 0x5C, "Temperature Sensor 4"},
327 { 0x5D, "Temperature Sensor 5"},
328 { 0x5E, "Temperature Sensor 6"},
329 { 0x5F, "Temperature Sensor 7"},
330 { 0x60, "Temperature Sensor 8"},
331 { 0x61, "Thermal Management Temperature 1 Transition Count"},
332 { 0x62, "Thermal Management Temperature 2 Transition Count"},
333 { 0x63, "Total Time For Thermal Management Temperature 1"},
334 { 0x64, "Total Time For Thermal Management Temperature 2"},
335 { 0x65, "Endurance Estimate"},
336 { 0x66, "Data Units Read"},
337 { 0x67, "Data Units Written"},
338 { 0x68, "Media Units Written"},
339 { 0x69, "Number of Error Information Log Entries"},
340 { 0x6A, "Form Factor"},
341 { 0x6B, "Dies In Use Bad NAND Blocks"},
342 { 0x6C, "Proactive Bad Die Retirement"},
343 { 0x6D, "Namespace ID Context Statistic Descriptor"},
344 { 0x6E, "Controller ID Context Statistic Descriptor"},
345 { 0x6F, "Queue ID Context Statistic Descriptor"}
346};
347
348struct request_data host_log_page_header[] = {
349 { "LogIdentifier", 1 },
350 { "Reserved1", 4 },
351 { "IEEE OUI Identifier", 3 },
352 { "Telemetry Host-Initiated Data Area 1 Last Block", 2 },
353 { "Telemetry Host-Initiated Data Area 2 Last Block", 2 },
354 { "Telemetry Host-Initiated Data Area 3 Last Block", 2 },
355 { "Reserved2", 2 },
356 { "Telemetry Host-Initiated Data Area 4 Last Block", 4 },
357 { "Reserved3", 360 },
358 { "Telemetry Host-Initiated Scope", 1 },
359 { "Telemetry Host Initiated Generation Number", 1 },
360 { "Telemetry Host-Initiated Data Available", 1 },
361 { "Telemetry Controller-Initiated Data Generation Number", 1 }
362};
363
364struct request_data controller_log_page_header[] = {
365 { "LogIdentifier", 1 },
366 { "Reserved1", 4 },
367 { "IEEE OUI Identifier", 3 },
368 { "Telemetry Host-Initiated Data Area 1 Last Block", 2 },
369 { "Telemetry Host-Initiated Data Area 2 Last Block", 2 },
370 { "Telemetry Host-Initiated Data Area 3 Last Block", 2 },
371 { "Reserved2", 2 },
372 { "Telemetry Host-Initiated Data Area 4 Last Block", 4 },
373 { "Reserved3", 361 },
374 { "Telemetry Controller-Initiated Scope", 1 },
375 { "Telemetry Controller-Initiated Data Available", 1 },
376 { "Telemetry Controller-Initiated Data Generation Number", 1 }
377};
378
379struct request_data reason_identifier[] = {
380 { "Error ID", 64 },
381 { "File ID", 8 },
382 { "Line Number", 2 },
383 { "Valid Flags", 1 },
384 { "Reserved", 21 },
385 { "VU Reason Extension", 32 }
386};
387
388struct request_data ocp_header_in_da1[] = {
389 { "Major Version", 2 },
390 { "Minor Version", 2 },
391 { "Reserved1", 4 },
392 { "Timestamp", 8 },
393 { "Log page GUID", GUID_LEN16 },
394 { "Number Telemetry Profiles Supported", 1 },
395 { "Telemetry Profile Selected", 1 },
396 { "Reserved2", 6 },
397 { "Telemetry String Log Size", 8 },
398 { "Reserved3", 8 },
399 { "Firmware Revision", 8 },
400 { "Reserved4", 32 },
401 { "Data Area 1 Statistic Start", 8 },
402 { "Data Area 1 Statistic Size", 8 },
403 { "Data Area 2 Statistic Start", 8 },
404 { "Data Area 2 Statistic Size", 8 },
405 { "Reserved5", 32 },
406 { "Event FIFO 1 Data Area", 1 },
407 { "Event FIFO 2 Data Area", 1 },
408 { "Event FIFO 3 Data Area", 1 },
409 { "Event FIFO 4 Data Area", 1 },
410 { "Event FIFO 5 Data Area", 1 },
411 { "Event FIFO 6 Data Area", 1 },
412 { "Event FIFO 7 Data Area", 1 },
413 { "Event FIFO 8 Data Area", 1 },
414 { "Event FIFO 9 Data Area", 1 },
415 { "Event FIFO 10 Data Area", 1 },
416 { "Event FIFO 11 Data Area", 1 },
417 { "Event FIFO 12 Data Area", 1 },
418 { "Event FIFO 13 Data Area", 1 },
419 { "Event FIFO 14 Data Area", 1 },
420 { "Event FIFO 15 Data Area", 1 },
421 { "Event FIFO 16 Data Area", 1 },
422 { "Event FIFO 1 Start", 8 },
423 { "Event FIFO 1 Size", 8 },
424 { "Event FIFO 2 Start", 8 },
425 { "Event FIFO 2 Size", 8 },
426 { "Event FIFO 3 Start", 8 },
427 { "Event FIFO 3 Size", 8 },
428 { "Event FIFO 4 Start", 8 },
429 { "Event FIFO 4 Size", 8 },
430 { "Event FIFO 5 Start", 8 },
431 { "Event FIFO 5 Size", 8 },
432 { "Event FIFO 6 Start", 8 },
433 { "Event FIFO 6 Size", 8 },
434 { "Event FIFO 7 Start", 8 },
435 { "Event FIFO 7 Size", 8 },
436 { "Event FIFO 8 Start", 8 },
437 { "Event FIFO 8 Size", 8 },
438 { "Event FIFO 9 Start", 8 },
439 { "Event FIFO 9 Size", 8 },
440 { "Event FIFO 10 Start", 8 },
441 { "Event FIFO 10 Size", 8 },
442 { "Event FIFO 11 Start", 8 },
443 { "Event FIFO 11 Size", 8 },
444 { "Event FIFO 12 Start", 8 },
445 { "Event FIFO 12 Size", 8 },
446 { "Event FIFO 13 Start", 8 },
447 { "Event FIFO 13 Size", 8 },
448 { "Event FIFO 14 Start", 8 },
449 { "Event FIFO 14 Size", 8 },
450 { "Event FIFO 15 Start", 8 },
451 { "Event FIFO 15 Size", 8 },
452 { "Event FIFO 16 Start", 8 },
453 { "Event FIFO 16 Size", 8 },
454 { "Reserved6", 80 }
455};
456
457struct request_data smart[] = {
458 { "Critical Warning", 1 },
459 { "Composite Temperature", 2 },
460 { "Available Spare", 1 },
461 { "Available Spare Threshold", 1 },
462 { "Percentage Used", 1 },
463 { "Reserved1", 26 },
464 { "Data Units Read", 16 },
465 { "Data Units Written", 16 },
466 { "Host Read Commands", 16 },
467 { "Host Write Commands", 16 },
468 { "Controller Busy Time", 16 },
469 { "Power Cycles", 16 },
470 { "Power On Hours", 16 },
471 { "Unsafe Shutdowns", 16 },
472 { "Media and Data Integrity Errors", 16 },
473 { "Number of Error Information Log Entries", 16 },
474 { "Warning Composite Temperature Time", 4 },
475 { "Critical Composite Temperature Time", 4 },
476 { "Temperature Sensor 1", 2 },
477 { "Temperature Sensor 2", 2 },
478 { "Temperature Sensor 3", 2 },
479 { "Temperature Sensor 4", 2 },
480 { "Temperature Sensor 5", 2 },
481 { "Temperature Sensor 6", 2 },
482 { "Temperature Sensor 7", 2 },
483 { "Temperature Sensor 8", 2 },
484 { "Thermal Management Temperature 1 Transition Count", 4 },
485 { "Thermal Management Temperature 2 Transition Count", 4 },
486 { "Total Time for Thermal Management Temperature 1", 4 },
487 { "Total Time for Thermal Management Temperature 2", 4 },
488 { "Reserved2", 280 }
489};
490
491struct request_data smart_extended[] = {
492 { "Physical Media Units Written", 16 },
493 { "Physical Media Units Read", 16 },
494 { "Bad User NAND Blocks Raw Count", 6 },
495 { "Bad User NAND Blocks Normalized Value", 2 },
496 { "Bad System NAND Blocks Raw Count", 6 },
497 { "Bad System NAND Blocks Normalized Value", 2 },
498 { "XOR Recovery Count", 8 },
499 { "Uncorrectable Read Error Count", 8 },
500 { "Soft ECC Error Count", 8 },
501 { "End to End Correction Counts Detected Errors", 4 },
502 { "End to End Correction Counts Corrected Errors", 4 },
503 { "System Data Percent Used", 1 },
504 { "Refresh Counts", 7 },
505 { "Maximum User Data Erase Count", 4 },
506 { "Minimum User Data Erase Count", 4 },
507 { "Number of thermal throttling events", 1 },
508 { "Current Throttling Status", 1 },
509 { "Errata Version Field", 1 },
510 { "Point Version Field", 2 },
511 { "Minor Version Field", 2 },
512 { "Major Version Field", 1 },
513 { "PCIe Correctable Error Count", 8 },
514 { "Incomplete Shutdowns", 4 },
515 { "Reserved1", 4 },
516 { "Percent Free Blocks", 1 },
517 { "Reserved2", 7 },
518 { "Capacitor Health", 2 },
519 { "NVMe Base Errata Version", 1 },
520 { "NVMe Command Set Errata Version", 1 },
521 { "Reserved3", 4 },
522 { "Unaligned IO", 8 },
523 { "Security Version Number", 8 },
524 { "Total NUSE", 8 },
525 { "PLP Start Count", 16 },
526 { "Endurance Estimate", 16 },
527 { "PCIe Link Retraining Count", 8 },
528 { "Power State Change Count", 8 },
529 { "Lowest Permitted Firmware Revision", 8 },
530 { "Reserved4", 278 },
531 { "Log Page Version", 2 },
532 { "Log page GUID", GUID_LEN16 }
533};
534
535#ifdef CONFIG_JSONC
536void json_add_formatted_u32_str(struct json_object *pobject, const char *msg, unsigned int pdata)
537{
538 char data_str[70] = { 0 };
539
540 sprintf(data_str, "0x%x", pdata);
541 json_object_add_value_string(pobject, msg, data_str);
542}
543
544void json_add_formatted_var_size_str(struct json_object *pobject, const char *msg, __u8 *pdata,
545 unsigned int data_size)
546{
547 char *description_str = NULL((void*)0);
548 char temp_buffer[3] = { 0 };
549
550 /* Allocate 2 chars for each value in the data + 2 bytes for the null terminator */
551 description_str = (char *) calloc(1, data_size*2 + 2);
552
553 for (size_t i = 0; i < data_size; ++i) {
554 sprintf(temp_buffer, "%02X", pdata[i]);
555 strcat(description_str, temp_buffer);
556 }
557
558 json_object_add_value_string(pobject, msg, description_str);
559 free(description_str);
560}
561#endif /* CONFIG_JSONC */
562
563int get_telemetry_das_offset_and_size(
564 struct nvme_ocp_telemetry_common_header *ptelemetry_common_header,
565 struct nvme_ocp_telemetry_offsets *ptelemetry_das_offset)
566{
567 if (NULL((void*)0) == ptelemetry_common_header || NULL((void*)0) == ptelemetry_das_offset) {
568 nvme_show_error("Invalid input arguments.")nvme_show_message(1, "Invalid input arguments.");
569 return -1;
570 }
571
572 if (ptelemetry_common_header->log_id == NVME_LOG_LID_TELEMETRY_HOST)
573 ptelemetry_das_offset->header_size =
574 sizeof(struct nvme_ocp_telemetry_host_initiated_header);
575 else if (ptelemetry_common_header->log_id == NVME_LOG_LID_TELEMETRY_CTRL)
576 ptelemetry_das_offset->header_size =
577 sizeof(struct nvme_ocp_telemetry_controller_initiated_header);
578 else
579 return -1;
580
581 ptelemetry_das_offset->da1_start_offset = ptelemetry_das_offset->header_size;
582 ptelemetry_das_offset->da1_size = ptelemetry_common_header->da1_last_block *
583 OCP_TELEMETRY_DATA_BLOCK_SIZE512;
584
585 ptelemetry_das_offset->da2_start_offset = ptelemetry_das_offset->da1_start_offset +
586 ptelemetry_das_offset->da1_size;
587 ptelemetry_das_offset->da2_size =
588 (ptelemetry_common_header->da2_last_block -
589 ptelemetry_common_header->da1_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE512;
590
591 ptelemetry_das_offset->da3_start_offset = ptelemetry_das_offset->da2_start_offset +
592 ptelemetry_das_offset->da2_size;
593 ptelemetry_das_offset->da3_size =
594 (ptelemetry_common_header->da3_last_block -
595 ptelemetry_common_header->da2_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE512;
596
597 ptelemetry_das_offset->da4_start_offset = ptelemetry_das_offset->da3_start_offset +
598 ptelemetry_das_offset->da3_size;
599 ptelemetry_das_offset->da4_size =
600 (ptelemetry_common_header->da4_last_block -
601 ptelemetry_common_header->da3_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE512;
602
603 return 0;
604}
605
606int get_statistic_id_ascii_string(int identifier, char *description)
607{
608 if (!pstring_buffer || !description)
609 return -1;
610
611 struct nvme_ocp_telemetry_string_header *pocp_ts_header =
612 (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
613
614 //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
615 //So multiplying with sizeof(DWORD)
616 unsigned long long sits_table_size = (pocp_ts_header->sitsz) * SIZE_OF_DWORD4;
617
618 //Calculating number of entries present in all 3 tables
619 int sits_entries = (int)sits_table_size /
620 sizeof(struct nvme_ocp_statistics_identifier_string_table);
621
622 for (int sits_entry = 0; sits_entry < sits_entries; sits_entry++) {
623 struct nvme_ocp_statistics_identifier_string_table
624 *peach_statistic_entry =
625 (struct nvme_ocp_statistics_identifier_string_table *)
626 (pstring_buffer + (pocp_ts_header->sits * SIZE_OF_DWORD4) +
627 (sits_entry *
628 sizeof(struct nvme_ocp_statistics_identifier_string_table)));
629
630 if (identifier == (int)peach_statistic_entry->vs_statistic_identifier) {
631 char *pdescription = (char *)(pstring_buffer +
632 (pocp_ts_header->ascts * SIZE_OF_DWORD4) +
633 (peach_statistic_entry->ascii_id_offset *
634 SIZE_OF_DWORD4));
635
636 memcpy(description, pdescription,
637 peach_statistic_entry->ascii_id_length + 1);
638
639 return 0;
640 }
641 }
642
643 // If ASCII string isn't found, see in our internal Map
644 // for 2.5 Spec defined strings
645 if (identifier <= 0x6F) {
646 strcpy(description, statistic_identifiers_map[identifier].description);
647 return 0;
648 }
649
650 return -1;
651}
652
653int get_event_id_ascii_string(int identifier, int debug_event_class, char *description)
654{
655 if (pstring_buffer == NULL((void*)0))
656 return -1;
657
658 struct nvme_ocp_telemetry_string_header *pocp_ts_header =
659 (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
660
661 //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
662 //So multiplying with sizeof(DWORD)
663 unsigned long long ests_table_size = (pocp_ts_header->estsz) * SIZE_OF_DWORD4;
664
665 //Calculating number of entries present in all 3 tables
666 int ests_entries = (int)ests_table_size / sizeof(struct nvme_ocp_event_string_table);
667
668 for (int ests_entry = 0; ests_entry < ests_entries; ests_entry++) {
669 struct nvme_ocp_event_string_table *peach_event_entry =
670 (struct nvme_ocp_event_string_table *)
671 (pstring_buffer + (pocp_ts_header->ests * SIZE_OF_DWORD4) +
672 (ests_entry * sizeof(struct nvme_ocp_event_string_table)));
673
674 if (identifier == (int)peach_event_entry->event_identifier &&
675 debug_event_class == (int)peach_event_entry->debug_event_class) {
676 char *pdescription = (char *)(pstring_buffer +
677 (pocp_ts_header->ascts * SIZE_OF_DWORD4) +
678 (peach_event_entry->ascii_id_offset * SIZE_OF_DWORD4));
679
680 memcpy(description, pdescription,
681 peach_event_entry->ascii_id_length + 1);
682 return 0;
683 }
684 }
685
686 return -1;
687}
688
689int get_vu_event_id_ascii_string(int identifier, int debug_event_class, char *description)
690{
691 if (pstring_buffer == NULL((void*)0))
692 return -1;
693
694 struct nvme_ocp_telemetry_string_header *pocp_ts_header =
695 (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
696
697 //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
698 //So multiplying with sizeof(DWORD)
699 unsigned long long vuests_table_size = (pocp_ts_header->vu_estsz) * SIZE_OF_DWORD4;
700
701 //Calculating number of entries present in all 3 tables
702 int vu_ests_entries = (int)vuests_table_size /
703 sizeof(struct nvme_ocp_vu_event_string_table);
704
705 for (int vu_ests_entry = 0; vu_ests_entry < vu_ests_entries; vu_ests_entry++) {
706 struct nvme_ocp_vu_event_string_table *peach_vu_event_entry =
707 (struct nvme_ocp_vu_event_string_table *)
708 (pstring_buffer + (pocp_ts_header->vu_ests * SIZE_OF_DWORD4) +
709 (vu_ests_entry * sizeof(struct nvme_ocp_vu_event_string_table)));
710
711 if (identifier == (int)peach_vu_event_entry->vu_event_identifier &&
712 debug_event_class ==
713 (int)peach_vu_event_entry->debug_event_class) {
714 char *pdescription = (char *)(pstring_buffer +
715 (pocp_ts_header->ascts * SIZE_OF_DWORD4) +
716 (peach_vu_event_entry->ascii_id_offset * SIZE_OF_DWORD4));
717
718 memcpy(description, pdescription,
719 peach_vu_event_entry->ascii_id_length + 1);
720 return 0;
721 }
722 }
723
724 return -1;
725}
726
727int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug_event_class,
728 enum ocp_telemetry_string_tables string_table, char *description)
729{
730 if (pstring_buffer == NULL((void*)0))
731 return -1;
732
733 if (event_fifo_num != 0) {
734 struct nvme_ocp_telemetry_string_header *pocp_ts_header =
735 (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
736
737 if (*pocp_ts_header->fifo_ascii_string[event_fifo_num-1] != '\0')
738 memcpy(description, pocp_ts_header->fifo_ascii_string[event_fifo_num-1],
739 16);
740 else
741 description = "";
742
743 return 0;
744 }
745
746 if (string_table == STATISTICS_IDENTIFIER_STRING)
747 get_statistic_id_ascii_string(identifier, description);
748 else if (string_table == EVENT_STRING && debug_event_class < 0x80)
749 get_event_id_ascii_string(identifier, debug_event_class, description);
750 else if (string_table == VU_EVENT_STRING || debug_event_class >= 0x80)
751 get_vu_event_id_ascii_string(identifier, debug_event_class, description);
752
753 return 0;
754}
755
756#ifdef CONFIG_JSONC
757int parse_time_stamp_event(
758 struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
759 struct json_object *pevent_descriptor_obj,
760 __u8 *pevent_specific_data,
761 struct json_object *pevent_fifos_object,
762 FILE *fp)
763{
764 struct nvme_ocp_time_stamp_dbg_evt_class_format *ptime_stamp_event =
765 (struct nvme_ocp_time_stamp_dbg_evt_class_format *) pevent_specific_data;
766 struct nvme_ocp_common_dbg_evt_class_vu_data *ptime_stamp_event_vu_data = NULL((void*)0);
767 __u16 vu_event_id = 0;
768 __u8 *pdata = NULL((void*)0);
769 char description_str[256] = "";
770 unsigned int vu_data_size = 0;
771 bool_Bool vu_data_present = false0;
772
773 if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) >
774 sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format)) {
775 vu_data_present = true1;
776 vu_data_size =
777 ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) -
778 (sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format) +
779 SIZE_OF_VU_EVENT_ID2));
780
781 ptime_stamp_event_vu_data =
782 (struct nvme_ocp_common_dbg_evt_class_vu_data *)((char *)ptime_stamp_event +
783 sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format));
784 vu_event_id = le16_to_cpu(ptime_stamp_event_vu_data->vu_event_identifier);
785 pdata = (__u8 *)&(ptime_stamp_event_vu_data->data);
786
787 parse_ocp_telemetry_string_log(0, vu_event_id,
788 pevent_descriptor->debug_event_class_type,
789 VU_EVENT_STRING, description_str);
790 } else if (pevent_descriptor->event_data_size < 2)
791 return -1;
792
793 if (pevent_fifos_object != NULL((void*)0)) {
794 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data",
795 ptime_stamp_event->time_stamp, DATA_SIZE_88);
796 if (vu_data_present) {
797 json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier",
798 vu_event_id);
799 json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String",
800 description_str);
801 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata,
802 vu_data_size);
803 }
804 } else {
805 if (fp) {
806 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
807 ptime_stamp_event->time_stamp, DATA_SIZE_88, fp);
808 if (vu_data_present) {
809 fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
810 fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
811 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
812 }
813 } else {
814 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
815 ptime_stamp_event->time_stamp, DATA_SIZE_88, fp);
816 if (vu_data_present) {
817 printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
818 printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
819 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
820 }
821 }
822 }
823
824 return 0;
825}
826
827int parse_pcie_event(
828 struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
829 struct json_object *pevent_descriptor_obj,
830 __u8 *pevent_specific_data,
831 struct json_object *pevent_fifos_object,
832 FILE *fp)
833{
834 struct nvme_ocp_pcie_dbg_evt_class_format *ppcie_event =
835 (struct nvme_ocp_pcie_dbg_evt_class_format *) pevent_specific_data;
836 struct nvme_ocp_common_dbg_evt_class_vu_data *ppcie_event_vu_data = NULL((void*)0);
837 __u16 vu_event_id = 0;
838 __u8 *pdata = NULL((void*)0);
839 char description_str[256] = "";
840 unsigned int vu_data_size = 0;
841 bool_Bool vu_data_present = false0;
842
843 if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) >
844 sizeof(struct nvme_ocp_pcie_dbg_evt_class_format)) {
845 vu_data_present = true1;
846 vu_data_size =
847 ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) -
848 (sizeof(struct nvme_ocp_pcie_dbg_evt_class_format) +
849 SIZE_OF_VU_EVENT_ID2));
850
851 ppcie_event_vu_data =
852 (struct nvme_ocp_common_dbg_evt_class_vu_data *)((char *)ppcie_event +
853 sizeof(struct nvme_ocp_pcie_dbg_evt_class_format));
854 vu_event_id = le16_to_cpu(ppcie_event_vu_data->vu_event_identifier);
855 pdata = (__u8 *)&(ppcie_event_vu_data->data);
856
857 parse_ocp_telemetry_string_log(0, vu_event_id,
858 pevent_descriptor->debug_event_class_type,
859 VU_EVENT_STRING, description_str);
860 } else if (pevent_descriptor->event_data_size < 1)
861 return -1;
862
863 if (pevent_fifos_object != NULL((void*)0)) {
864 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data",
865 ppcie_event->pCIeDebugEventData, DATA_SIZE_44);
866 if (vu_data_present) {
867 json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier",
868 vu_event_id);
869 json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String",
870 description_str);
871 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata,
872 vu_data_size);
873 }
874 } else {
875 if (fp) {
876 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
877 ppcie_event->pCIeDebugEventData, DATA_SIZE_44, fp);
878 if (vu_data_present) {
879 fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
880 fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
881 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
882 }
883 } else {
884 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
885 ppcie_event->pCIeDebugEventData, DATA_SIZE_44, fp);
886 if (vu_data_present) {
887 printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
888 printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
889 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
890 }
891 }
892 }
893
894 return 0;
895}
896
897int parse_nvme_event(
898 struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
899 struct json_object *pevent_descriptor_obj,
900 __u8 *pevent_specific_data,
901 struct json_object *pevent_fifos_object,
902 FILE *fp)
903{
904 struct nvme_ocp_nvme_dbg_evt_class_format *pnvme_event =
905 (struct nvme_ocp_nvme_dbg_evt_class_format *) pevent_specific_data;
906 struct nvme_ocp_common_dbg_evt_class_vu_data *pnvme_event_vu_data = NULL((void*)0);
907 __u16 vu_event_id = 0;
908 __u8 *pdata = NULL((void*)0);
909 char description_str[256] = "";
910 unsigned int vu_data_size = 0;
911 bool_Bool vu_data_present = false0;
912
913 if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) >
914 sizeof(struct nvme_ocp_nvme_dbg_evt_class_format)) {
915 vu_data_present = true1;
916 vu_data_size =
917 ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) -
918 (sizeof(struct nvme_ocp_nvme_dbg_evt_class_format) +
919 SIZE_OF_VU_EVENT_ID2));
920 pnvme_event_vu_data =
921 (struct nvme_ocp_common_dbg_evt_class_vu_data *)((char *)pnvme_event +
922 sizeof(struct nvme_ocp_nvme_dbg_evt_class_format));
923
924 vu_event_id = le16_to_cpu(pnvme_event_vu_data->vu_event_identifier);
925 pdata = (__u8 *)&(pnvme_event_vu_data->data);
926
927 parse_ocp_telemetry_string_log(0, vu_event_id,
928 pevent_descriptor->debug_event_class_type,
929 VU_EVENT_STRING,
930 description_str);
931 } else if (pevent_descriptor->event_data_size < 2)
932 return -1;
933
934 if (pevent_fifos_object != NULL((void*)0)) {
935 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data",
936 pnvme_event->nvmeDebugEventData, DATA_SIZE_88);
937 if (vu_data_present) {
938 json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier",
939 vu_event_id);
940 json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String",
941 description_str);
942 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata,
943 vu_data_size);
944 }
945 } else {
946 if (fp) {
947 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
948 pnvme_event->nvmeDebugEventData, DATA_SIZE_88, fp);
949 if (vu_data_present) {
950 fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
951 fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
952 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
953 }
954 } else {
955 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
956 pnvme_event->nvmeDebugEventData, DATA_SIZE_88, fp);
957 if (vu_data_present) {
958 printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
959 printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
960 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
961 }
962 }
963 }
964
965 return 0;
966}
967
968void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
969 struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
970 struct json_object *pevent_fifos_object, FILE *fp)
971{
972 if (pevent_specific_data) {
973 struct nvme_ocp_common_dbg_evt_class_vu_data *pcommon_debug_event_vu_data =
974 (struct nvme_ocp_common_dbg_evt_class_vu_data *) pevent_specific_data;
975
976 __u16 vu_event_id = le16_to_cpu(pcommon_debug_event_vu_data->vu_event_identifier);
977 char description_str[256] = "";
978 __u8 *pdata = (__u8 *)&(pcommon_debug_event_vu_data->data);
979
980 unsigned int vu_data_size = ((pevent_descriptor->event_data_size *
981 SIZE_OF_DWORD4) - SIZE_OF_VU_EVENT_ID2);
982
983 parse_ocp_telemetry_string_log(0, vu_event_id,
984 pevent_descriptor->debug_event_class_type,
985 VU_EVENT_STRING, description_str);
986
987 if (pevent_fifos_object != NULL((void*)0)) {
988 json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier",
989 vu_event_id);
990 json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String",
991 description_str);
992 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata,
993 vu_data_size);
994 } else {
995 if (fp) {
996 fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
997 fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
998 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
999 } else {
1000 printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
1001 printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
1002 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
1003 }
1004 }
1005 }
1006}
1007
1008int parse_media_wear_event(
1009 struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
1010 struct json_object *pevent_descriptor_obj,
1011 __u8 *pevent_specific_data,
1012 struct json_object *pevent_fifos_object,
1013 FILE *fp)
1014{
1015 struct nvme_ocp_media_wear_dbg_evt_class_format *pmedia_wear_event =
1016 (struct nvme_ocp_media_wear_dbg_evt_class_format *) pevent_specific_data;
1017 struct nvme_ocp_common_dbg_evt_class_vu_data *pmedia_wear_event_vu_data = NULL((void*)0);
1018
1019 __u16 vu_event_id = 0;
1020 __u8 *pdata = NULL((void*)0);
1021 char description_str[256] = "";
1022 unsigned int vu_data_size = 0;
1023 bool_Bool vu_data_present = false0;
1024
1025 if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) >
1026 sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format)) {
1027 vu_data_present = true1;
1028 vu_data_size =
1029 ((pevent_descriptor->event_data_size * SIZE_OF_DWORD4) -
1030 (sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format) +
1031 SIZE_OF_VU_EVENT_ID2));
1032
1033 pmedia_wear_event_vu_data =
1034 (struct nvme_ocp_common_dbg_evt_class_vu_data *)((char *)pmedia_wear_event +
1035 sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format));
1036 vu_event_id = le16_to_cpu(pmedia_wear_event_vu_data->vu_event_identifier);
1037 pdata = (__u8 *)&(pmedia_wear_event_vu_data->data);
1038
1039 parse_ocp_telemetry_string_log(0, vu_event_id,
1040 pevent_descriptor->debug_event_class_type,
1041 VU_EVENT_STRING,
1042 description_str);
1043 } else if (pevent_descriptor->event_data_size < 3)
1044 return -1;
1045
1046 if (pevent_fifos_object != NULL((void*)0)) {
1047 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA"Class Specific Data",
1048 pmedia_wear_event->currentMediaWear, DATA_SIZE_1212);
1049 if (vu_data_present) {
1050 json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING"VU Event Identifier",
1051 vu_event_id);
1052 json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING"VU Event String",
1053 description_str);
1054 json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA"VU Data", pdata,
1055 vu_data_size);
1056 }
1057 } else {
1058 if (fp) {
1059 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
1060 pmedia_wear_event->currentMediaWear, DATA_SIZE_1212, fp);
1061 if (vu_data_present) {
1062 fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
1063 fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
1064 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
1065 }
1066 } else {
1067 print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA"Class Specific Data",
1068 pmedia_wear_event->currentMediaWear, DATA_SIZE_1212, NULL((void*)0));
1069 if (vu_data_present) {
1070 printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING"VU Event Identifier", vu_event_id);
1071 printf("%s: %s\n", STR_VU_EVENT_STRING"VU Event String", description_str);
1072 print_formatted_var_size_str(STR_VU_DATA"VU Data", pdata, vu_data_size, fp);
1073 }
1074 }
1075 }
1076
1077 return 0;
1078}
1079
1080int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
1081 struct json_object *pevent_fifos_object, unsigned char *pstring_buffer,
1082 struct nvme_ocp_telemetry_offsets *poffsets, __u64 fifo_size, FILE *fp)
1083{
1084 if (NULL((void*)0) == pfifo_start || NULL((void*)0) == poffsets) {
1085 nvme_show_error("Input buffer was NULL")nvme_show_message(1, "Input buffer was NULL");
1086 return -1;
1087 }
1088
1089 int status = 0, ret = 0;
1090 unsigned int event_fifo_number = fifo_num + 1;
1091 char *description = (char *)malloc((40 + 1) * sizeof(char));
1092
1093 memset(description, 0, sizeof(40));
1094
1095 status =
1096 parse_ocp_telemetry_string_log(event_fifo_number, 0, 0, EVENT_STRING, description);
1097
1098 if (status != 0) {
1099 nvme_show_error("Failed to get C9 String. status: %d", status)nvme_show_message(1, "Failed to get C9 String. status: %d", status
)
;
1100 ret = -1;
1101 goto free_desc;
1102 }
1103
1104 char event_fifo_name[100] = {0};
1105
1106 snprintf(event_fifo_name, sizeof(event_fifo_name), "%s%d%s%s", "EVENT FIFO ",
1107 event_fifo_number, " - ", description);
1108
1109 struct json_object *pevent_fifo_array = NULL((void*)0);
1110
1111 if (pevent_fifos_object != NULL((void*)0))
1112 pevent_fifo_array = json_create_array()json_object_new_array();
1113 else {
1114 char buffer[1024] = {0};
1115
1116 sprintf(buffer, "%s%s\n%s", STR_LINE"==============================================================================\n", event_fifo_name, STR_LINE"==============================================================================\n");
1117 if (fp)
1118 fprintf(fp, "%s", buffer);
1119 else
1120 printf("%s", buffer);
1121 }
1122
1123 int offset_to_move = 0;
1124 unsigned int event_des_size = sizeof(struct nvme_ocp_telemetry_event_descriptor);
1125
1126 while ((fifo_size > 0) && (offset_to_move < fifo_size)) {
1127 struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor =
1128 (struct nvme_ocp_telemetry_event_descriptor *)
1129 (pfifo_start + offset_to_move);
1130
1131 /* check if at the end of the list */
1132 if (pevent_descriptor->debug_event_class_type == RESERVED_CLASS_TYPE)
1133 break;
1134
1135 __u8 *pevent_specific_data = NULL((void*)0);
1136 __u16 event_id = 0;
1137 char description_str[256] = "";
1138 unsigned int data_size = 0;
1139
1140 if (pevent_descriptor != NULL((void*)0) &&
1141 pevent_descriptor->event_data_size >= 0 &&
1142 pevent_descriptor->debug_event_class_type !=
1143 STATISTIC_SNAPSHOT_CLASS_TYPE) {
1144 event_des_size = sizeof(struct nvme_ocp_telemetry_event_descriptor);
1145 /* Data is present in the form of DWORDS,
1146 * So multiplying with sizeof(DWORD)
1147 */
1148 data_size = pevent_descriptor->event_data_size *
1149 SIZE_OF_DWORD4;
1150
1151 if (pevent_descriptor != NULL((void*)0) && pevent_descriptor->event_data_size > 0)
1152 pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size;
1153
1154 event_id = le16_to_cpu(pevent_descriptor->event_id);
1155
1156 parse_ocp_telemetry_string_log(0, event_id,
1157 pevent_descriptor->debug_event_class_type, EVENT_STRING,
1158 description_str);
1159
1160 struct json_object *pevent_descriptor_obj =
1161 ((pevent_fifos_object != NULL((void*)0))?json_create_object()json_object_new_object():NULL((void*)0));
1162
1163 if (pevent_descriptor_obj != NULL((void*)0)) {
1164 json_add_formatted_u32_str(pevent_descriptor_obj,
1165 STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type",
1166 pevent_descriptor->debug_event_class_type);
1167 json_add_formatted_u32_str(pevent_descriptor_obj,
1168 STR_EVENT_IDENTIFIER"Event Identifier", event_id);
1169 json_object_add_value_string(pevent_descriptor_obj,
1170 STR_EVENT_STRING"Event String", description_str);
1171 json_add_formatted_u32_str(pevent_descriptor_obj,
1172 STR_EVENT_DATA_SIZE"Event Data Size", pevent_descriptor->event_data_size);
1173
1174 if (pevent_descriptor->debug_event_class_type >= 0x80)
1175 json_add_formatted_var_size_str(pevent_descriptor_obj,
1176 STR_VU_DATA"VU Data", pevent_specific_data, data_size);
1177 } else {
1178 if (fp) {
1179 fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type",
1180 pevent_descriptor->debug_event_class_type);
1181 fprintf(fp, "%s: 0x%x\n", STR_EVENT_IDENTIFIER"Event Identifier",
1182 event_id);
1183 fprintf(fp, "%s: %s\n", STR_EVENT_STRING"Event String", description_str);
1184 fprintf(fp, "%s: 0x%x\n", STR_EVENT_DATA_SIZE"Event Data Size",
1185 pevent_descriptor->event_data_size);
1186 } else {
1187 printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type",
1188 pevent_descriptor->debug_event_class_type);
1189 printf("%s: 0x%x\n", STR_EVENT_IDENTIFIER"Event Identifier",
1190 event_id);
1191 printf("%s: %s\n", STR_EVENT_STRING"Event String", description_str);
1192 printf("%s: 0x%x\n", STR_EVENT_DATA_SIZE"Event Data Size",
1193 pevent_descriptor->event_data_size);
1194 }
1195
1196 if (pevent_descriptor->debug_event_class_type >= 0x80)
1197 print_formatted_var_size_str(STR_VU_DATA"VU Data",
1198 pevent_specific_data, data_size, fp);
1199 }
1200
1201 switch (pevent_descriptor->debug_event_class_type) {
1202 case TIME_STAMP_CLASS_TYPE:
1203 ret = parse_time_stamp_event(pevent_descriptor,
1204 pevent_descriptor_obj,
1205 pevent_specific_data,
1206 pevent_fifos_object,
1207 fp);
1208 break;
1209 case PCIE_CLASS_TYPE:
1210 ret = parse_pcie_event(pevent_descriptor,
1211 pevent_descriptor_obj,
1212 pevent_specific_data,
1213 pevent_fifos_object,
1214 fp);
1215 break;
1216 case NVME_CLASS_TYPE:
1217 ret = parse_nvme_event(pevent_descriptor,
1218 pevent_descriptor_obj,
1219 pevent_specific_data,
1220 pevent_fifos_object,
1221 fp);
1222 break;
1223 case RESET_CLASS_TYPE:
1224 case BOOT_SEQUENCE_CLASS_TYPE:
1225 case FIRMWARE_ASSERT_CLASS_TYPE:
1226 case TEMPERATURE_CLASS_TYPE:
1227 case MEDIA_CLASS_TYPE:
1228 parse_common_event(pevent_descriptor,
1229 pevent_descriptor_obj,
1230 pevent_specific_data,
1231 pevent_fifos_object,
1232 fp);
1233 ret = 0;
1234 break;
1235 case MEDIA_WEAR_CLASS_TYPE:
1236 ret = parse_media_wear_event(pevent_descriptor,
1237 pevent_descriptor_obj,
1238 pevent_specific_data,
1239 pevent_fifos_object,
1240 fp);
1241 break;
1242 case RESERVED_CLASS_TYPE:
1243 default:
1244 break;
1245 }
1246
1247 if (ret) {
1248 nvme_show_error(nvme_show_message(1, "ERROR : OCP : Invalid NVMe Event FIFO entry\n"
)
1249 "ERROR : OCP : Invalid NVMe Event FIFO entry\n")nvme_show_message(1, "ERROR : OCP : Invalid NVMe Event FIFO entry\n"
)
;
1250 nvme_show_error(nvme_show_message(1, "FIFO: %d, offset: 0x%x\n", fifo_num, offset_to_move
)
1251 "FIFO: %d, offset: 0x%x\n",nvme_show_message(1, "FIFO: %d, offset: 0x%x\n", fifo_num, offset_to_move
)
1252 fifo_num, offset_to_move)nvme_show_message(1, "FIFO: %d, offset: 0x%x\n", fifo_num, offset_to_move
)
;
1253 nvme_show_error(nvme_show_message(1, "Type: 0x%x, ID: 0x%x, Size: 0x%x\n", pevent_descriptor
->debug_event_class_type, pevent_descriptor->event_id, pevent_descriptor
->event_data_size)
1254 "Type: 0x%x, ID: 0x%x, Size: 0x%x\n",nvme_show_message(1, "Type: 0x%x, ID: 0x%x, Size: 0x%x\n", pevent_descriptor
->debug_event_class_type, pevent_descriptor->event_id, pevent_descriptor
->event_data_size)
1255 pevent_descriptor->debug_event_class_type,nvme_show_message(1, "Type: 0x%x, ID: 0x%x, Size: 0x%x\n", pevent_descriptor
->debug_event_class_type, pevent_descriptor->event_id, pevent_descriptor
->event_data_size)
1256 pevent_descriptor->event_id,nvme_show_message(1, "Type: 0x%x, ID: 0x%x, Size: 0x%x\n", pevent_descriptor
->debug_event_class_type, pevent_descriptor->event_id, pevent_descriptor
->event_data_size)
1257 pevent_descriptor->event_data_size)nvme_show_message(1, "Type: 0x%x, ID: 0x%x, Size: 0x%x\n", pevent_descriptor
->debug_event_class_type, pevent_descriptor->event_id, pevent_descriptor
->event_data_size)
;
1258 goto free_desc;
1259 }
1260
1261 if (pevent_descriptor_obj != NULL((void*)0) && pevent_fifo_array != NULL((void*)0))
1262 json_array_add_value_object(pevent_fifo_array,json_object_array_add(pevent_fifo_array, pevent_descriptor_obj
)
1263 pevent_descriptor_obj)json_object_array_add(pevent_fifo_array, pevent_descriptor_obj
)
;
1264 else {
1265 if (fp)
1266 fprintf(fp, STR_LINE2"-----------------------------------------------------------------------------\n");
1267 else
1268 printf(STR_LINE2"-----------------------------------------------------------------------------\n");
1269 }
1270 } else if ((pevent_descriptor != NULL((void*)0)) &&
1271 (pevent_descriptor->debug_event_class_type ==
1272 STATISTIC_SNAPSHOT_CLASS_TYPE)) {
1273 parse_ocp_telemetry_string_log(0, event_id,
1274 pevent_descriptor->debug_event_class_type, EVENT_STRING,
1275 description_str);
1276
1277 struct json_object *pevent_descriptor_obj =
1278 ((pevent_fifos_object != NULL((void*)0)) ? json_create_object()json_object_new_object() : NULL((void*)0));
1279
1280 if (pevent_descriptor_obj != NULL((void*)0)) {
1281 json_add_formatted_u32_str(pevent_descriptor_obj,
1282 STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type",
1283 pevent_descriptor->debug_event_class_type);
1284 json_object_add_value_string(pevent_descriptor_obj,
1285 STR_EVENT_STRING"Event String", description_str);
1286 } else {
1287 if (fp) {
1288 fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type",
1289 pevent_descriptor->debug_event_class_type);
1290 fprintf(fp, "%s: %s\n", STR_EVENT_STRING"Event String", description_str);
1291 } else {
1292 printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE"Debug Event Class type",
1293 pevent_descriptor->debug_event_class_type);
1294 printf("%s: %s\n", STR_EVENT_STRING"Event String", description_str);
1295 }
1296 }
1297
1298 struct nvme_ocp_statistic_snapshot_evt_class_format
1299 *pStaticSnapshotEvent =
1300 (struct nvme_ocp_statistic_snapshot_evt_class_format *)
1301 pevent_descriptor;
1302
1303 event_des_size =
1304 sizeof(struct nvme_ocp_statistic_snapshot_evt_class_format);
1305 data_size =
1306 (le16_to_cpu((unsigned int)pStaticSnapshotEvent->stat_data_size) *
1307 SIZE_OF_DWORD4);
1308
1309 struct json_object *pstats_array =
1310 ((pevent_fifos_object != NULL((void*)0)) ? json_create_array()json_object_new_array() : NULL((void*)0));
1311
1312 if (pStaticSnapshotEvent != NULL((void*)0) &&
1313 pStaticSnapshotEvent->stat_data_size > 0) {
1314 __u8 *pstatistic_entry =
1315 (__u8 *)pStaticSnapshotEvent +
1316 sizeof(struct nvme_ocp_telemetry_event_descriptor);
1317
1318 parse_statistic(
1319 (struct nvme_ocp_telemetry_statistic_descriptor *)
1320 pstatistic_entry,
1321 pstats_array,
1322 fp);
1323 }
1324 } else {
1325 if (fp)
1326 fprintf(fp, "Unknown or null event class %p\n", pevent_descriptor);
1327 else
1328 printf("Unknown or null event class %p\n", pevent_descriptor);
1329
1330 break;
1331 }
1332
1333 offset_to_move += (data_size + event_des_size);
1334 }
1335
1336 if (pevent_fifos_object != NULL((void*)0) && pevent_fifo_array != NULL((void*)0))
1337 json_object_add_value_array(pevent_fifos_object, event_fifo_name,json_object_object_add(pevent_fifos_object, event_fifo_name, pevent_fifo_array
)
1338 pevent_fifo_array)json_object_object_add(pevent_fifos_object, event_fifo_name, pevent_fifo_array
)
;
1339
1340free_desc:
1341 free(description);
1342 return ret;
1343}
1344
1345int parse_event_fifos(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
1346 FILE *fp)
1347{
1348 if (poffsets == NULL((void*)0)) {
1349 nvme_show_error("Input buffer was NULL")nvme_show_message(1, "Input buffer was NULL");
1350 return -1;
1351 }
1352
1353 struct json_object *pevent_fifos_object = NULL((void*)0);
1354
1355 if (root != NULL((void*)0))
1356 pevent_fifos_object = json_create_object()json_object_new_object();
1357
1358 __u8 *pda1_header_offset = ptelemetry_buffer + poffsets->da1_start_offset;//512
1359 __u8 *pda2_offset = ptelemetry_buffer + poffsets->da2_start_offset;
1360 struct nvme_ocp_header_in_da1 *pda1_header = (struct nvme_ocp_header_in_da1 *)
1361 pda1_header_offset;
1362 struct nvme_ocp_event_fifo_data event_fifo[MAX_NUM_FIFOS16];
1363
1364 for (int fifo_num = 0; fifo_num < MAX_NUM_FIFOS16; fifo_num++) {
1365 event_fifo[fifo_num].event_fifo_num = fifo_num;
1366 event_fifo[fifo_num].event_fifo_da = pda1_header->event_fifo_da[fifo_num];
1367 event_fifo[fifo_num].event_fifo_start =
1368 pda1_header->fifo_offsets[fifo_num].event_fifo_start;
1369 event_fifo[fifo_num].event_fifo_size =
1370 pda1_header->fifo_offsets[fifo_num].event_fifo_size;
1371 }
1372
1373 //Parse all the FIFOs DA wise
1374 for (int fifo_no = 0; fifo_no < MAX_NUM_FIFOS16; fifo_no++) {
1375 if (event_fifo[fifo_no].event_fifo_da == poffsets->data_area) {
1376 __u64 fifo_offset =
1377 (event_fifo[fifo_no].event_fifo_start * SIZE_OF_DWORD4);
1378 __u64 fifo_size =
1379 (event_fifo[fifo_no].event_fifo_size * SIZE_OF_DWORD4);
1380 __u64 da_size = (poffsets->data_area == 1) ?
1381 poffsets->da1_size : poffsets->da2_size;
1382 __u8 *pfifo_start = NULL((void*)0);
1383
1384 if (!fifo_size || fifo_offset + fifo_size > da_size) {
1385 nvme_show_error(nvme_show_message(1, "Invalid FIFO bounds for FIFO %d", fifo_no
)
1386 "Invalid FIFO bounds for FIFO %d",nvme_show_message(1, "Invalid FIFO bounds for FIFO %d", fifo_no
)
1387 fifo_no)nvme_show_message(1, "Invalid FIFO bounds for FIFO %d", fifo_no
)
;
1388 return -1;
1389 }
1390
1391 if (event_fifo[fifo_no].event_fifo_da == 1)
1392 pfifo_start = pda1_header_offset + fifo_offset;
1393 else if (event_fifo[fifo_no].event_fifo_da == 2)
1394 pfifo_start = pda2_offset + fifo_offset;
1395 else {
1396 nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area)nvme_show_message(1, "Unsupported Data Area:[%d]", poffsets->
data_area)
;
1397 return -1;
1398 }
1399
1400 int status = parse_event_fifo(fifo_no, pfifo_start, pevent_fifos_object,
1401 pstring_buffer, poffsets, fifo_size, fp);
1402
1403 if (status != 0) {
1404 nvme_show_error("Failed to parse Event FIFO. status:%d", status)nvme_show_message(1, "Failed to parse Event FIFO. status:%d",
status)
;
1405 return -1;
1406 }
1407 }
1408 }
1409
1410 if (pevent_fifos_object != NULL((void*)0) && root != NULL((void*)0)) {
1411 const char *data_area = (poffsets->data_area == 1 ? STR_DA_1_EVENT_FIFO_INFO"Data Area 1 Event FIFO info" :
1412 STR_DA_2_EVENT_FIFO_INFO"Data Area 2 Event FIFO info");
1413
1414 json_object_add_value_array(root, data_area, pevent_fifos_object)json_object_object_add(root, data_area, pevent_fifos_object);
1415 }
1416
1417 return 0;
1418}
1419
1420int parse_statistic(struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry,
1421 struct json_object *pstats_array, FILE *fp)
1422{
1423 if (pstatistic_entry == NULL((void*)0)) {
1424 nvme_show_error("Statistics Input buffer was NULL")nvme_show_message(1, "Statistics Input buffer was NULL");
1425 return -1;
1426 }
1427
1428 if (le16_to_cpu(pstatistic_entry->statistic_id) == STATISTICS_RESERVED_ID)
1429 /* End of statistics entries, return -1 to stop processing the buffer */
1430 return -1;
1431
1432 unsigned int data_size = pstatistic_entry->statistic_data_size * SIZE_OF_DWORD4;
1433 __u8 *pdata = (__u8 *)pstatistic_entry +
1434 sizeof(struct nvme_ocp_telemetry_statistic_descriptor);
1435 char description_str[256] = "";
1436
1437 parse_ocp_telemetry_string_log(0, pstatistic_entry->statistic_id, 0,
1438 STATISTICS_IDENTIFIER_STRING, description_str);
1439
1440 if (pstats_array != NULL((void*)0)) {
1441 struct json_object *pstatistics_object = json_create_object()json_object_new_object();
1442
1443 json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_IDENTIFIER"Statistics Identifier",
1444 pstatistic_entry->statistic_id);
1445 json_object_add_value_string(pstatistics_object, STR_STATISTICS_IDENTIFIER_STR"Statistic Identifier String",
1446 description_str);
1447 json_add_formatted_u32_str(pstatistics_object,
1448 STR_STATISTICS_INFO_BEHAVIOUR_TYPE"Statistics Info Behavior Type",
1449 pstatistic_entry->statistic_info_behaviour_type);
1450 json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_INFO_RESERVED"Statistics Info Reserved",
1451 pstatistic_entry->statistic_info_reserved);
1452 json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_IDENTIFIER"Namespace Identifier",
1453 pstatistic_entry->ns_info_nsid);
1454 json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_INFO_VALID"Namespace Information Valid",
1455 pstatistic_entry->ns_info_ns_info_valid);
1456 json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_DATA_SIZE"Statistic Data Size",
1457 pstatistic_entry->statistic_data_size);
1458 json_add_formatted_u32_str(pstatistics_object, STR_RESERVED"Reserved",
1459 pstatistic_entry->reserved);
1460 if (pstatistic_entry->statistic_id == MAX_DIE_BAD_BLOCK_ID) {
1461 json_add_formatted_u32_str(pstatistics_object,
1462 STR_STATISTICS_WORST_DIE_PERCENT"Worst die % of bad blocks",
1463 pdata[0]);
1464 json_add_formatted_u32_str(pstatistics_object,
1465 STR_STATISTICS_WORST_DIE_RAW"Worst die raw number of bad blocks",
1466 *(__u16 *)&pdata[2]);
1467 } else if (pstatistic_entry->statistic_id == MAX_NAND_CHANNEL_BAD_BLOCK_ID) {
1468 json_add_formatted_u32_str(pstatistics_object,
1469 STR_STATISTICS_WORST_NAND_CHANNEL_PERCENT"Worst NAND channel % of bad blocks",
1470 pdata[0]);
1471 json_add_formatted_u32_str(pstatistics_object,
1472 STR_STATISTICS_WORST_NAND_CHANNEL_RAW"Worst NAND channel number of bad blocks",
1473 *(__u16 *)&pdata[2]);
1474 } else if (pstatistic_entry->statistic_id == MIN_NAND_CHANNEL_BAD_BLOCK_ID) {
1475 json_add_formatted_u32_str(pstatistics_object,
1476 STR_STATISTICS_BEST_NAND_CHANNEL_PERCENT"Best NAND channel % of bad blocks",
1477 pdata[0]);
1478 json_add_formatted_u32_str(pstatistics_object,
1479 STR_STATISTICS_BEST_NAND_CHANNEL_RAW"Best NAND channel number of bad blocks",
1480 *(__u16 *)&pdata[2]);
1481 } else {
1482 json_add_formatted_var_size_str(pstatistics_object,
1483 STR_STATISTICS_SPECIFIC_DATA"Statistic Specific Data",
1484 pdata,
1485 data_size);
1486 }
1487
1488 if (pstatistics_object != NULL((void*)0))
1489 json_array_add_value_object(pstats_array, pstatistics_object)json_object_array_add(pstats_array, pstatistics_object);
1490 } else {
1491 if (fp) {
1492 fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_IDENTIFIER"Statistics Identifier",
1493 pstatistic_entry->statistic_id);
1494 fprintf(fp, "%s: %s\n", STR_STATISTICS_IDENTIFIER_STR"Statistic Identifier String", description_str);
1495 fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE"Statistics Info Behavior Type",
1496 pstatistic_entry->statistic_info_behaviour_type);
1497 fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED"Statistics Info Reserved",
1498 pstatistic_entry->statistic_info_reserved);
1499 fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER"Namespace Identifier",
1500 pstatistic_entry->ns_info_nsid);
1501 fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_INFO_VALID"Namespace Information Valid",
1502 pstatistic_entry->ns_info_ns_info_valid);
1503 fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_DATA_SIZE"Statistic Data Size",
1504 pstatistic_entry->statistic_data_size);
1505 fprintf(fp, "%s: 0x%x\n", STR_RESERVED"Reserved", pstatistic_entry->reserved);
1506 if (pstatistic_entry->statistic_id == MAX_DIE_BAD_BLOCK_ID) {
1507 fprintf(fp, "%s: 0x%02x\n", STR_STATISTICS_WORST_DIE_PERCENT"Worst die % of bad blocks",
1508 pdata[0]);
1509 fprintf(fp, "%s: 0x%04x\n", STR_STATISTICS_WORST_DIE_RAW"Worst die raw number of bad blocks",
1510 *(__u16 *)&pdata[2]);
1511 } else if (pstatistic_entry->statistic_id ==
1512 MAX_NAND_CHANNEL_BAD_BLOCK_ID) {
1513 fprintf(fp, "%s: 0x%02x\n",
1514 STR_STATISTICS_WORST_NAND_CHANNEL_PERCENT"Worst NAND channel % of bad blocks",
1515 pdata[0]);
1516 fprintf(fp, "%s: 0x%04x\n",
1517 STR_STATISTICS_WORST_NAND_CHANNEL_RAW"Worst NAND channel number of bad blocks",
1518 *(__u16 *)&pdata[2]);
1519 } else if (pstatistic_entry->statistic_id ==
1520 MIN_NAND_CHANNEL_BAD_BLOCK_ID) {
1521 fprintf(fp, "%s: 0x%02x\n",
1522 STR_STATISTICS_BEST_NAND_CHANNEL_PERCENT"Best NAND channel % of bad blocks",
1523 pdata[0]);
1524 fprintf(fp, "%s: 0x%04x\n",
1525 STR_STATISTICS_BEST_NAND_CHANNEL_RAW"Best NAND channel number of bad blocks",
1526 *(__u16 *)&pdata[2]);
1527 } else {
1528 print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA"Statistic Specific Data",
1529 pdata,
1530 data_size,
1531 fp);
1532 }
1533 fprintf(fp, STR_LINE2"-----------------------------------------------------------------------------\n");
1534 } else {
1535 printf("%s: 0x%x\n", STR_STATISTICS_IDENTIFIER"Statistics Identifier",
1536 pstatistic_entry->statistic_id);
1537 printf("%s: %s\n", STR_STATISTICS_IDENTIFIER_STR"Statistic Identifier String", description_str);
1538 printf("%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE"Statistics Info Behavior Type",
1539 pstatistic_entry->statistic_info_behaviour_type);
1540 printf("%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED"Statistics Info Reserved",
1541 pstatistic_entry->statistic_info_reserved);
1542 printf("%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER"Namespace Identifier",
1543 pstatistic_entry->ns_info_nsid);
1544 printf("%s: 0x%x\n", STR_NAMESPACE_INFO_VALID"Namespace Information Valid",
1545 pstatistic_entry->ns_info_ns_info_valid);
1546 printf("%s: 0x%x\n", STR_STATISTICS_DATA_SIZE"Statistic Data Size",
1547 pstatistic_entry->statistic_data_size);
1548 printf("%s: 0x%x\n", STR_RESERVED"Reserved", pstatistic_entry->reserved);
1549 if (pstatistic_entry->statistic_id == MAX_DIE_BAD_BLOCK_ID) {
1550 printf("%s: 0x%02x\n", STR_STATISTICS_WORST_DIE_PERCENT"Worst die % of bad blocks",
1551 pdata[0]);
1552 printf("%s: 0x%04x\n", STR_STATISTICS_WORST_DIE_RAW"Worst die raw number of bad blocks",
1553 *(__u16 *)&pdata[2]);
1554 } else if (pstatistic_entry->statistic_id ==
1555 MAX_NAND_CHANNEL_BAD_BLOCK_ID) {
1556 printf("%s: 0x%02x\n",
1557 STR_STATISTICS_WORST_NAND_CHANNEL_PERCENT"Worst NAND channel % of bad blocks",
1558 pdata[0]);
1559 printf("%s: 0x%04x\n",
1560 STR_STATISTICS_WORST_NAND_CHANNEL_RAW"Worst NAND channel number of bad blocks",
1561 *(__u16 *)&pdata[2]);
1562 } else if (pstatistic_entry->statistic_id ==
1563 MIN_NAND_CHANNEL_BAD_BLOCK_ID) {
1564 printf("%s: 0x%02x\n",
1565 STR_STATISTICS_BEST_NAND_CHANNEL_PERCENT"Best NAND channel % of bad blocks",
1566 pdata[0]);
1567 printf("%s: 0x%04x\n",
1568 STR_STATISTICS_BEST_NAND_CHANNEL_RAW"Best NAND channel number of bad blocks",
1569 *(__u16 *)&pdata[2]);
1570 } else {
1571 print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA"Statistic Specific Data",
1572 pdata,
1573 data_size,
1574 fp);
1575 }
1576 printf(STR_LINE2"-----------------------------------------------------------------------------\n");
1577 }
1578 }
1579
1580 return 0;
1581}
1582
1583int parse_statistics(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
1584 FILE *fp)
1585{
1586 if (poffsets == NULL((void*)0)) {
1587 nvme_show_error("Input buffer was NULL")nvme_show_message(1, "Input buffer was NULL");
1588 return -1;
1589 }
1590
1591 __u8 *pda1_ocp_header_offset = ptelemetry_buffer + poffsets->header_size;//512
1592 __u32 statistics_size = 0;
1593 __u32 stats_da_1_start_dw = 0, stats_da_1_size_dw = 0;
1594 __u32 stats_da_2_start_dw = 0, stats_da_2_size_dw = 0;
1595 __u8 *pstats_offset = NULL((void*)0);
1596 int parse_rc = 0;
1597
1598 if (poffsets->data_area == 1) {
1599 __u32 stats_da_1_start = *(__u32 *)(pda1_ocp_header_offset +
1600 offsetof(struct nvme_ocp_header_in_da1, da1_statistic_start)__builtin_offsetof(struct nvme_ocp_header_in_da1, da1_statistic_start
)
);
1601 __u32 stats_da_1_size = *(__u32 *)(pda1_ocp_header_offset +
1602 offsetof(struct nvme_ocp_header_in_da1, da1_statistic_size)__builtin_offsetof(struct nvme_ocp_header_in_da1, da1_statistic_size
)
);
1603
1604 //Data is present in the form of DWORDS, So multiplying with sizeof(DWORD)
1605 stats_da_1_start_dw = (stats_da_1_start * SIZE_OF_DWORD4);
1606 stats_da_1_size_dw = (stats_da_1_size * SIZE_OF_DWORD4);
1607
1608 pstats_offset = pda1_ocp_header_offset + stats_da_1_start_dw;
1609 statistics_size = stats_da_1_size_dw;
1610 } else if (poffsets->data_area == 2) {
1611 __u32 stats_da_2_start = *(__u32 *)(pda1_ocp_header_offset +
1612 offsetof(struct nvme_ocp_header_in_da1, da2_statistic_start)__builtin_offsetof(struct nvme_ocp_header_in_da1, da2_statistic_start
)
);
1613 __u32 stats_da_2_size = *(__u32 *)(pda1_ocp_header_offset +
1614 offsetof(struct nvme_ocp_header_in_da1, da2_statistic_size)__builtin_offsetof(struct nvme_ocp_header_in_da1, da2_statistic_size
)
);
1615
1616 stats_da_2_start_dw = (stats_da_2_start * SIZE_OF_DWORD4);
1617 stats_da_2_size_dw = (stats_da_2_size * SIZE_OF_DWORD4);
1618
1619 pstats_offset = pda1_ocp_header_offset + poffsets->da1_size + stats_da_2_start_dw;
1620 statistics_size = stats_da_2_size_dw;
1621 } else {
1622 nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area)nvme_show_message(1, "Unsupported Data Area:[%d]", poffsets->
data_area)
;
1623 return -1;
1624 }
1625
1626 struct json_object *pstats_array = ((root != NULL((void*)0)) ? json_create_array()json_object_new_array() : NULL((void*)0));
1627
1628 __u32 stat_des_size = sizeof(struct nvme_ocp_telemetry_statistic_descriptor);//8
1629 __u32 offset_to_move = 0;
1630
1631 while (((statistics_size > 0) && (offset_to_move < statistics_size))) {
1632 struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry =
1633 (struct nvme_ocp_telemetry_statistic_descriptor *)
1634 (pstats_offset + offset_to_move);
1635
1636 parse_rc = parse_statistic(pstatistic_entry, pstats_array, fp);
1637 if (parse_rc < 0)
1638 /* end of stats entries or null pointer, so break */
1639 break;
1640
1641 offset_to_move += (pstatistic_entry->statistic_data_size * SIZE_OF_DWORD4 +
1642 stat_des_size);
1643 }
1644
1645 if (root != NULL((void*)0) && pstats_array != NULL((void*)0)) {
1646 const char *pdata_area =
1647 (poffsets->data_area == 1 ? STR_DA_1_STATS"Data Area 1 Statistics" : STR_DA_2_STATS"Data Area 2 Statistics");
1648
1649 json_object_add_value_array(root, pdata_area, pstats_array)json_object_object_add(root, pdata_area, pstats_array);
1650 }
1651
1652 return 0;
1653}
1654
1655int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
1656{
1657 int status = 0;
1658 char file_path[PATH_MAX4096];
1659
1660 if (options->output_file != NULL((void*)0)) {
1
Assuming field 'output_file' is equal to NULL
2
Taking false branch
1661 sprintf(file_path, "%s.%s", options->output_file, "txt");
1662 FILE *fp = fopen(file_path, "w");
1663
1664 if (fp) {
1665 fprintf(fp, STR_LINE"==============================================================================\n");
1666 fprintf(fp, "%s\n", STR_LOG_PAGE_HEADER"Log Page Header");
1667 fprintf(fp, STR_LINE"==============================================================================\n");
1668 if (!strcmp(options->telemetry_type, "host")) {
1669 if ((ptelemetry_buffer == NULL((void*)0)) ||
1670 (ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header)
[0]))
== 0))
1671 printf("skip generic_structure_parser\n");
1672 else
1673 generic_structure_parser(ptelemetry_buffer,
1674 host_log_page_header,
1675 ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header)
[0]))
,
1676 NULL((void*)0), 0, fp);
1677 }
1678 else if (!strcmp(options->telemetry_type, "controller"))
1679 generic_structure_parser(ptelemetry_buffer,
1680 controller_log_page_header,
1681 ARRAY_SIZE(controller_log_page_header)(sizeof(controller_log_page_header) / sizeof((controller_log_page_header
)[0]))
, NULL((void*)0), 0, fp);
1682 fprintf(fp, STR_LINE"==============================================================================\n");
1683 fprintf(fp, "%s\n", STR_REASON_IDENTIFIER"Reason Identifier");
1684 fprintf(fp, STR_LINE"==============================================================================\n");
1685 __u8 *preason_identifier_offset = ptelemetry_buffer +
1686 offsetof(struct nvme_ocp_telemetry_host_initiated_header,__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header
, reason_id)
1687 reason_id)__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header
, reason_id)
;
1688
1689 generic_structure_parser(preason_identifier_offset, reason_identifier,
1690 ARRAY_SIZE(reason_identifier)(sizeof(reason_identifier) / sizeof((reason_identifier)[0])), NULL((void*)0), 0, fp);
1691
1692 fprintf(fp, STR_LINE"==============================================================================\n");
1693 fprintf(fp, "%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1"Telemetry Host-Initiated Data Block 1");
1694 fprintf(fp, STR_LINE"==============================================================================\n");
1695
1696 //Set DA to 1 and get offsets
1697 struct nvme_ocp_telemetry_offsets offsets = { 0 };
1698
1699 offsets.data_area = 1;// Default DA - DA1
1700
1701 struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
1702 (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
1703
1704 get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
1705
1706 __u8 *pda1_header_offset = ptelemetry_buffer +
1707 offsets.da1_start_offset;//512
1708
1709 generic_structure_parser(pda1_header_offset, ocp_header_in_da1,
1710 ARRAY_SIZE(ocp_header_in_da1)(sizeof(ocp_header_in_da1) / sizeof((ocp_header_in_da1)[0])), NULL((void*)0), 0, fp);
1711
1712 fprintf(fp, STR_LINE"==============================================================================\n");
1713 fprintf(fp, "%s\n", STR_SMART_HEALTH_INFO"SMART / Health Information Log(LID-02h)");
1714 fprintf(fp, STR_LINE"==============================================================================\n");
1715 __u8 *pda1_smart_offset = pda1_header_offset +
1716 offsetof(struct nvme_ocp_header_in_da1, smart_health_info)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info
)
;
1717 //512+512 =1024
1718
1719 generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart)(sizeof(smart) / sizeof((smart)[0])),
1720 NULL((void*)0), 0, fp);
1721
1722 fprintf(fp, STR_LINE"==============================================================================\n");
1723 fprintf(fp, "%s\n", STR_SMART_HEALTH_INTO_EXTENDED"SMART / Health Information Extended(LID-C0h)");
1724 fprintf(fp, STR_LINE"==============================================================================\n");
1725 __u8 *pda1_smart_ext_offset = pda1_header_offset +
1726 offsetof(struct nvme_ocp_header_in_da1,__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended
)
1727 smart_health_info_extended)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended
)
;
1728
1729 generic_structure_parser(pda1_smart_ext_offset, smart_extended,
1730 ARRAY_SIZE(smart_extended)(sizeof(smart_extended) / sizeof((smart_extended)[0])), NULL((void*)0), 0, fp);
1731
1732 fprintf(fp, STR_LINE"==============================================================================\n");
1733 fprintf(fp, "%s\n", STR_DA_1_STATS"Data Area 1 Statistics");
1734 fprintf(fp, STR_LINE"==============================================================================\n");
1735
1736 status = parse_statistics(NULL((void*)0), &offsets, fp);
1737 if (status != 0) {
1738 nvme_show_error("status: %d", status)nvme_show_message(1, "status: %d", status);
1739 fclose(fp);
1740 return -1;
1741 }
1742
1743 fprintf(fp, STR_LINE"==============================================================================\n");
1744 fprintf(fp, "%s\n", STR_DA_1_EVENT_FIFO_INFO"Data Area 1 Event FIFO info");
1745 fprintf(fp, STR_LINE"==============================================================================\n");
1746 status = parse_event_fifos(NULL((void*)0), &offsets, fp);
1747 if (status != 0) {
1748 fclose(fp);
1749 return -1;
1750 }
1751
1752 //Set the DA to 2
1753 if (options->data_area == 2) {
1754 offsets.data_area = 2;
1755 fprintf(fp, STR_LINE"==============================================================================\n");
1756 fprintf(fp, "%s\n", STR_DA_2_STATS"Data Area 2 Statistics");
1757 fprintf(fp, STR_LINE"==============================================================================\n");
1758 status = parse_statistics(NULL((void*)0), &offsets, fp);
1759
1760 if (status != 0) {
1761 nvme_show_error("status: %d", status)nvme_show_message(1, "status: %d", status);
1762 fclose(fp);
1763 return -1;
1764 }
1765
1766 fprintf(fp, STR_LINE"==============================================================================\n");
1767 fprintf(fp, "%s\n", STR_DA_2_EVENT_FIFO_INFO"Data Area 2 Event FIFO info");
1768 fprintf(fp, STR_LINE"==============================================================================\n");
1769 status = parse_event_fifos(NULL((void*)0), &offsets, fp);
1770 if (status != 0) {
1771 fclose(fp);
1772 return -1;
1773 }
1774 }
1775
1776 fprintf(fp, STR_LINE"==============================================================================\n");
1777 fclose(fp);
1778 } else {
1779 nvme_show_error("Failed to open %s file.", file_path)nvme_show_message(1, "Failed to open %s file.", file_path);
1780 return -1;
1781 }
1782 } else {
1783 printf(STR_LINE"==============================================================================\n");
1784 printf("%s\n", STR_LOG_PAGE_HEADER"Log Page Header");
1785 printf(STR_LINE"==============================================================================\n");
1786 if (!strcmp(options->telemetry_type, "host")) {
1787 if ((ptelemetry_buffer == NULL((void*)0)) ||
3
Assuming 'ptelemetry_buffer' is equal to NULL
1788 (ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header)
[0]))
== 0))
1789 printf("skip generic_structure_parser\n");
1790 else {
1791 generic_structure_parser(ptelemetry_buffer, host_log_page_header,
1792 ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header)
[0]))
, NULL((void*)0), 0, NULL((void*)0));
1793 }
1794 }
1795 else if (!strcmp(options->telemetry_type, "controller"))
1796 generic_structure_parser(ptelemetry_buffer, controller_log_page_header,
1797 ARRAY_SIZE(controller_log_page_header)(sizeof(controller_log_page_header) / sizeof((controller_log_page_header
)[0]))
, NULL((void*)0), 0, NULL((void*)0));
1798
1799 printf(STR_LINE"==============================================================================\n");
1800 printf("%s\n", STR_REASON_IDENTIFIER"Reason Identifier");
1801 printf(STR_LINE"==============================================================================\n");
1802 __u8 *preason_identifier_offset = ptelemetry_buffer +
4
Addition of a null pointer (from variable 'ptelemetry_buffer') and a nonzero integer value results in undefined behavior
1803 offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id)__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header
, reason_id)
;
1804 generic_structure_parser(preason_identifier_offset, reason_identifier,
1805 ARRAY_SIZE(reason_identifier)(sizeof(reason_identifier) / sizeof((reason_identifier)[0])), NULL((void*)0), 0, NULL((void*)0));
1806
1807 printf(STR_LINE"==============================================================================\n");
1808 printf("%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1"Telemetry Host-Initiated Data Block 1");
1809 printf(STR_LINE"==============================================================================\n");
1810
1811 //Set DA to 1 and get offsets
1812 struct nvme_ocp_telemetry_offsets offsets = { 0 };
1813
1814 offsets.data_area = 1;
1815
1816 struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
1817 (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
1818
1819 get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
1820
1821 __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512
1822
1823 generic_structure_parser(pda1_header_offset, ocp_header_in_da1,
1824 ARRAY_SIZE(ocp_header_in_da1)(sizeof(ocp_header_in_da1) / sizeof((ocp_header_in_da1)[0])), NULL((void*)0), 0, NULL((void*)0));
1825
1826 printf(STR_LINE"==============================================================================\n");
1827 printf("%s\n", STR_SMART_HEALTH_INFO"SMART / Health Information Log(LID-02h)");
1828 printf(STR_LINE"==============================================================================\n");
1829 __u8 *pda1_smart_offset = pda1_header_offset +
1830 offsetof(struct nvme_ocp_header_in_da1, smart_health_info)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info
)
;
1831
1832 generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart)(sizeof(smart) / sizeof((smart)[0])), NULL((void*)0), 0,
1833 NULL((void*)0));
1834
1835 printf(STR_LINE"==============================================================================\n");
1836 printf("%s\n", STR_SMART_HEALTH_INTO_EXTENDED"SMART / Health Information Extended(LID-C0h)");
1837 printf(STR_LINE"==============================================================================\n");
1838 __u8 *pda1_smart_ext_offset = pda1_header_offset +
1839 offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended
)
;
1840
1841 generic_structure_parser(pda1_smart_ext_offset, smart_extended,
1842 ARRAY_SIZE(smart_extended)(sizeof(smart_extended) / sizeof((smart_extended)[0])), NULL((void*)0), 0, NULL((void*)0));
1843
1844 printf(STR_LINE"==============================================================================\n");
1845 printf("%s\n", STR_DA_1_STATS"Data Area 1 Statistics");
1846 printf(STR_LINE"==============================================================================\n");
1847 status = parse_statistics(NULL((void*)0), &offsets, NULL((void*)0));
1848 if (status != 0) {
1849 nvme_show_error("status: %d", status)nvme_show_message(1, "status: %d", status);
1850 return -1;
1851 }
1852
1853 printf(STR_LINE"==============================================================================\n");
1854 printf("%s\n", STR_DA_1_EVENT_FIFO_INFO"Data Area 1 Event FIFO info");
1855 printf(STR_LINE"==============================================================================\n");
1856 status = parse_event_fifos(NULL((void*)0), &offsets, NULL((void*)0));
1857 if (status != 0)
1858 return -1;
1859
1860 //Set the DA to 2
1861 if (options->data_area == 2) {
1862 offsets.data_area = 2;
1863 printf(STR_LINE"==============================================================================\n");
1864 printf("%s\n", STR_DA_2_STATS"Data Area 2 Statistics");
1865 printf(STR_LINE"==============================================================================\n");
1866 status = parse_statistics(NULL((void*)0), &offsets, NULL((void*)0));
1867 if (status != 0) {
1868 nvme_show_error("status: %d", status)nvme_show_message(1, "status: %d", status);
1869 return -1;
1870 }
1871
1872 printf(STR_LINE"==============================================================================\n");
1873 printf("%s\n", STR_DA_2_EVENT_FIFO_INFO"Data Area 2 Event FIFO info");
1874 printf(STR_LINE"==============================================================================\n");
1875 status = parse_event_fifos(NULL((void*)0), &offsets, NULL((void*)0));
1876 if (status != 0)
1877 return -1;
1878 }
1879
1880 printf(STR_LINE"==============================================================================\n");
1881 }
1882
1883 return status;
1884}
1885
1886int print_ocp_telemetry_json(struct ocp_telemetry_parse_options *options)
1887{
1888 int status = 0;
1889 char file_path[PATH_MAX4096];
1890
1891 //create json objects
1892 struct json_object *root, *pheader, *preason_identifier, *da1_header, *smart_obj,
1893 *ext_smart_obj;
1894
1895 root = json_create_object()json_object_new_object();
1896
1897 //Add data to root json object
1898
1899 //"Log Page Header"
1900 pheader = json_create_object()json_object_new_object();
1901
1902 generic_structure_parser(ptelemetry_buffer, host_log_page_header,
1903 ARRAY_SIZE(host_log_page_header)(sizeof(host_log_page_header) / sizeof((host_log_page_header)
[0]))
, pheader, 0, NULL((void*)0));
1904 json_object_add_value_object(root, STR_LOG_PAGE_HEADER, pheader)json_object_object_add(root, "Log Page Header", pheader);
1905
1906 //"Reason Identifier"
1907 preason_identifier = json_create_object()json_object_new_object();
1908
1909 __u8 *preason_identifier_offset = ptelemetry_buffer +
1910 offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id)__builtin_offsetof(struct nvme_ocp_telemetry_host_initiated_header
, reason_id)
;
1911
1912 generic_structure_parser(preason_identifier_offset, reason_identifier,
1913 ARRAY_SIZE(reason_identifier)(sizeof(reason_identifier) / sizeof((reason_identifier)[0])), preason_identifier, 0, NULL((void*)0));
1914 json_object_add_value_object(pheader, STR_REASON_IDENTIFIER, preason_identifier)json_object_object_add(pheader, "Reason Identifier", preason_identifier
)
;
1915
1916 struct nvme_ocp_telemetry_offsets offsets = { 0 };
1917
1918 //Set DA to 1 and get offsets
1919 offsets.data_area = 1;
1920 struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
1921 (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
1922
1923 get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
1924
1925 //"Telemetry Host-Initiated Data Block 1"
1926 __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512
1927
1928 da1_header = json_create_object()json_object_new_object();
1929
1930 generic_structure_parser(pda1_header_offset, ocp_header_in_da1,
1931 ARRAY_SIZE(ocp_header_in_da1)(sizeof(ocp_header_in_da1) / sizeof((ocp_header_in_da1)[0])), da1_header, 0, NULL((void*)0));
1932 json_object_add_value_object(root, STR_TELEMETRY_HOST_DATA_BLOCK_1, da1_header)json_object_object_add(root, "Telemetry Host-Initiated Data Block 1"
, da1_header)
;
1933
1934 //"SMART / Health Information Log(LID-02h)"
1935 __u8 *pda1_smart_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info
)
1936 smart_health_info)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info
)
;
1937 smart_obj = json_create_object()json_object_new_object();
1938
1939 generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart)(sizeof(smart) / sizeof((smart)[0])), smart_obj, 0, NULL((void*)0));
1940 json_object_add_value_object(da1_header, STR_SMART_HEALTH_INFO, smart_obj)json_object_object_add(da1_header, "SMART / Health Information Log(LID-02h)"
, smart_obj)
;
1941
1942 //"SMART / Health Information Extended(LID-C0h)"
1943 __u8 *pda1_smart_ext_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended
)
1944 smart_health_info_extended)__builtin_offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended
)
;
1945 ext_smart_obj = json_create_object()json_object_new_object();
1946
1947 generic_structure_parser(pda1_smart_ext_offset, smart_extended, ARRAY_SIZE(smart_extended)(sizeof(smart_extended) / sizeof((smart_extended)[0])),
1948 ext_smart_obj, 0, NULL((void*)0));
1949 json_object_add_value_object(da1_header, STR_SMART_HEALTH_INTO_EXTENDED, ext_smart_obj)json_object_object_add(da1_header, "SMART / Health Information Extended(LID-C0h)"
, ext_smart_obj)
;
1950
1951 //Data Area 1 Statistics
1952 status = parse_statistics(root, &offsets, NULL((void*)0));
1953 if (status != 0) {
1954 nvme_show_error("status: %d", status)nvme_show_message(1, "status: %d", status);
1955 return -1;
1956 }
1957
1958 //Data Area 1 Event FIFOs
1959 status = parse_event_fifos(root, &offsets, NULL((void*)0));
1960 if (status != 0)
1961 return -1;
1962
1963 if (options->data_area == 2) {
1964 //Set the DA to 2
1965 offsets.data_area = 2;
1966 //Data Area 2 Statistics
1967 status = parse_statistics(root, &offsets, NULL((void*)0));
1968 if (status != 0) {
1969 nvme_show_error("status: %d", status)nvme_show_message(1, "status: %d", status);
1970 return -1;
1971 }
1972
1973 //Data Area 2 Event FIFOs
1974 status = parse_event_fifos(root, &offsets, NULL((void*)0));
1975 if (status != 0)
1976 return -1;
1977 }
1978
1979 if (options->output_file != NULL((void*)0)) {
1980 const char *json_string = json_object_to_json_string(root);
1981 sprintf(file_path, "%s.%s", options->output_file, "json");
1982 FILE *fp = fopen(file_path, "w");
1983
1984 if (fp) {
1985 fputs(json_string, fp);
1986 fclose(fp);
1987 } else {
1988 nvme_show_error("Failed to open %s file.", file_path)nvme_show_message(1, "Failed to open %s file.", file_path);
1989 return -1;
1990 }
1991 } else {
1992 //Print root json object
1993 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
1994 nvme_show_result("\n")nvme_show_message(0, "\n");
1995 json_free_object(root)json_object_put(root);
1996 }
1997
1998 return status;
1999}
2000#endif /* CONFIG_JSONC */