Skip to content

Commit c41a4fe

Browse files
committed
plugins/solidigm: Better string handling on Telemetry parsing.
Checking for data in buffer after string termination. Showing reserved uint8_t arrays as (likely empty) strings. Signed-off-by: Leonardo da Cunha <leonardo.da.cunha@solidigm.com>
1 parent 9ed7ba7 commit c41a4fe

File tree

5 files changed

+147
-109
lines changed

5 files changed

+147
-109
lines changed

plugins/solidigm/solidigm-nvme.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#include "cmd.h"
1515

16-
#define SOLIDIGM_PLUGIN_VERSION "1.15"
16+
#define SOLIDIGM_PLUGIN_VERSION "1.16"
1717

1818
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
1919
COMMAND_LIST(

plugins/solidigm/solidigm-telemetry/cod.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
#include "common.h"
88
#include "cod.h"
9+
#include "header.h"
910

1011
const char *oemDataMapDesc[] = {
1112
"Media Read Count", //Uid 0x00
@@ -170,18 +171,27 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
170171
case FLOAT:
171172
json_object_add_value_float(cod, key, *(float *)val);
172173
break;
173-
case STRING:
174-
json_object_object_add(cod, key,
175-
json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes));
174+
case STRING: {
175+
struct json_object *str_obj = NULL;
176+
177+
sldm_uint8_array_to_string(val, item.DataFieldSizeInBytes, &str_obj);
178+
json_object_object_add(cod, key, str_obj);
176179
break;
177-
case TWO_BYTE_ASCII:
178-
json_object_object_add(cod, key,
179-
json_object_new_string_len((const char *)val, 2));
180+
}
181+
case TWO_BYTE_ASCII: {
182+
struct json_object *str_obj = NULL;
183+
184+
sldm_uint8_array_to_string(val, 2, &str_obj);
185+
json_object_object_add(cod, key, str_obj);
180186
break;
181-
case FOUR_BYTE_ASCII:
182-
json_object_object_add(cod, key,
183-
json_object_new_string_len((const char *)val, 4));
187+
}
188+
case FOUR_BYTE_ASCII: {
189+
struct json_object *str_obj = NULL;
190+
191+
sldm_uint8_array_to_string(val, 4, &str_obj);
192+
json_object_object_add(cod, key, str_obj);
184193
break;
194+
}
185195
default:
186196
SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid);
187197
break;

plugins/solidigm/solidigm-telemetry/data-area.c

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,8 @@ static bool uint8_array_try_string(const struct telemetry_log *tl,
4747
// Get direct pointer to the UINT8 array in the telemetry log
4848
const uint8_t *data_ptr = (const uint8_t *)tl->log + offset_byte;
4949

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-
// making sure trailing bytes are nulls
58-
for (size_t i = actual_length; i < array_size; i++) {
59-
if (data_ptr[i] != '\0')
60-
return false;
61-
}
62-
63-
// Create JSON string directly from the data without intermediate buffer
64-
*str_obj = json_object_new_string_len((const char *)data_ptr, actual_length);
65-
66-
return true;
50+
// Use the generic converter function
51+
return sldm_uint8_array_to_string(data_ptr, array_size, str_obj);
6752
}
6853

6954
static void reverse_string(char *buff, size_t len)
@@ -575,11 +560,14 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
575560
&header_nlogName)) {
576561
int nlogName = json_object_get_int(header_nlogName);
577562
char *name = (char *)&nlogName;
563+
struct json_object *nlog_name_obj = NULL;
578564

579565
reverse_string(name, sizeof(uint32_t));
566+
sldm_uint8_array_to_string((const uint8_t *)name,
567+
sizeof(uint32_t),
568+
&nlog_name_obj);
580569
json_object_object_add(header_nlogSelect, "nlogName",
581-
json_object_new_string_len(name,
582-
sizeof(uint32_t)));
570+
nlog_name_obj);
583571
}
584572
}
585573
// Overwrite the object name

plugins/solidigm/solidigm-telemetry/header.c

Lines changed: 117 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,57 @@
88
#include "common.h"
99
#include "header.h"
1010

11+
bool sldm_uint8_array_to_string(const uint8_t *data_ptr, uint32_t array_size,
12+
struct json_object **str_obj)
13+
{
14+
if (!data_ptr || !str_obj) {
15+
if (str_obj)
16+
*str_obj = json_object_new_string("Error: Invalid parameters");
17+
return false;
18+
}
19+
20+
// Calculate actual string length (stopping at null terminator if found)
21+
size_t actual_length = 0;
22+
bool is_ascii = true;
23+
24+
for (actual_length = 0; actual_length < array_size; actual_length++) {
25+
if (data_ptr[actual_length] == '\0')
26+
break;
27+
// Check if character is ASCII printable (0x20-0x7E) or common whitespace
28+
// (0x09, 0x0A, 0x0D)
29+
if (!((data_ptr[actual_length] >= 0x20 && data_ptr[actual_length] <= 0x7E) ||
30+
data_ptr[actual_length] == 0x09 || data_ptr[actual_length] == 0x0A ||
31+
data_ptr[actual_length] == 0x0D)) {
32+
is_ascii = false;
33+
}
34+
}
35+
36+
// Check if there is data after the null terminator
37+
bool has_data_after_terminator = false;
38+
39+
for (size_t i = actual_length; i < array_size; i++) {
40+
if (data_ptr[i] != '\0') {
41+
has_data_after_terminator = true;
42+
// Also check ASCII for data after null terminator
43+
if (!((data_ptr[i] >= 0x20 && data_ptr[i] <= 0x7E) ||
44+
data_ptr[i] == 0x09 || data_ptr[i] == 0x0A ||
45+
data_ptr[i] == 0x0D)) {
46+
is_ascii = false;
47+
}
48+
break;
49+
}
50+
}
51+
52+
// If there is data after the terminator, use the whole array_size
53+
size_t string_length = has_data_after_terminator ? array_size : actual_length;
54+
55+
// Create JSON string directly from the data
56+
*str_obj = json_object_new_string_len((const char *)data_ptr, string_length);
57+
58+
// Return true only if data is ASCII and no data after null terminator
59+
return is_ascii && !has_data_after_terminator;
60+
}
61+
1162
#pragma pack(push, reason_indentifier, 1)
1263
struct reason_indentifier_1_0 {
1364
uint16_t versionMajor;
@@ -85,72 +136,71 @@ static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl,
85136
struct json_object *reason_id)
86137
{
87138
const struct reason_indentifier_1_0 *ri;
88-
struct json_object *reserved;
139+
struct json_object *reserved = NULL;
140+
struct json_object *firmware_str_obj = NULL;
141+
struct json_object *bootloader_str_obj = NULL;
142+
struct json_object *serial_str_obj = NULL;
89143

90144
ri = (struct reason_indentifier_1_0 *) tl->log->rsnident;
91-
json_object_object_add(reason_id, "firmwareVersion",
92-
json_object_new_string_len(ri->FirmwareVersion,
93-
sizeof(ri->FirmwareVersion)));
94-
json_object_object_add(reason_id, "bootloaderVersion",
95-
json_object_new_string_len(ri->BootloaderVersion,
96-
sizeof(ri->BootloaderVersion)));
97-
json_object_object_add(reason_id, "serialNumber",
98-
json_object_new_string_len(ri->SerialNumber,
99-
sizeof(ri->SerialNumber)));
100-
101-
reserved = json_create_array();
102-
json_object_add_value_array(reason_id, "reserved", reserved);
103-
for (int i = 0; i < sizeof(ri->Reserved); i++) {
104-
struct json_object *val = json_object_new_int(ri->Reserved[i]);
105-
106-
json_object_array_add(reserved, val);
107-
}
145+
sldm_uint8_array_to_string((const uint8_t *)ri->FirmwareVersion,
146+
sizeof(ri->FirmwareVersion), &firmware_str_obj);
147+
json_object_object_add(reason_id, "firmwareVersion", firmware_str_obj);
148+
sldm_uint8_array_to_string((const uint8_t *)ri->BootloaderVersion,
149+
sizeof(ri->BootloaderVersion), &bootloader_str_obj);
150+
json_object_object_add(reason_id, "bootloaderVersion", bootloader_str_obj);
151+
sldm_uint8_array_to_string((const uint8_t *)ri->SerialNumber,
152+
sizeof(ri->SerialNumber), &serial_str_obj);
153+
json_object_object_add(reason_id, "serialNumber", serial_str_obj);
154+
155+
sldm_uint8_array_to_string((const uint8_t *)ri->Reserved,
156+
sizeof(ri->Reserved), &reserved);
157+
json_object_object_add(reason_id, "reserved", reserved);
108158
}
109159

110160
static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl,
111161
struct json_object *reason_id)
112162
{
113163
const struct reason_indentifier_1_1 *ri;
114-
struct json_object *reserved;
164+
struct json_object *reserved = NULL;
165+
struct json_object *firmware_str_obj2 = NULL;
166+
struct json_object *bootloader_str_obj2 = NULL;
167+
struct json_object *serial_str_obj2 = NULL;
115168

116169
ri = (struct reason_indentifier_1_1 *) tl->log->rsnident;
117-
json_object_object_add(reason_id, "firmwareVersion",
118-
json_object_new_string_len(ri->FirmwareVersion,
119-
sizeof(ri->FirmwareVersion)));
120-
json_object_object_add(reason_id, "bootloaderVersion",
121-
json_object_new_string_len(ri->BootloaderVersion,
122-
sizeof(ri->BootloaderVersion)));
123-
json_object_object_add(reason_id, "serialNumber",
124-
json_object_new_string_len(ri->SerialNumber,
125-
sizeof(ri->SerialNumber)));
170+
sldm_uint8_array_to_string((const uint8_t *)ri->FirmwareVersion,
171+
sizeof(ri->FirmwareVersion), &firmware_str_obj2);
172+
json_object_object_add(reason_id, "firmwareVersion", firmware_str_obj2);
173+
sldm_uint8_array_to_string((const uint8_t *)ri->BootloaderVersion,
174+
sizeof(ri->BootloaderVersion), &bootloader_str_obj2);
175+
json_object_object_add(reason_id, "bootloaderVersion", bootloader_str_obj2);
176+
sldm_uint8_array_to_string((const uint8_t *)ri->SerialNumber,
177+
sizeof(ri->SerialNumber), &serial_str_obj2);
178+
json_object_object_add(reason_id, "serialNumber", serial_str_obj2);
126179
json_object_add_value_uint64(reason_id, "oemDataMapOffset",
127180
le64_to_cpu(ri->OemDataMapOffset));
128181
json_object_add_value_uint(reason_id, "telemetryMajorVersion",
129182
le16_to_cpu(ri->TelemetryMajorVersion));
130183
json_object_add_value_uint(reason_id, "telemetryMinorVersion",
131184
le16_to_cpu(ri->TelemetryMinorVersion));
132185

133-
reserved = json_create_array();
134-
json_object_add_value_array(reason_id, "reserved", reserved);
135-
for (int i = 0; i < sizeof(ri->Reserved); i++) {
136-
struct json_object *val = json_object_new_int(ri->Reserved[i]);
137-
138-
json_object_array_add(reserved, val);
139-
}
186+
sldm_uint8_array_to_string((const uint8_t *)ri->Reserved,
187+
sizeof(ri->Reserved), &reserved);
188+
json_object_object_add(reason_id, "reserved", reserved);
140189
}
141190

142191
static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl,
143192
struct json_object *reason_id)
144193
{
145194
const struct reason_indentifier_1_2 *ri;
146-
struct json_object *dp_reserved;
147-
struct json_object *reserved;
195+
struct json_object *dp_reserved = NULL;
196+
struct json_object *reserved = NULL;
197+
struct json_object *serial_str_obj3 = NULL;
148198

149199
ri = (struct reason_indentifier_1_2 *) tl->log->rsnident;
150200

151-
json_object_object_add(reason_id, "serialNumber",
152-
json_object_new_string_len(ri->SerialNumber,
153-
sizeof(ri->SerialNumber)));
201+
sldm_uint8_array_to_string((const uint8_t *)ri->SerialNumber,
202+
sizeof(ri->SerialNumber), &serial_str_obj3);
203+
json_object_object_add(reason_id, "serialNumber", serial_str_obj3);
154204
json_object_add_value_uint64(reason_id, "oemDataMapOffset",
155205
le64_to_cpu(ri->OemDataMapOffset));
156206
json_object_add_value_uint(reason_id, "telemetryMajorVersion",
@@ -159,58 +209,44 @@ static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl,
159209
le16_to_cpu(ri->TelemetryMinorVersion));
160210
json_object_add_value_uint(reason_id, "productFamilyId", ri->ProductFamilyId);
161211

162-
reserved = json_create_array();
163-
json_object_add_value_array(reason_id, "reserved2", reserved);
164-
for (int i = 0; i < sizeof(ri->Reserved2); i++) {
165-
struct json_object *val = json_object_new_int(ri->Reserved2[i]);
166-
167-
json_object_array_add(reserved, val);
168-
}
169-
170-
dp_reserved = json_create_array();
171-
json_object_add_value_array(reason_id, "dualPortReserved", dp_reserved);
172-
for (int i = 0; i < sizeof(ri->DualPortReserved); i++) {
173-
struct json_object *val = json_object_new_int(ri->DualPortReserved[i]);
212+
sldm_uint8_array_to_string((const uint8_t *)ri->Reserved2,
213+
sizeof(ri->Reserved2), &reserved);
214+
json_object_object_add(reason_id, "reserved2", reserved);
174215

175-
json_object_array_add(dp_reserved, val);
176-
}
216+
sldm_uint8_array_to_string((const uint8_t *)ri->DualPortReserved,
217+
sizeof(ri->DualPortReserved), &dp_reserved);
218+
json_object_object_add(reason_id, "dualPortReserved", dp_reserved);
177219
}
178220
static void telemetry_log_reason_id_parse_ocp_2_5(const struct telemetry_log *tl,
179221
struct json_object *reason_id)
180222
{
181223
const struct reason_identifier_ocp_2_5 *ri;
182-
struct json_object *reserved;
183-
struct json_object *vu_extension;
224+
struct json_object *reserved = NULL;
225+
struct json_object *vu_extension = NULL;
226+
struct json_object *error_str_obj = NULL;
227+
struct json_object *file_str_obj = NULL;
184228

185229
ri = (struct reason_identifier_ocp_2_5 *) tl->log->rsnident;
186230

187-
json_object_object_add(reason_id, "errorId",
188-
json_object_new_string_len(ri->errorId,
189-
sizeof(ri->errorId)));
190-
json_object_object_add(reason_id, "fileId",
191-
json_object_new_string_len(ri->fileId,
192-
sizeof(ri->fileId)));
231+
sldm_uint8_array_to_string((const uint8_t *)ri->errorId,
232+
sizeof(ri->errorId), &error_str_obj);
233+
json_object_object_add(reason_id, "errorId", error_str_obj);
234+
sldm_uint8_array_to_string((const uint8_t *)ri->fileId,
235+
sizeof(ri->fileId), &file_str_obj);
236+
json_object_object_add(reason_id, "fileId", file_str_obj);
193237
json_object_add_value_uint(reason_id, "lineNum", le16_to_cpu(ri->lineNum));
194238
json_object_add_value_uint(reason_id, "validLineNum", ri->validFlags.validLineNum);
195239
json_object_add_value_uint(reason_id, "validFileId", ri->validFlags.validFileId);
196240
json_object_add_value_uint(reason_id, "validErrorId", ri->validFlags.validErrorId);
197241
json_object_add_value_uint(reason_id, "validVuExtension", ri->validFlags.validVuExtension);
198242

199-
reserved = json_create_array();
200-
json_object_add_value_array(reason_id, "reserved", reserved);
201-
for (int i = 0; i < sizeof(ri->reserved); i++) {
202-
struct json_object *val = json_object_new_int(ri->reserved[i]);
243+
sldm_uint8_array_to_string((const uint8_t *)ri->reserved,
244+
sizeof(ri->reserved), &reserved);
245+
json_object_object_add(reason_id, "reserved", reserved);
203246

204-
json_object_array_add(reserved, val);
205-
}
206-
207-
vu_extension = json_create_array();
208-
json_object_add_value_array(reason_id, "vuExtension", vu_extension);
209-
for (int i = 0; i < sizeof(ri->vuExtension); i++) {
210-
struct json_object *val = json_object_new_int(ri->vuExtension[i]);
211-
212-
json_object_array_add(vu_extension, val);
213-
}
247+
sldm_uint8_array_to_string((const uint8_t *)ri->vuExtension,
248+
sizeof(ri->vuExtension), &vu_extension);
249+
json_object_object_add(reason_id, "vuExtension", vu_extension);
214250
}
215251

216252
static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *tl, struct json_object *reason_id)
@@ -219,6 +255,7 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t
219255
(struct reason_indentifier_1_0 *) tl->log->rsnident;
220256
uint16_t version_major = le16_to_cpu(ri1_0->versionMajor);
221257
uint16_t version_minor = le16_to_cpu(ri1_0->versionMinor);
258+
struct json_object *drive_status_obj = NULL;
222259

223260
if (tl->is_ocp) {
224261
telemetry_log_reason_id_parse_ocp_2_5(tl, reason_id);
@@ -228,9 +265,9 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t
228265
json_object_add_value_uint(reason_id, "versionMajor", version_major);
229266
json_object_add_value_uint(reason_id, "versionMinor", version_minor);
230267
json_object_add_value_uint(reason_id, "reasonCode", le32_to_cpu(ri1_0->reasonCode));
231-
json_object_add_value_object(reason_id, "driveStatus",
232-
json_object_new_string_len(ri1_0->DriveStatus,
233-
sizeof(ri1_0->DriveStatus)));
268+
sldm_uint8_array_to_string((const uint8_t *)ri1_0->DriveStatus,
269+
sizeof(ri1_0->DriveStatus), &drive_status_obj);
270+
json_object_add_value_object(reason_id, "driveStatus", drive_status_obj);
234271

235272
if (version_major == 1) {
236273
switch (version_minor) {
@@ -250,7 +287,7 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t
250287
bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl)
251288
{
252289
const struct nvme_telemetry_log *log;
253-
struct json_object *ieee_oui_id;
290+
struct json_object *ieee_oui_id = NULL;
254291
struct json_object *reason_id;
255292
struct json_object *header;
256293

plugins/solidigm/solidigm-telemetry/header.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@
66
*/
77

88
#include "telemetry-log.h"
9+
10+
bool sldm_uint8_array_to_string(const uint8_t *data_ptr, uint32_t array_size,
11+
struct json_object **str_obj);
912
bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl);

0 commit comments

Comments
 (0)