Bug Summary

File:.build-ci/../plugins/solidigm/solidigm-telemetry/data-area.c
Warning:line 337, column 11
Value stored to 'last_block' during its initialization 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 data-area.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/solidigm/solidigm-telemetry/data-area.c
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright (c) 2022 Solidigm.
4 *
5 * Author: leonardo.da.cunha@solidigm.com
6 */
7
8#include "cod.h"
9#include "common.h"
10#include "config.h"
11#include "data-area.h"
12#include "header.h"
13#include "nlog.h"
14#include "side-trace.h"
15#include "skht.h"
16
17#define SIGNED_int_PREFIX"int" "int"
18#define SIGNED_INT_PREFIX"INT" "INT"
19
20#define MAX_WARNING_SIZE1024 1024
21#define MAX_ARRAY_RANK16 16
22#define NLOG_HEADER_ID101 101
23
24static void reverse_string(char *buff, size_t len)
25{
26 char *start = buff;
27 char *end = buff + len - 1;
28 char temp;
29
30 while (end > start) {
31 temp = *end;
32 *end = *start;
33 *start = temp;
34 start++;
35 end--;
36 }
37}
38
39static bool_Bool telemetry_log_get_value(const struct telemetry_log *tl,
40 uint64_t offset_bit, uint32_t size_bit,
41 bool_Bool is_signed, struct json_object **val_obj)
42{
43 uint32_t offset_bit_from_byte;
44 uint32_t additional_size_byte;
45 uint32_t offset_byte;
46 uint64_t val;
47
48 if (!size_bit) {
49 char err_msg[MAX_WARNING_SIZE1024];
50
51 snprintf(err_msg, MAX_WARNING_SIZE1024,
52 "Value with size_bit=0 not supported.");
53 *val_obj = json_object_new_string(err_msg);
54
55 return false0;
56 }
57 additional_size_byte = (size_bit - 1) ? (size_bit - 1) / NUM_BITS_IN_BYTE8 : 0;
58 offset_byte = (uint32_t)offset_bit / NUM_BITS_IN_BYTE8;
59
60 if (offset_byte > (tl->log_size - additional_size_byte)) {
61 char err_msg[MAX_WARNING_SIZE1024];
62
63 snprintf(err_msg, MAX_WARNING_SIZE1024,
64 "Value offset greater than binary size (%u + %u > %zu).",
65 offset_byte, additional_size_byte, tl->log_size);
66 *val_obj = json_object_new_string(err_msg);
67
68 return false0;
69 }
70
71 offset_bit_from_byte = (uint32_t) (offset_bit - ((uint64_t)offset_byte * NUM_BITS_IN_BYTE8));
72
73 if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * NUM_BITS_IN_BYTE8)) {
74 char err_msg[MAX_WARNING_SIZE1024];
75
76 snprintf(err_msg, MAX_WARNING_SIZE1024,
77 "Value crossing 64 bit, byte aligned boundary, not supported. size_bit=%u, offset_bit_from_byte=%u.",
78 size_bit, offset_bit_from_byte);
79 *val_obj = json_object_new_string(err_msg);
80
81 return false0;
82 }
83
84 val = *(uint64_t *)(((char *)tl->log) + offset_byte);
85 val >>= offset_bit_from_byte;
86 if (size_bit < 64)
87 val &= (1ULL << size_bit) - 1;
88 if (is_signed) {
89 if (val >> (size_bit - 1))
90 val |= (0ULL - 1) << size_bit;
91 *val_obj = json_object_new_int64(val);
92 } else {
93 *val_obj = json_object_new_uint64(val);
94 }
95
96 return true1;
97}
98
99int sldm_telemetry_structure_parse(const struct telemetry_log *tl,
100 struct json_object *struct_def,
101 uint64_t parent_offset_bit,
102 struct json_object *output,
103 struct json_object *metadata)
104{
105 struct json_object *obj_arraySizeArray = NULL((void*)0);
106 struct json_object *obj = NULL((void*)0);
107 struct json_object *obj_memberList;
108 struct json_object *sub_output;
109 struct json_object *obj_arraySizeIndicator = NULL((void*)0);
110 bool_Bool force_array = false0;
111 bool_Bool is_enumeration = false0;
112 bool_Bool has_member_list;
113 const char *type = "";
114 const char *name;
115 size_t array_rank;
116 uint64_t offset_bit;
117 uint32_t size_bit;
118 uint64_t linear_array_pos_bit;
119 uint32_t array_size_dimension[MAX_ARRAY_RANK16] = { 0 };
120
121 if (!json_object_object_get_ex(struct_def, "name", &obj)) {
122 SOLIDIGM_LOG_WARNING("Warning: Structure definition missing property 'name': %s",fprintf(stderr, "Warning: Structure definition missing property 'name': %s"
"\n" ,json_object_to_json_string(struct_def))
123 json_object_to_json_string(struct_def))fprintf(stderr, "Warning: Structure definition missing property 'name': %s"
"\n" ,json_object_to_json_string(struct_def))
;
124 return -1;
125 }
126
127 name = json_object_get_string(obj);
128
129 if (metadata) {
130 json_object_get(obj);
131 json_object_object_add(metadata, "objName", obj);
132 }
133
134 if (json_object_object_get_ex(struct_def, "type", &obj))
135 type = json_object_get_string(obj);
136
137 if (!json_object_object_get_ex(struct_def, "offsetBit", &obj)) {
138 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: Structure definition missing property 'offsetBit': %s"
"\n" ,json_object_to_json_string(struct_def))
139 "Warning: Structure definition missing property 'offsetBit': %s",fprintf(stderr, "Warning: Structure definition missing property 'offsetBit': %s"
"\n" ,json_object_to_json_string(struct_def))
140 json_object_to_json_string(struct_def))fprintf(stderr, "Warning: Structure definition missing property 'offsetBit': %s"
"\n" ,json_object_to_json_string(struct_def))
;
141 return -1;
142 }
143
144 offset_bit = json_object_get_uint64(obj);
145
146 if (!json_object_object_get_ex(struct_def, "sizeBit", &obj)) {
147 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: Structure definition missing property 'sizeBit': %s"
"\n" ,json_object_to_json_string(struct_def))
148 "Warning: Structure definition missing property 'sizeBit': %s",fprintf(stderr, "Warning: Structure definition missing property 'sizeBit': %s"
"\n" ,json_object_to_json_string(struct_def))
149 json_object_to_json_string(struct_def))fprintf(stderr, "Warning: Structure definition missing property 'sizeBit': %s"
"\n" ,json_object_to_json_string(struct_def))
;
150 return -1;
151 }
152
153 size_bit = (uint32_t)json_object_get_uint64(obj);
154
155 if (json_object_object_get_ex(struct_def, "enum", &obj))
156 is_enumeration = json_object_get_boolean(obj);
157
158 has_member_list = json_object_object_get_ex(struct_def,
159 "memberList",
160 &obj_memberList);
161
162 if (!json_object_object_get_ex(struct_def, "arraySize",
163 &obj_arraySizeArray)) {
164 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: Structure definition missing property 'arraySize': %s"
"\n" ,json_object_to_json_string(struct_def))
165 "Warning: Structure definition missing property 'arraySize': %s",fprintf(stderr, "Warning: Structure definition missing property 'arraySize': %s"
"\n" ,json_object_to_json_string(struct_def))
166 json_object_to_json_string(struct_def))fprintf(stderr, "Warning: Structure definition missing property 'arraySize': %s"
"\n" ,json_object_to_json_string(struct_def))
;
167 return -1;
168 }
169
170 array_rank = json_object_array_length(obj_arraySizeArray);
171 if (!array_rank) {
172 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: Structure property 'arraySize' don't support flexible array: %s"
"\n" ,json_object_to_json_string(struct_def))
173 "Warning: Structure property 'arraySize' don't support flexible array: %s",fprintf(stderr, "Warning: Structure property 'arraySize' don't support flexible array: %s"
"\n" ,json_object_to_json_string(struct_def))
174 json_object_to_json_string(struct_def))fprintf(stderr, "Warning: Structure property 'arraySize' don't support flexible array: %s"
"\n" ,json_object_to_json_string(struct_def))
;
175 return -1;
176 }
177 if (array_rank > MAX_ARRAY_RANK16) {
178 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: Structure property 'arraySize' don't support more than %d dimensions: %s"
"\n" ,16, json_object_to_json_string(struct_def))
179 "Warning: Structure property 'arraySize' don't support more than %d dimensions: %s",fprintf(stderr, "Warning: Structure property 'arraySize' don't support more than %d dimensions: %s"
"\n" ,16, json_object_to_json_string(struct_def))
180 MAX_ARRAY_RANK, json_object_to_json_string(struct_def))fprintf(stderr, "Warning: Structure property 'arraySize' don't support more than %d dimensions: %s"
"\n" ,16, json_object_to_json_string(struct_def))
;
181 return -1;
182 }
183
184 for (size_t i = 0; i < array_rank; i++) {
185 struct json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i);
186
187 array_size_dimension[i] = json_object_get_int(dimension);
188 }
189
190 // Check for arraySizeIndicator property to support dynamic array sizes
191 if (json_object_object_get_ex(struct_def, "arraySizeIndicator", &obj_arraySizeIndicator)) {
192 const char *indicator_name = json_object_get_string(obj_arraySizeIndicator);
193
194 force_array = true1; // Force array output even if size is 1
195
196 // Look for the indicator property in the parent object (output)
197 if (indicator_name && output) {
198 struct json_object *parent_prop = NULL((void*)0);
199
200 if (json_object_object_get_ex(output, indicator_name, &parent_prop)) {
201 // Get the dynamic array size from the parent property
202 uint32_t dynamic_size = json_object_get_int(parent_prop);
203
204 array_size_dimension[0] = dynamic_size;
205 }
206 }
207 }
208
209 if (array_rank > 1) {
210 uint32_t linear_pos_per_index = 1;
211 uint32_t outer_size = array_size_dimension[array_rank - 1];
212 uint32_t prev_index_offset_bit = 0;
213 struct json_object *dimension_output;
214 struct json_object *inner_dim_array;
215
216 /*
217 * arraySize convention: the last element is the outermost
218 * (major) dimension. Stride = product of all inner dims
219 * [0..rank-2].
220 */
221 for (unsigned int i = 0; i < array_rank - 1; i++)
222 linear_pos_per_index *= array_size_dimension[i];
223
224 /*
225 * When output is already an array (recursive call from
226 * outer dimension), fill it directly to avoid extra wrap.
227 */
228 if (json_object_get_type(output) == json_type_array) {
229 dimension_output = output;
230 } else {
231 dimension_output = json_create_array()json_object_new_array();
232 json_object_add_value_array(output, name, dimension_output)json_object_object_add(output, name, dimension_output);
233 }
234
235 /*
236 * Build a copy of arraySize without the last (outermost)
237 * dimension so recursive calls see only the inner dimensions.
238 */
239 inner_dim_array = json_create_array()json_object_new_array();
240 for (size_t i = 0; i < array_rank - 1; i++) {
241 struct json_object *dim =
242 json_object_array_get_idx(
243 obj_arraySizeArray, i);
244
245 json_object_get(dim);
246 json_object_array_add(inner_dim_array, dim);
247 }
248 json_object_get(obj_arraySizeArray);
249 json_object_object_add(struct_def, "arraySize",
250 inner_dim_array);
251
252 for (unsigned int i = 0 ; i < outer_size; i++) {
253 struct json_object *sub_array = json_create_array()json_object_new_array();
254 uint64_t offset;
255
256 offset = parent_offset_bit + prev_index_offset_bit;
257
258 json_object_array_add(dimension_output, sub_array);
259 sldm_telemetry_structure_parse(tl, struct_def,
260 offset, sub_array, NULL((void*)0));
261 prev_index_offset_bit += linear_pos_per_index * size_bit;
262 }
263
264 json_object_object_add(struct_def, "arraySize",
265 obj_arraySizeArray);
266
267 return 0;
268 }
269
270 linear_array_pos_bit = 0;
271 sub_output = output;
272
273 if (array_size_dimension[0] > 1 || force_array) {
274 /*
275 * When output is already an array (from an outer
276 * multi-dim call), fill it directly to avoid extra wrap.
277 */
278 if (json_object_is_type(output, json_type_array)) {
279 sub_output = output;
280 } else {
281 sub_output = json_create_array()json_object_new_array();
282 json_object_add_value_array(output, name, sub_output)json_object_object_add(output, name, sub_output);
283 }
284 }
285
286 for (uint32_t j = 0; j < array_size_dimension[0]; j++) {
287 if (is_enumeration || !has_member_list) {
288 bool_Bool is_signed = !strncmp(type, SIGNED_int_PREFIX"int",
289 sizeof(SIGNED_int_PREFIX"int")-1) ||
290 !strncmp(type, SIGNED_INT_PREFIX"INT",
291 sizeof(SIGNED_INT_PREFIX"INT")-1);
292 struct json_object *val_obj;
293 uint64_t offset;
294
295 offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
296 if (telemetry_log_get_value(tl, offset, size_bit, is_signed, &val_obj)) {
297 if (array_size_dimension[0] > 1 || force_array)
298 json_object_array_put_idx(sub_output, j, val_obj);
299 else
300 json_object_object_add(sub_output, name, val_obj);
301 } else {
302 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: %s From property '%s', array index %u, structure definition: %s"
"\n" ,json_object_get_string(val_obj), name, j, json_object_to_json_string
(struct_def))
303 "Warning: %s From property '%s', array index %u, structure definition: %s",fprintf(stderr, "Warning: %s From property '%s', array index %u, structure definition: %s"
"\n" ,json_object_get_string(val_obj), name, j, json_object_to_json_string
(struct_def))
304 json_object_get_string(val_obj), name, j,fprintf(stderr, "Warning: %s From property '%s', array index %u, structure definition: %s"
"\n" ,json_object_get_string(val_obj), name, j, json_object_to_json_string
(struct_def))
305 json_object_to_json_string(struct_def))fprintf(stderr, "Warning: %s From property '%s', array index %u, structure definition: %s"
"\n" ,json_object_get_string(val_obj), name, j, json_object_to_json_string
(struct_def))
;
306 json_free_object(val_obj)json_object_put(val_obj);
307 }
308 } else {
309 struct json_object *sub_sub_output = json_object_new_object();
310 int num_members;
311
312 if (array_size_dimension[0] > 1 || force_array)
313 json_object_array_put_idx(sub_output, j, sub_sub_output);
314 else
315 json_object_add_value_object(sub_output, name, sub_sub_output)json_object_object_add(sub_output, name, sub_sub_output);
316
317 num_members = json_object_array_length(obj_memberList);
318 for (int k = 0; k < num_members; k++) {
319 struct json_object *member = json_object_array_get_idx(obj_memberList, k);
320 uint64_t offset;
321
322 offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
323 sldm_telemetry_structure_parse(tl, member, offset,
324 sub_sub_output, NULL((void*)0));
325 }
326 }
327 linear_array_pos_bit += size_bit;
328 }
329 return 0;
330}
331
332static int telemetry_log_data_area_get_offset(const struct telemetry_log *tl,
333 enum nvme_telemetry_da da,
334 uint32_t *offset, uint32_t *size)
335{
336 uint32_t offset_blocks = 1;
337 uint32_t last_block = tl->log->dalb1;
Value stored to 'last_block' during its initialization is never read
338 uint32_t last;
339
340 switch (da) {
341 case NVME_TELEMETRY_DA_1:
342 offset_blocks = 1;
343 last_block = tl->log->dalb1;
344 break;
345 case NVME_TELEMETRY_DA_2:
346 offset_blocks = tl->log->dalb1 + 1;
347 last_block = tl->log->dalb2;
348 break;
349 case NVME_TELEMETRY_DA_3:
350 offset_blocks = tl->log->dalb2 + 1;
351 last_block = tl->log->dalb3;
352 break;
353 case NVME_TELEMETRY_DA_4:
354 offset_blocks = tl->log->dalb3 + 1;
355 last_block = tl->log->dalb4;
356 break;
357 default:
358 return -1;
359 }
360
361 *offset = offset_blocks * NVME_LOG_TELEM_BLOCK_SIZE;
362 last = (last_block + 1) * NVME_LOG_TELEM_BLOCK_SIZE;
363 *size = last - *offset;
364 if (last < *offset)
365 return -1; /* DA is absent or empty, skip silently */
366 if ((*offset > tl->log_size) || (last > tl->log_size)) {
367 SOLIDIGM_LOG_WARNING("Warning: Data Area %d don't fit this Telemetry log.", da)fprintf(stderr, "Warning: Data Area %d don't fit this Telemetry log."
"\n" ,da)
;
368 return -1;
369 }
370
371 return 0;
372}
373
374static int telemetry_log_nlog_parse(const struct telemetry_log *tl, struct json_object *formats,
375 uint64_t nlog_file_offset, uint64_t nlog_size,
376 struct json_object *output, struct json_object *metadata)
377{
378 /* boundary check */
379 if (tl->log_size < (nlog_file_offset + nlog_size)) {
380 const char *name = "";
381 int media_bank = -1;
382 struct json_object *jobj;
383
384 if (json_object_object_get_ex(metadata, "objName", &jobj))
385 name = json_object_get_string(jobj);
386 if (json_object_object_get_ex(metadata, "mediaBankId", &jobj))
387 media_bank = json_object_get_int(jobj);
388 SOLIDIGM_LOG_WARNING("%s:%d do not fit this log dump.", name, media_bank)fprintf(stderr, "%s:%d do not fit this log dump.""\n" ,name, media_bank
)
;
389 return -1;
390 }
391 return solidigm_nlog_parse(((char *) tl->log) + nlog_file_offset,
392 nlog_size, formats, metadata, output);
393}
394
395struct toc_item {
396 uint32_t OffsetBytes;
397 uint32_t ContentSizeBytes;
398};
399
400struct data_area_header {
401 uint8_t versionMajor;
402 uint8_t versionMinor;
403 uint16_t TableOfContentsCount;
404 uint32_t DataAreaSize;
405 uint8_t Reserved[8];
406};
407
408struct table_of_contents {
409 struct data_area_header header;
410 struct toc_item items[];
411};
412
413struct telemetry_object_header {
414 uint16_t versionMajor;
415 uint16_t versionMinor;
416 uint32_t Token;
417 uint8_t CoreId;
418 uint8_t Reserved[3];
419};
420
421static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
422 enum nvme_telemetry_da da,
423 struct json_object *toc_array,
424 struct json_object *tele_obj_array)
425{
426
427 const struct telemetry_object_header *header;
428 const struct table_of_contents *toc;
429 char *payload;
430 uint32_t da_offset;
431 uint32_t da_size;
432 struct json_object *nlog_formats;
433
434 if (telemetry_log_data_area_get_offset(tl, da, &da_offset, &da_size))
435 return;
436
437 toc = (struct table_of_contents *)(((char *)tl->log) + da_offset);
438 payload = (char *) tl->log;
439 nlog_formats = solidigm_config_get_nlog_formats(tl->configuration);
440
441 for (int i = 0; i < toc->header.TableOfContentsCount; i++) {
442 struct json_object *structure_definition = NULL((void*)0);
443 struct json_object *toc_item;
444 uint32_t obj_offset;
445 bool_Bool has_struct;
446 const char *nlog_name = NULL((void*)0);
447 uint32_t header_offset = sizeof(const struct telemetry_object_header);
448 struct json_object *tele_obj_item;
449 struct json_object *parsed_struct;
450 struct json_object *obj_hasTelemObjHdr = NULL((void*)0);
451 uint64_t object_file_offset;
452
453 if ((char *)&toc->items[i] >
454 (((char *)toc) + da_size - sizeof(const struct toc_item))) {
455 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: Data Area %d, Table of Contents item %d crossed Data Area size."
"\n" ,da, i)
456 "Warning: Data Area %d, Table of Contents item %d crossed Data Area size.",fprintf(stderr, "Warning: Data Area %d, Table of Contents item %d crossed Data Area size."
"\n" ,da, i)
457 da, i)fprintf(stderr, "Warning: Data Area %d, Table of Contents item %d crossed Data Area size."
"\n" ,da, i)
;
458 return;
459 }
460
461 obj_offset = toc->items[i].OffsetBytes;
462 if ((obj_offset + sizeof(const struct telemetry_object_header)) > da_size) {
463 SOLIDIGM_LOG_WARNING(fprintf(stderr, "Warning: Data Area %d, item %d data, crossed Data Area size."
"\n" ,da, i)
464 "Warning: Data Area %d, item %d data, crossed Data Area size.", da, i)fprintf(stderr, "Warning: Data Area %d, item %d data, crossed Data Area size."
"\n" ,da, i)
;
465 continue;
466 }
467
468 toc_item = json_object_new_object();
469 json_object_array_add(toc_array, toc_item);
470 json_object_add_value_uint(toc_item, "dataArea", da)json_object_object_add(toc_item, "dataArea", json_object_new_uint64
(da))
;
471 json_object_add_value_uint(toc_item, "dataAreaIndex", i)json_object_object_add(toc_item, "dataAreaIndex", json_object_new_uint64
(i))
;
472 json_object_add_value_uint(toc_item, "dataAreaOffset", obj_offset)json_object_object_add(toc_item, "dataAreaOffset", json_object_new_uint64
(obj_offset))
;
473 json_object_add_value_uint(toc_item, "fileOffset", obj_offset + da_offset)json_object_object_add(toc_item, "fileOffset", json_object_new_uint64
(obj_offset + da_offset))
;
474 json_object_add_value_uint(toc_item, "size", toc->items[i].ContentSizeBytes)json_object_object_add(toc_item, "size", json_object_new_uint64
(toc->items[i].ContentSizeBytes))
;
475
476 header = (const struct telemetry_object_header *) (payload + da_offset + obj_offset);
477 json_object_add_value_uint(toc_item, "telemMajor", header->versionMajor)json_object_object_add(toc_item, "telemMajor", json_object_new_uint64
(header->versionMajor))
;
478 json_object_add_value_uint(toc_item, "telemMinor", header->versionMinor)json_object_object_add(toc_item, "telemMinor", json_object_new_uint64
(header->versionMinor))
;
479 json_object_add_value_uint(toc_item, "objectId", header->Token)json_object_object_add(toc_item, "objectId", json_object_new_uint64
(header->Token))
;
480 json_object_add_value_uint(toc_item, "mediaBankId", header->CoreId)json_object_object_add(toc_item, "mediaBankId", json_object_new_uint64
(header->CoreId))
;
481
482 has_struct = solidigm_config_get_struct_by_token_version(tl->configuration,
483 header->Token,
484 header->versionMajor,
485 header->versionMinor,
486 &structure_definition);
487 if (!has_struct) {
488 if (!nlog_formats)
489 continue;
490 nlog_name = solidigm_config_get_nlog_obj_name(tl->configuration,
491 header->Token);
492 if (!nlog_name)
493 continue;
494
495 // NLOGs have different parser from other Telemetry objects
496 has_struct = solidigm_config_get_struct_by_token_version(tl->configuration,
497 NLOG_HEADER_ID101,
498 header->versionMajor,
499 header->versionMinor,
500 &structure_definition);
501 }
502 tele_obj_item = json_object_new_object();
503
504 json_object_array_add(tele_obj_array, tele_obj_item);
505 json_object_get(toc_item);
506 json_object_add_value_object(tele_obj_item, "metadata", toc_item)json_object_object_add(tele_obj_item, "metadata", toc_item);
507 parsed_struct = json_object_new_object();
508
509 json_object_add_value_object(tele_obj_item, "objectData", parsed_struct)json_object_object_add(tele_obj_item, "objectData", parsed_struct
)
;
510
511 if (json_object_object_get_ex(structure_definition,
512 "hasTelemObjHdr",
513 &obj_hasTelemObjHdr)) {
514 bool_Bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr);
515
516 if (hasHeader)
517 header_offset = 0;
518 }
519 object_file_offset = ((uint64_t)da_offset) + obj_offset + header_offset;
520 if (has_struct) {
521 sldm_telemetry_structure_parse(tl, structure_definition,
522 NUM_BITS_IN_BYTE8 * object_file_offset,
523 parsed_struct, toc_item);
524 }
525 // NLOGs have different parser from other Telemetry objects
526 if (nlog_name) {
527 if (has_struct) {
528 struct json_object *header_sizeBits = NULL((void*)0);
529 struct json_object *header_nlogSelect = NULL((void*)0);
530 struct json_object *header_nlogName = NULL((void*)0);
531
532 if (json_object_object_get_ex(structure_definition, "sizeBit",
533 &header_sizeBits))
534 header_offset = json_object_get_int(header_sizeBits) /
535 NUM_BITS_IN_BYTE8;
536 // Overwrite nlogName with correct type
537 if (json_object_object_get_ex(parsed_struct, "nlogSelect",
538 &header_nlogSelect) &&
539 json_object_object_get_ex(header_nlogSelect, "nlogName",
540 &header_nlogName)) {
541 int nlogName = json_object_get_int(header_nlogName);
542 char *name = (char *)&nlogName;
543 struct json_object *nlog_name_obj = NULL((void*)0);
544
545 reverse_string(name, sizeof(uint32_t));
546 sldm_uint8_array_to_string((const uint8_t *)name,
547 sizeof(uint32_t),
548 &nlog_name_obj);
549 json_object_object_add(header_nlogSelect, "nlogName",
550 nlog_name_obj);
551 }
552 }
553 // Overwrite the object name
554 json_object_object_add(toc_item, "objName",
555 json_object_new_string(nlog_name));
556
557 telemetry_log_nlog_parse(tl, nlog_formats,
558 object_file_offset + header_offset,
559 toc->items[i].ContentSizeBytes - header_offset,
560 parsed_struct, toc_item);
561 }
562
563 // Check if this is a side trace object
564 struct json_object *obj_name = NULL((void*)0);
565
566 if (json_object_object_get_ex(toc_item, "objName", &obj_name)) {
567 const char *obj_name_str =
568 json_object_get_string(obj_name);
569
570 if (obj_name_str &&
571 (strstr(obj_name_str, "sideTrace") ||
572 strstr(obj_name_str, "SideTrace") ||
573 strstr(obj_name_str, "SIDETRACE"))) {
574 /* This is a side trace object, parse it when
575 * configuration is available. We want to
576 * replace array member fwSideTrace by parsed
577 * entries.
578 */
579 struct json_object *first_dic = NULL((void*)0);
580
581 json_object_object_foreach(parsed_struct, key,char *key = ((void*)0); struct json_object *val __attribute__
((__unused__)) = ((void*)0); for (struct lh_entry *entrykey =
lh_table_head(json_object_get_object(parsed_struct)), *entry_nextkey
= ((void*)0); ({ if (entrykey) { key = (char *)lh_entry_k(entrykey
); val = (struct json_object *)lh_entry_v(entrykey); entry_nextkey
= lh_entry_next(entrykey); }; entrykey; }); entrykey = entry_nextkey
)
582 val)char *key = ((void*)0); struct json_object *val __attribute__
((__unused__)) = ((void*)0); for (struct lh_entry *entrykey =
lh_table_head(json_object_get_object(parsed_struct)), *entry_nextkey
= ((void*)0); ({ if (entrykey) { key = (char *)lh_entry_k(entrykey
); val = (struct json_object *)lh_entry_v(entrykey); entry_nextkey
= lh_entry_next(entrykey); }; entrykey; }); entrykey = entry_nextkey
)
{
583 (void)key;
584 if (json_object_is_type(val,
585 json_type_object)) {
586 first_dic = val;
587 break;
588 }
589 }
590 sldm_parse_side_trace(tl, object_file_offset,
591 toc->items[i]
592 .ContentSizeBytes,
593 first_dic, toc_item);
594 }
595 }
596 }
597}
598
599void solidigm_telemetry_log_da1_check_ocp(struct telemetry_log *tl)
600{
601 const uint64_t ocp_telemetry_uuid[] = {0xBC73719D87E64EFA, 0xBA560A9C3043424C};
602 const uint64_t *log_uuid = (uint64_t *) &tl->log->data_area[16];
603
604 tl->is_ocp = tl->log_size >= (size_t)(&tl->log->data_area[32] - (uint8_t *) tl->log) &&
605 log_uuid[0] == ocp_telemetry_uuid[0] && log_uuid[1] == ocp_telemetry_uuid[1];
606}
607
608int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl,
609 enum nvme_telemetry_da last_da)
610{
611 struct json_object *tele_obj_array = NULL((void*)0);
612 struct json_object *toc_array = NULL((void*)0);
613
614 solidigm_telemetry_log_da1_check_ocp(tl);
615 sldm_telemetry_check_for_skhT(tl);
616
617 // if TELEMETRY_CONFIG_META available copy it to the output for better
618 // context in the output data
619 if (tl->configuration) {
620 struct json_object *config_meta = NULL((void*)0);
621
622 if (json_object_object_get_ex(tl->configuration,
623 "TELEMETRY_CONFIG_META",
624 &config_meta))
625 json_object_object_add(tl->root,
626 "TELEMETRY_CONFIG_META",
627 config_meta);
628 }
629 solidigm_telemetry_log_header_parse(tl);
630 solidigm_telemetry_log_cod_parse(tl);
631 if (tl->configuration) {
632 enum nvme_telemetry_da first_da = NVME_TELEMETRY_DA_1;
633
634 if (tl->is_ocp)
635 first_da = NVME_TELEMETRY_DA_3;
636
637 if (tl->skhT_offset) {
638 if (last_da >= NVME_TELEMETRY_DA_2)
639 sldm_telemetry_skhT_parse(tl);
640 if (last_da >= NVME_TELEMETRY_DA_3)
641 sldm_telemetry_sktT_segment_parse(tl, toc_array,
642 tele_obj_array);
643 return 0;
644 }
645
646 tele_obj_array = json_create_array()json_object_new_array();
647 toc_array = json_create_array()json_object_new_array();
648 json_object_add_value_array(tl->root, "tableOfContents", toc_array)json_object_object_add(tl->root, "tableOfContents", toc_array
)
;
649 json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array)json_object_object_add(tl->root, "telemetryObjects", tele_obj_array
)
;
650
651 for (enum nvme_telemetry_da da = first_da; da <= last_da; da++)
652 telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array);
653 }
654 return 0;
655}