1111#include "data-area.h"
1212#include "config.h"
1313#include "nlog.h"
14+ #include "skht.h"
1415#include <ctype.h>
1516
16- #define SIGNED_INT_PREFIX "int"
17- #define BITS_IN_BYTE 8
17+ #define SIGNED_int_PREFIX "int"
18+ #define SIGNED_INT_PREFIX "INT"
1819
1920#define MAX_WARNING_SIZE 1024
2021#define MAX_ARRAY_RANK 16
2122#define NLOG_HEADER_ID 101
2223
24+ static bool uint8_array_to_string (const struct telemetry_log * tl ,
25+ uint64_t offset_bit , uint32_t size_bit ,
26+ uint32_t array_size ,
27+ struct json_object * * str_obj )
28+ {
29+ uint32_t offset_byte = (uint32_t )offset_bit / NUM_BITS_IN_BYTE ;
30+
31+ if (size_bit != 8 ) {
32+ * str_obj = json_object_new_string (
33+ "Error: Only UINT8 arrays can be converted to strings" );
34+ return false;
35+ }
36+
37+ if (offset_byte > (tl -> log_size - array_size )) {
38+ char err_msg [MAX_WARNING_SIZE ];
39+
40+ snprintf (err_msg , MAX_WARNING_SIZE ,
41+ "String offset greater than binary size (%u > %zu)." ,
42+ offset_byte , tl -> log_size );
43+ * str_obj = json_object_new_string (err_msg );
44+ return false;
45+ }
46+
47+ // Get direct pointer to the UINT8 array in the telemetry log
48+ const uint8_t * data_ptr = (const uint8_t * )tl -> log + offset_byte ;
49+
50+ // Calculate actual string length (stopping at null terminator if found)
51+ size_t actual_length = 0 ;
52+
53+ for (actual_length = 0 ; actual_length < array_size ; actual_length ++ ) {
54+ if (data_ptr [actual_length ] == '\0' )
55+ break ;
56+ }
57+
58+ // Create JSON string directly from the data without intermediate buffer
59+ * str_obj = json_object_new_string_len ((const char * )data_ptr , actual_length );
60+
61+ return true;
62+ }
2363
2464static void reverse_string (char * buff , size_t len )
2565{
@@ -54,23 +94,23 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
5494
5595 return false;
5696 }
57- additional_size_byte = (size_bit - 1 ) ? (size_bit - 1 ) / BITS_IN_BYTE : 0 ;
58- offset_byte = (uint32_t )offset_bit / BITS_IN_BYTE ;
97+ additional_size_byte = (size_bit - 1 ) ? (size_bit - 1 ) / NUM_BITS_IN_BYTE : 0 ;
98+ offset_byte = (uint32_t )offset_bit / NUM_BITS_IN_BYTE ;
5999
60100 if (offset_byte > (tl -> log_size - additional_size_byte )) {
61101 char err_msg [MAX_WARNING_SIZE ];
62102
63103 snprintf (err_msg , MAX_WARNING_SIZE ,
64- "Value offset greater than binary size (%u > %zu)." ,
65- offset_byte , tl -> log_size );
104+ "Value offset greater than binary size (%u + %u > %zu)." ,
105+ offset_byte , additional_size_byte , tl -> log_size );
66106 * val_obj = json_object_new_string (err_msg );
67107
68108 return false;
69109 }
70110
71- offset_bit_from_byte = (uint32_t ) (offset_bit - ((uint64_t )offset_byte * BITS_IN_BYTE ));
111+ offset_bit_from_byte = (uint32_t ) (offset_bit - ((uint64_t )offset_byte * NUM_BITS_IN_BYTE ));
72112
73- if ((size_bit + offset_bit_from_byte ) > (sizeof (uint64_t ) * BITS_IN_BYTE )) {
113+ if ((size_bit + offset_bit_from_byte ) > (sizeof (uint64_t ) * NUM_BITS_IN_BYTE )) {
74114 char err_msg [MAX_WARNING_SIZE ];
75115
76116 snprintf (err_msg , MAX_WARNING_SIZE ,
@@ -96,17 +136,19 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
96136 return true;
97137}
98138
99- static int telemetry_log_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 )
139+ int sldm_telemetry_structure_parse (const struct telemetry_log * tl ,
140+ struct json_object * struct_def ,
141+ uint64_t parent_offset_bit ,
142+ struct json_object * output ,
143+ struct json_object * metadata )
104144{
105145 struct json_object * obj_arraySizeArray = NULL ;
106146 struct json_object * obj = NULL ;
107147 struct json_object * obj_memberList ;
108148 struct json_object * major_dimension = NULL ;
109149 struct json_object * sub_output ;
150+ struct json_object * obj_arraySizeIndicator = NULL ;
151+ bool force_array = false;
110152 bool is_enumeration = false;
111153 bool has_member_list ;
112154 const char * type = "" ;
@@ -115,7 +157,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
115157 uint64_t offset_bit ;
116158 uint32_t size_bit ;
117159 uint64_t linear_array_pos_bit ;
118- uint32_t array_size_dimension [MAX_ARRAY_RANK ];
160+ uint32_t array_size_dimension [MAX_ARRAY_RANK ] = { 0 } ;
119161
120162 if (!json_object_object_get_ex (struct_def , "name" , & obj )) {
121163 SOLIDIGM_LOG_WARNING ("Warning: Structure definition missing property 'name': %s" ,
@@ -186,6 +228,26 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
186228 array_size_dimension [i ] = json_object_get_int (dimension );
187229 major_dimension = dimension ;
188230 }
231+
232+ // Check for arraySizeIndicator property to support dynamic array sizes
233+ if (json_object_object_get_ex (struct_def , "arraySizeIndicator" , & obj_arraySizeIndicator )) {
234+ const char * indicator_name = json_object_get_string (obj_arraySizeIndicator );
235+
236+ force_array = true; // Force array output even if size is 1
237+
238+ // Look for the indicator property in the parent object (output)
239+ if (indicator_name && output ) {
240+ struct json_object * parent_prop = NULL ;
241+
242+ if (json_object_object_get_ex (output , indicator_name , & parent_prop )) {
243+ // Get the dynamic array size from the parent property
244+ uint32_t dynamic_size = json_object_get_int (parent_prop );
245+
246+ array_size_dimension [0 ] = dynamic_size ;
247+ }
248+ }
249+ }
250+
189251 if (array_rank > 1 ) {
190252 uint32_t linear_pos_per_index = array_size_dimension [0 ];
191253 uint32_t prev_index_offset_bit = 0 ;
@@ -214,8 +276,8 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
214276 offset = parent_offset_bit + prev_index_offset_bit ;
215277
216278 json_object_array_add (dimension_output , sub_array );
217- telemetry_log_structure_parse (tl , struct_def ,
218- offset , sub_array , NULL );
279+ sldm_telemetry_structure_parse (tl , struct_def ,
280+ offset , sub_array , NULL );
219281 prev_index_offset_bit += linear_pos_per_index * size_bit ;
220282 }
221283
@@ -228,7 +290,23 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
228290 linear_array_pos_bit = 0 ;
229291 sub_output = output ;
230292
231- if (array_size_dimension [0 ] > 1 ) {
293+ if (array_size_dimension [0 ] > 1 || force_array ) {
294+ // Check if this is a UINT8 array that should be treated as a string
295+ if (strcmp (type , "UINT8" ) == 0 && !force_array ) {
296+ // Handle UINT8 arrays as strings
297+ struct json_object * str_obj = NULL ;
298+ uint64_t offset = parent_offset_bit + offset_bit ;
299+
300+ if (uint8_array_to_string (tl , offset , size_bit ,
301+ array_size_dimension [0 ], & str_obj )) {
302+ json_object_object_add (output , name , str_obj );
303+ return 0 ;
304+ }
305+
306+ // If string conversion failed, fall back to normal array processing
307+ json_object_put (str_obj );
308+ }
309+
232310 sub_output = json_create_array ();
233311 if (json_object_get_type (output ) == json_type_array )
234312 json_object_array_add (output , sub_output );
@@ -238,13 +316,16 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
238316
239317 for (uint32_t j = 0 ; j < array_size_dimension [0 ]; j ++ ) {
240318 if (is_enumeration || !has_member_list ) {
241- bool is_signed = !strncmp (type , SIGNED_INT_PREFIX , sizeof (SIGNED_INT_PREFIX )- 1 );
319+ bool is_signed = !strncmp (type , SIGNED_int_PREFIX ,
320+ sizeof (SIGNED_int_PREFIX )- 1 ) ||
321+ !strncmp (type , SIGNED_INT_PREFIX ,
322+ sizeof (SIGNED_INT_PREFIX )- 1 );
242323 struct json_object * val_obj ;
243324 uint64_t offset ;
244325
245326 offset = parent_offset_bit + offset_bit + linear_array_pos_bit ;
246327 if (telemetry_log_get_value (tl , offset , size_bit , is_signed , & val_obj )) {
247- if (array_size_dimension [0 ] > 1 )
328+ if (array_size_dimension [0 ] > 1 || force_array )
248329 json_object_array_put_idx (sub_output , j , val_obj );
249330 else
250331 json_object_object_add (sub_output , name , val_obj );
@@ -256,10 +337,10 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
256337 json_free_object (val_obj );
257338 }
258339 } else {
259- struct json_object * sub_sub_output = json_create_object ();
340+ struct json_object * sub_sub_output = json_object_new_object ();
260341 int num_members ;
261342
262- if (array_size_dimension [0 ] > 1 )
343+ if (array_size_dimension [0 ] > 1 || force_array )
263344 json_object_array_put_idx (sub_output , j , sub_sub_output );
264345 else
265346 json_object_add_value_object (sub_output , name , sub_sub_output );
@@ -270,8 +351,8 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
270351 uint64_t offset ;
271352
272353 offset = parent_offset_bit + offset_bit + linear_array_pos_bit ;
273- telemetry_log_structure_parse (tl , member , offset ,
274- sub_sub_output , NULL );
354+ sldm_telemetry_structure_parse (tl , member , offset ,
355+ sub_sub_output , NULL );
275356 }
276357 }
277358 linear_array_pos_bit += size_bit ;
@@ -393,9 +474,13 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
393474 bool has_struct ;
394475 const char * nlog_name = NULL ;
395476 uint32_t header_offset = sizeof (const struct telemetry_object_header );
477+ struct json_object * tele_obj_item ;
478+ struct json_object * parsed_struct ;
479+ struct json_object * obj_hasTelemObjHdr = NULL ;
480+ uint64_t object_file_offset ;
396481
397482 if ((char * )& toc -> items [i ] >
398- (((char * )toc ) + da_size - sizeof (const struct toc_item ))) {
483+ (((char * )toc ) + da_size - sizeof (const struct toc_item ))) {
399484 SOLIDIGM_LOG_WARNING (
400485 "Warning: Data Area %d, Table of Contents item %d crossed Data Area size." ,
401486 da , i );
@@ -409,7 +494,7 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
409494 continue ;
410495 }
411496
412- toc_item = json_create_object ();
497+ toc_item = json_object_new_object ();
413498 json_object_array_add (toc_array , toc_item );
414499 json_object_add_value_uint (toc_item , "dataArea" , da );
415500 json_object_add_value_uint (toc_item , "dataAreaIndex" , i );
@@ -443,16 +528,14 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
443528 header -> versionMinor ,
444529 & structure_definition );
445530 }
446- struct json_object * tele_obj_item = json_create_object ();
531+ tele_obj_item = json_object_new_object ();
447532
448533 json_object_array_add (tele_obj_array , tele_obj_item );
449534 json_object_get (toc_item );
450535 json_object_add_value_object (tele_obj_item , "metadata" , toc_item );
451- struct json_object * parsed_struct = json_create_object ();
536+ parsed_struct = json_object_new_object ();
452537
453538 json_object_add_value_object (tele_obj_item , "objectData" , parsed_struct );
454- struct json_object * obj_hasTelemObjHdr = NULL ;
455- uint64_t object_file_offset ;
456539
457540 if (json_object_object_get_ex (structure_definition ,
458541 "hasTelemObjHdr" ,
@@ -464,8 +547,8 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
464547 }
465548 object_file_offset = ((uint64_t )da_offset ) + obj_offset + header_offset ;
466549 if (has_struct ) {
467- telemetry_log_structure_parse (tl , structure_definition ,
468- BITS_IN_BYTE * object_file_offset ,
550+ sldm_telemetry_structure_parse (tl , structure_definition ,
551+ NUM_BITS_IN_BYTE * object_file_offset ,
469552 parsed_struct , toc_item );
470553 }
471554 // NLOGs have different parser from other Telemetry objects
@@ -478,7 +561,7 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
478561 if (json_object_object_get_ex (structure_definition , "sizeBit" ,
479562 & header_sizeBits ))
480563 header_offset = json_object_get_int (header_sizeBits ) /
481- BITS_IN_BYTE ;
564+ NUM_BITS_IN_BYTE ;
482565 // Overwrite nlogName with correct type
483566 if (json_object_object_get_ex (parsed_struct , "nlogSelect" ,
484567 & header_nlogSelect ) &&
@@ -510,17 +593,18 @@ void solidigm_telemetry_log_da1_check_ocp(struct telemetry_log *tl)
510593 const uint64_t ocp_telemetry_uuid [] = {0xBC73719D87E64EFA , 0xBA560A9C3043424C };
511594 const uint64_t * log_uuid = (uint64_t * ) & tl -> log -> data_area [16 ];
512595
513- tl -> is_ocp = tl -> log_size >= (& tl -> log -> data_area [32 ] - (uint8_t * ) tl -> log ) &&
596+ tl -> is_ocp = tl -> log_size >= (size_t )( & tl -> log -> data_area [32 ] - (uint8_t * ) tl -> log ) &&
514597 log_uuid [0 ] == ocp_telemetry_uuid [0 ] && log_uuid [1 ] == ocp_telemetry_uuid [1 ];
515598}
516599
517600int solidigm_telemetry_log_data_areas_parse (struct telemetry_log * tl ,
518601 enum nvme_telemetry_da last_da )
519602{
520- struct json_object * tele_obj_array = json_create_array () ;
521- struct json_object * toc_array = json_create_array () ;
603+ struct json_object * tele_obj_array = NULL ;
604+ struct json_object * toc_array = NULL ;
522605
523606 solidigm_telemetry_log_da1_check_ocp (tl );
607+ sldm_telemetry_da2_check_skhT (tl );
524608 solidigm_telemetry_log_header_parse (tl );
525609 solidigm_telemetry_log_cod_parse (tl );
526610 if (tl -> configuration ) {
@@ -529,6 +613,17 @@ int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl,
529613 if (tl -> is_ocp )
530614 first_da = NVME_TELEMETRY_DA_3 ;
531615
616+ if (tl -> is_skhT ) {
617+ if (last_da >= NVME_TELEMETRY_DA_2 )
618+ sldm_telemetry_skhT_parse (tl );
619+ if (last_da >= NVME_TELEMETRY_DA_3 )
620+ sldm_telemetry_sktT_segment_parse (tl , toc_array ,
621+ tele_obj_array );
622+ return 0 ;
623+ }
624+
625+ tele_obj_array = json_create_array ();
626+ toc_array = json_create_array ();
532627 json_object_add_value_array (tl -> root , "tableOfContents" , toc_array );
533628 json_object_add_value_array (tl -> root , "telemetryObjects" , tele_obj_array );
534629
0 commit comments