diff options
Diffstat (limited to 'plugins/solidigm/solidigm-telemetry/header.c')
-rw-r--r-- | plugins/solidigm/solidigm-telemetry/header.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/plugins/solidigm/solidigm-telemetry/header.c b/plugins/solidigm/solidigm-telemetry/header.c new file mode 100644 index 0000000..866ebff --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/header.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "common.h" +#include "header.h" + +#pragma pack(push, reason_indentifier, 1) +struct reason_indentifier_1_0 { + uint16_t versionMajor; + uint16_t versionMinor; + uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. + char DriveStatus[20]; //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020") + char FirmwareVersion[12]; //! Similar to IdentifyController.FR + char BootloaderVersion[12]; //! Bootloader version string + char SerialNumber[20]; //! Device serial number + uint8_t Reserved[56]; //! Reserved for future usage +}; +static_assert(sizeof(const struct reason_indentifier_1_0) == + MEMBER_SIZE(struct nvme_telemetry_log, rsnident), + "Size mismatch for reason_indentifier_1_0"); + +struct reason_indentifier_1_1 { + uint16_t versionMajor; + uint16_t versionMinor; + uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. + char DriveStatus[20]; //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020") + char FirmwareVersion[12]; //! Similar to IdentifyController.FR + char BootloaderVersion[12]; //! Bootloader version string + char SerialNumber[20]; //! Device serial number + uint64_t OemDataMapOffset; //! Customer Data Map Object Log Offset + uint8_t TelemetryMajorVersion; //! Shadow of version in TOC + uint8_t TelemetryMinorVersion; //! Shadow of version in TOC + uint8_t Reserved[46]; //! Reserved for future usage +}; +static_assert(sizeof(const struct reason_indentifier_1_1) == + MEMBER_SIZE(struct nvme_telemetry_log, rsnident), + "Size mismatch for reason_indentifier_1_1"); + +struct reason_indentifier_1_2 { + uint16_t versionMajor; + uint16_t versionMinor; + uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. + char DriveStatus[20]; //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020") + uint8_t Reserved1[24]; //! pad over Fields removed from version 1.1 + char SerialNumber[20]; //! Device serial number + uint64_t OemDataMapOffset; //! Customer Data Map Object Log Offset + uint8_t TelemetryMajorVersion; //! Shadow of version in TOC + uint8_t TelemetryMinorVersion; //! Shadow of version in TOC + uint8_t ProductFamilyId; + uint8_t Reserved2[5]; //! Reserved for future usage + uint8_t DualPortReserved[40]; //! Reserved for dual port +}; +static_assert(sizeof(const struct reason_indentifier_1_2) == + MEMBER_SIZE(struct nvme_telemetry_log, rsnident), + "Size mismatch for reason_indentifier_1_2"); +#pragma pack(pop, reason_indentifier) + +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; + + 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); + } +} + +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; + + 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))); + 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); + } +} + +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; + + 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))); + 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)); + 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]); + + json_object_array_add(dp_reserved, val); + } +} + +static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *tl, struct json_object *reason_id) +{ + const struct reason_indentifier_1_0 *ri1_0 = + (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); + + 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))); + if (version_major == 1) { + switch (version_minor) { + case 0: + telemetry_log_reason_id_parse1_0_ext(tl, reason_id); + break; + case 1: + telemetry_log_reason_id_parse1_1_ext(tl, reason_id); + break; + default: + telemetry_log_reason_id_parse1_2_ext(tl, reason_id); + break; + } + } +} + +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 *reason_id; + struct json_object *header; + + if (tl->log_size < sizeof(const struct nvme_telemetry_log)) { + SOLIDIGM_LOG_WARNING("Telemetry log too short."); + return false; + } + + header = json_create_object(); + + json_object_object_add(tl->root, "telemetryHeader", header); + log = tl->log; + + json_object_add_value_uint(header, "logIdentifier", log->lpi); + ieee_oui_id = json_create_array(); + + json_object_object_add(header, "ieeeOuiIdentifier", ieee_oui_id); + for (int i = 0; i < sizeof(log->ieee); i++) { + struct json_object *val = json_object_new_int(log->ieee[i]); + + json_object_array_add(ieee_oui_id, val); + } + json_object_add_value_uint(header, "dataArea1LastBlock", log->dalb1); + json_object_add_value_uint(header, "dataArea2LastBlock", log->dalb2); + json_object_add_value_uint(header, "dataArea3LastBlock", log->dalb3); + json_object_add_value_uint(header, "hostInitiatedDataGeneration", log->hostdgn); + json_object_add_value_uint(header, "controllerInitiatedDataAvailable", log->ctrlavail); + json_object_add_value_uint(header, "controllerInitiatedDataGeneration", log->ctrldgn); + + reason_id = json_create_object(); + json_object_add_value_object(header, "reasonIdentifier", reason_id); + solidigm_telemetry_log_reason_id_parse(tl, reason_id); + + return true; +} |