Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/solidigm/solidigm-nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "cmd.h"

#define SOLIDIGM_PLUGIN_VERSION "1.15"
#define SOLIDIGM_PLUGIN_VERSION "1.16"

PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
COMMAND_LIST(
Expand Down
28 changes: 19 additions & 9 deletions plugins/solidigm/solidigm-telemetry/cod.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
#include "common.h"
#include "cod.h"
#include "header.h"

const char *oemDataMapDesc[] = {
"Media Read Count", //Uid 0x00
Expand Down Expand Up @@ -170,18 +171,27 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
case FLOAT:
json_object_add_value_float(cod, key, *(float *)val);
break;
case STRING:
json_object_object_add(cod, key,
json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes));
case STRING: {
struct json_object *str_obj = NULL;

sldm_uint8_array_to_string(val, item.DataFieldSizeInBytes, &str_obj);
json_object_object_add(cod, key, str_obj);
break;
case TWO_BYTE_ASCII:
json_object_object_add(cod, key,
json_object_new_string_len((const char *)val, 2));
}
case TWO_BYTE_ASCII: {
struct json_object *str_obj = NULL;

sldm_uint8_array_to_string(val, 2, &str_obj);
json_object_object_add(cod, key, str_obj);
break;
case FOUR_BYTE_ASCII:
json_object_object_add(cod, key,
json_object_new_string_len((const char *)val, 4));
}
case FOUR_BYTE_ASCII: {
struct json_object *str_obj = NULL;

sldm_uint8_array_to_string(val, 4, &str_obj);
json_object_object_add(cod, key, str_obj);
break;
}
default:
SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid);
break;
Expand Down
26 changes: 7 additions & 19 deletions plugins/solidigm/solidigm-telemetry/data-area.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,8 @@ static bool uint8_array_try_string(const struct telemetry_log *tl,
// Get direct pointer to the UINT8 array in the telemetry log
const uint8_t *data_ptr = (const uint8_t *)tl->log + offset_byte;

// Calculate actual string length (stopping at null terminator if found)
size_t actual_length = 0;

for (actual_length = 0; actual_length < array_size; actual_length++) {
if (data_ptr[actual_length] == '\0')
break;
}
// making sure trailing bytes are nulls
for (size_t i = actual_length; i < array_size; i++) {
if (data_ptr[i] != '\0')
return false;
}

// Create JSON string directly from the data without intermediate buffer
*str_obj = json_object_new_string_len((const char *)data_ptr, actual_length);

return true;
// Use the generic converter function
return sldm_uint8_array_to_string(data_ptr, array_size, str_obj);
}

static void reverse_string(char *buff, size_t len)
Expand Down Expand Up @@ -575,11 +560,14 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
&header_nlogName)) {
int nlogName = json_object_get_int(header_nlogName);
char *name = (char *)&nlogName;
struct json_object *nlog_name_obj = NULL;

reverse_string(name, sizeof(uint32_t));
sldm_uint8_array_to_string((const uint8_t *)name,
sizeof(uint32_t),
&nlog_name_obj);
json_object_object_add(header_nlogSelect, "nlogName",
json_object_new_string_len(name,
sizeof(uint32_t)));
nlog_name_obj);
}
}
// Overwrite the object name
Expand Down
197 changes: 117 additions & 80 deletions plugins/solidigm/solidigm-telemetry/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,57 @@
#include "common.h"
#include "header.h"

bool sldm_uint8_array_to_string(const uint8_t *data_ptr, uint32_t array_size,
struct json_object **str_obj)
{
if (!data_ptr || !str_obj) {
if (str_obj)
*str_obj = json_object_new_string("Error: Invalid parameters");
return false;
}

// Calculate actual string length (stopping at null terminator if found)
size_t actual_length = 0;
bool is_ascii = true;

for (actual_length = 0; actual_length < array_size; actual_length++) {
if (data_ptr[actual_length] == '\0')
break;
// Check if character is ASCII printable (0x20-0x7E) or common whitespace
// (0x09, 0x0A, 0x0D)
if (!((data_ptr[actual_length] >= 0x20 && data_ptr[actual_length] <= 0x7E) ||
data_ptr[actual_length] == 0x09 || data_ptr[actual_length] == 0x0A ||
data_ptr[actual_length] == 0x0D)) {
is_ascii = false;
}
}

// Check if there is data after the null terminator
bool has_data_after_terminator = false;

for (size_t i = actual_length; i < array_size; i++) {
if (data_ptr[i] != '\0') {
has_data_after_terminator = true;
// Also check ASCII for data after null terminator
if (!((data_ptr[i] >= 0x20 && data_ptr[i] <= 0x7E) ||
data_ptr[i] == 0x09 || data_ptr[i] == 0x0A ||
data_ptr[i] == 0x0D)) {
is_ascii = false;
}
break;
}
}

// If there is data after the terminator, use the whole array_size
size_t string_length = has_data_after_terminator ? array_size : actual_length;

// Create JSON string directly from the data
*str_obj = json_object_new_string_len((const char *)data_ptr, string_length);

// Return true only if data is ASCII and no data after null terminator
return is_ascii && !has_data_after_terminator;
}

#pragma pack(push, reason_indentifier, 1)
struct reason_indentifier_1_0 {
uint16_t versionMajor;
Expand Down Expand Up @@ -85,72 +136,71 @@ static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl,
struct json_object *reason_id)
{
const struct reason_indentifier_1_0 *ri;
struct json_object *reserved;
struct json_object *reserved = NULL;
struct json_object *firmware_str_obj = NULL;
struct json_object *bootloader_str_obj = NULL;
struct json_object *serial_str_obj = NULL;

ri = (struct reason_indentifier_1_0 *) tl->log->rsnident;
json_object_object_add(reason_id, "firmwareVersion",
json_object_new_string_len(ri->FirmwareVersion,
sizeof(ri->FirmwareVersion)));
json_object_object_add(reason_id, "bootloaderVersion",
json_object_new_string_len(ri->BootloaderVersion,
sizeof(ri->BootloaderVersion)));
json_object_object_add(reason_id, "serialNumber",
json_object_new_string_len(ri->SerialNumber,
sizeof(ri->SerialNumber)));

reserved = json_create_array();
json_object_add_value_array(reason_id, "reserved", reserved);
for (int i = 0; i < sizeof(ri->Reserved); i++) {
struct json_object *val = json_object_new_int(ri->Reserved[i]);

json_object_array_add(reserved, val);
}
sldm_uint8_array_to_string((const uint8_t *)ri->FirmwareVersion,
sizeof(ri->FirmwareVersion), &firmware_str_obj);
json_object_object_add(reason_id, "firmwareVersion", firmware_str_obj);
sldm_uint8_array_to_string((const uint8_t *)ri->BootloaderVersion,
sizeof(ri->BootloaderVersion), &bootloader_str_obj);
json_object_object_add(reason_id, "bootloaderVersion", bootloader_str_obj);
sldm_uint8_array_to_string((const uint8_t *)ri->SerialNumber,
sizeof(ri->SerialNumber), &serial_str_obj);
json_object_object_add(reason_id, "serialNumber", serial_str_obj);

sldm_uint8_array_to_string((const uint8_t *)ri->Reserved,
sizeof(ri->Reserved), &reserved);
json_object_object_add(reason_id, "reserved", reserved);
}

static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl,
struct json_object *reason_id)
{
const struct reason_indentifier_1_1 *ri;
struct json_object *reserved;
struct json_object *reserved = NULL;
struct json_object *firmware_str_obj2 = NULL;
struct json_object *bootloader_str_obj2 = NULL;
struct json_object *serial_str_obj2 = NULL;

ri = (struct reason_indentifier_1_1 *) tl->log->rsnident;
json_object_object_add(reason_id, "firmwareVersion",
json_object_new_string_len(ri->FirmwareVersion,
sizeof(ri->FirmwareVersion)));
json_object_object_add(reason_id, "bootloaderVersion",
json_object_new_string_len(ri->BootloaderVersion,
sizeof(ri->BootloaderVersion)));
json_object_object_add(reason_id, "serialNumber",
json_object_new_string_len(ri->SerialNumber,
sizeof(ri->SerialNumber)));
sldm_uint8_array_to_string((const uint8_t *)ri->FirmwareVersion,
sizeof(ri->FirmwareVersion), &firmware_str_obj2);
json_object_object_add(reason_id, "firmwareVersion", firmware_str_obj2);
sldm_uint8_array_to_string((const uint8_t *)ri->BootloaderVersion,
sizeof(ri->BootloaderVersion), &bootloader_str_obj2);
json_object_object_add(reason_id, "bootloaderVersion", bootloader_str_obj2);
sldm_uint8_array_to_string((const uint8_t *)ri->SerialNumber,
sizeof(ri->SerialNumber), &serial_str_obj2);
json_object_object_add(reason_id, "serialNumber", serial_str_obj2);
json_object_add_value_uint64(reason_id, "oemDataMapOffset",
le64_to_cpu(ri->OemDataMapOffset));
json_object_add_value_uint(reason_id, "telemetryMajorVersion",
le16_to_cpu(ri->TelemetryMajorVersion));
json_object_add_value_uint(reason_id, "telemetryMinorVersion",
le16_to_cpu(ri->TelemetryMinorVersion));

reserved = json_create_array();
json_object_add_value_array(reason_id, "reserved", reserved);
for (int i = 0; i < sizeof(ri->Reserved); i++) {
struct json_object *val = json_object_new_int(ri->Reserved[i]);

json_object_array_add(reserved, val);
}
sldm_uint8_array_to_string((const uint8_t *)ri->Reserved,
sizeof(ri->Reserved), &reserved);
json_object_object_add(reason_id, "reserved", reserved);
}

static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl,
struct json_object *reason_id)
{
const struct reason_indentifier_1_2 *ri;
struct json_object *dp_reserved;
struct json_object *reserved;
struct json_object *dp_reserved = NULL;
struct json_object *reserved = NULL;
struct json_object *serial_str_obj3 = NULL;

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

json_object_object_add(reason_id, "serialNumber",
json_object_new_string_len(ri->SerialNumber,
sizeof(ri->SerialNumber)));
sldm_uint8_array_to_string((const uint8_t *)ri->SerialNumber,
sizeof(ri->SerialNumber), &serial_str_obj3);
json_object_object_add(reason_id, "serialNumber", serial_str_obj3);
json_object_add_value_uint64(reason_id, "oemDataMapOffset",
le64_to_cpu(ri->OemDataMapOffset));
json_object_add_value_uint(reason_id, "telemetryMajorVersion",
Expand All @@ -159,58 +209,44 @@ static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl,
le16_to_cpu(ri->TelemetryMinorVersion));
json_object_add_value_uint(reason_id, "productFamilyId", ri->ProductFamilyId);

reserved = json_create_array();
json_object_add_value_array(reason_id, "reserved2", reserved);
for (int i = 0; i < sizeof(ri->Reserved2); i++) {
struct json_object *val = json_object_new_int(ri->Reserved2[i]);

json_object_array_add(reserved, val);
}

dp_reserved = json_create_array();
json_object_add_value_array(reason_id, "dualPortReserved", dp_reserved);
for (int i = 0; i < sizeof(ri->DualPortReserved); i++) {
struct json_object *val = json_object_new_int(ri->DualPortReserved[i]);
sldm_uint8_array_to_string((const uint8_t *)ri->Reserved2,
sizeof(ri->Reserved2), &reserved);
json_object_object_add(reason_id, "reserved2", reserved);

json_object_array_add(dp_reserved, val);
}
sldm_uint8_array_to_string((const uint8_t *)ri->DualPortReserved,
sizeof(ri->DualPortReserved), &dp_reserved);
json_object_object_add(reason_id, "dualPortReserved", dp_reserved);
}
static void telemetry_log_reason_id_parse_ocp_2_5(const struct telemetry_log *tl,
struct json_object *reason_id)
{
const struct reason_identifier_ocp_2_5 *ri;
struct json_object *reserved;
struct json_object *vu_extension;
struct json_object *reserved = NULL;
struct json_object *vu_extension = NULL;
struct json_object *error_str_obj = NULL;
struct json_object *file_str_obj = NULL;

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

json_object_object_add(reason_id, "errorId",
json_object_new_string_len(ri->errorId,
sizeof(ri->errorId)));
json_object_object_add(reason_id, "fileId",
json_object_new_string_len(ri->fileId,
sizeof(ri->fileId)));
sldm_uint8_array_to_string((const uint8_t *)ri->errorId,
sizeof(ri->errorId), &error_str_obj);
json_object_object_add(reason_id, "errorId", error_str_obj);
sldm_uint8_array_to_string((const uint8_t *)ri->fileId,
sizeof(ri->fileId), &file_str_obj);
json_object_object_add(reason_id, "fileId", file_str_obj);
json_object_add_value_uint(reason_id, "lineNum", le16_to_cpu(ri->lineNum));
json_object_add_value_uint(reason_id, "validLineNum", ri->validFlags.validLineNum);
json_object_add_value_uint(reason_id, "validFileId", ri->validFlags.validFileId);
json_object_add_value_uint(reason_id, "validErrorId", ri->validFlags.validErrorId);
json_object_add_value_uint(reason_id, "validVuExtension", ri->validFlags.validVuExtension);

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

json_object_array_add(reserved, val);
}

vu_extension = json_create_array();
json_object_add_value_array(reason_id, "vuExtension", vu_extension);
for (int i = 0; i < sizeof(ri->vuExtension); i++) {
struct json_object *val = json_object_new_int(ri->vuExtension[i]);

json_object_array_add(vu_extension, val);
}
sldm_uint8_array_to_string((const uint8_t *)ri->vuExtension,
sizeof(ri->vuExtension), &vu_extension);
json_object_object_add(reason_id, "vuExtension", vu_extension);
}

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

if (tl->is_ocp) {
telemetry_log_reason_id_parse_ocp_2_5(tl, reason_id);
Expand All @@ -228,9 +265,9 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t
json_object_add_value_uint(reason_id, "versionMajor", version_major);
json_object_add_value_uint(reason_id, "versionMinor", version_minor);
json_object_add_value_uint(reason_id, "reasonCode", le32_to_cpu(ri1_0->reasonCode));
json_object_add_value_object(reason_id, "driveStatus",
json_object_new_string_len(ri1_0->DriveStatus,
sizeof(ri1_0->DriveStatus)));
sldm_uint8_array_to_string((const uint8_t *)ri1_0->DriveStatus,
sizeof(ri1_0->DriveStatus), &drive_status_obj);
json_object_add_value_object(reason_id, "driveStatus", drive_status_obj);

if (version_major == 1) {
switch (version_minor) {
Expand All @@ -250,7 +287,7 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t
bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl)
{
const struct nvme_telemetry_log *log;
struct json_object *ieee_oui_id;
struct json_object *ieee_oui_id = NULL;
struct json_object *reason_id;
struct json_object *header;

Expand Down
3 changes: 3 additions & 0 deletions plugins/solidigm/solidigm-telemetry/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@
*/

#include "telemetry-log.h"

bool sldm_uint8_array_to_string(const uint8_t *data_ptr, uint32_t array_size,
struct json_object **str_obj);
bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl);
Loading