| 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 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | |
| 24 | static 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 | |
| 39 | static 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 | |
| 99 | int 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 | |
| 332 | static 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 | |
| 374 | static 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 | |
| 395 | struct toc_item { |
| 396 | uint32_t OffsetBytes; |
| 397 | uint32_t ContentSizeBytes; |
| 398 | }; |
| 399 | |
| 400 | struct 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 | |
| 408 | struct table_of_contents { |
| 409 | struct data_area_header header; |
| 410 | struct toc_item items[]; |
| 411 | }; |
| 412 | |
| 413 | struct 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 | |
| 421 | static 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 | |
| 599 | void 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 | |
| 608 | int 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 | } |