]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
solidigm: Added parsing for telemetry customer screenable data
authorleonardo.da.cunha <leo.da.cunha@solidigm.com>
Thu, 15 Sep 2022 23:01:55 +0000 (16:01 -0700)
committerDaniel Wagner <dwagner@suse.de>
Fri, 28 Oct 2022 08:23:59 +0000 (10:23 +0200)
[dwagner: - shorted overlong lines
          - moved decleration at the beginning of the
    block]
Signed-off-by: Daniel Wagner <dwagner@suse.de>
16 files changed:
plugins/solidigm/solidigm-garbage-collection.c
plugins/solidigm/solidigm-latency-tracking.c
plugins/solidigm/solidigm-nvme.h
plugins/solidigm/solidigm-smart.c
plugins/solidigm/solidigm-telemetry.c
plugins/solidigm/solidigm-telemetry/cod.c
plugins/solidigm/solidigm-telemetry/cod.h
plugins/solidigm/solidigm-telemetry/config.c [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/config.h [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/data-area.c [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/data-area.h [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/header.c [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/header.h [moved from plugins/solidigm/solidigm-telemetry/reason-id.h with 50% similarity]
plugins/solidigm/solidigm-telemetry/meson.build
plugins/solidigm/solidigm-telemetry/reason-id.c [deleted file]
plugins/solidigm/solidigm-telemetry/telemetry-log.h

index 060233a32815012bec856938189d9d12289c2020..8e2ecccf5360a92ce4aef23aa898f47e2597d3b5 100644 (file)
@@ -108,6 +108,8 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c
                nvme_show_status(err);
        }
 
+       /* Redundant close() to make static code analysis happy */
+       close(dev->direct.fd);
        dev_close(dev);
        return err;
 }
index 072945ae6a254cc2af76bd79322d6de8d5f469b1..1013ae81830f3bbfab8a2a21da3d827cb07a6b79 100644 (file)
@@ -468,6 +468,8 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd
        } else {
                fprintf(stderr, "Could not read feature id 0xE2.\n");
        }
+       /* Redundant close() to make static code analysis happy */
+       close(dev->direct.fd);
        dev_close(dev);
        return err;
 }
index a1f48f631a32011cc171c96941fd15f4ccf677d5..ed48400093b2dfe1a8e4cf16be7ed7447249afd9 100644 (file)
@@ -13,7 +13,7 @@
 
 #include "cmd.h"
 
-#define SOLIDIGM_PLUGIN_VERSION "0.5"
+#define SOLIDIGM_PLUGIN_VERSION "0.6"
 
 PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
        COMMAND_LIST(
index 4acbf847ef18bf9723ce8867ae8750602f2ff0d7..77c26ac19bd6e789ab7987349f9f524217735103 100644 (file)
@@ -245,6 +245,8 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd
                nvme_show_status(err);
        }
 
+       /* Redundant close() to make static code analysis happy */
+       close(dev->direct.fd);
        dev_close(dev);
        return err;
 }
index 49bccf9e53e29c9da15aab66846d65f8ded56b00..7cd48c2315c794430cdd6633213bbd9b553d6a91 100644 (file)
 #include "solidigm-telemetry.h"
 #include "solidigm-telemetry/telemetry-log.h"
 #include "solidigm-telemetry/cod.h"
-#include "solidigm-telemetry/reason-id.h"
+#include "solidigm-telemetry/header.h"
+#include "solidigm-telemetry/config.h"
+#include "solidigm-telemetry/data-area.h"
+
+static int read_file2buffer(char *file_name, char **buffer, size_t *length)
+{
+       FILE *fd = fopen(file_name, "rb");
+
+       if (!fd)
+               return errno;
+
+       fseek(fd, 0, SEEK_END);
+       size_t length_bytes = ftell(fd);
+
+       fseek(fd, 0, SEEK_SET);
+
+       *buffer = malloc(length_bytes);
+       if (!*buffer) {
+               fclose(fd);
+               return errno;
+       }
+       *length = fread(*buffer, 1, length_bytes, fd);
+       fclose(fd);
+       return 0;
+}
 
 struct config {
        __u32 host_gen;
        bool ctrl_init;
-       int     data_area;
+       int  data_area;
+       char *cfg_file;
+       bool is_input_file;
 };
 
 int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -33,63 +59,125 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
        const char *hgen = "Controls when to generate new host initiated report. Default value '1' generates new host initiated report, value '0' causes retrieval of existing log.";
        const char *cgen = "Gather report generated by the controller.";
        const char *dgen = "Pick which telemetry data area to report. Default is 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4.";
+       const char *cfile = "JSON configuration file";
+       const char *sfile = "data source <device> is binary file containing log dump instead of block or character device";
        struct nvme_dev *dev;
 
        struct telemetry_log tl = {
                .root = json_create_object(),
+               .log = NULL,
        };
 
        struct config cfg = {
-               .host_gen       = 1,
-               .ctrl_init      = false,
-               .data_area      = 3,
+               .host_gen   = 1,
+               .ctrl_init  = false,
+               .data_area  = 3,
+               .cfg_file   = NULL,
+               .is_input_file = false,
        };
 
        OPT_ARGS(opts) = {
                OPT_UINT("host-generate",   'g', &cfg.host_gen,  hgen),
                OPT_FLAG("controller-init", 'c', &cfg.ctrl_init, cgen),
                OPT_UINT("data-area",       'd', &cfg.data_area, dgen),
+               OPT_FILE("config-file",     'j', &cfg.cfg_file, cfile),
+               OPT_FLAG("source-file",     's', &cfg.is_input_file, sfile),
                OPT_END()
        };
 
-       int err = parse_and_open(&dev, argc, argv, desc, opts);
+       int err = argconfig_parse(argc, argv, desc, opts);
+
+       if (err)
+               goto ret;
+
+       if (cfg.is_input_file) {
+               if (optind >= argc) {
+                       err = errno = EINVAL;
+                       perror(argv[0]);
+                       goto ret;
+               }
+               char *binary_file_name = argv[optind];
+
+               err = read_file2buffer(binary_file_name, (char **)&tl.log, &tl.log_size);
+       } else {
+               err = parse_and_open(&dev, argc, argv, desc, opts);
+       }
        if (err)
                goto ret;
 
        if (cfg.host_gen > 1) {
-               fprintf(stderr, "Invalid host-generate value '%d'\n", cfg.host_gen);
+               SOLIDIGM_LOG_WARNING("Invalid host-generate value '%d'", cfg.host_gen);
                err = EINVAL;
                goto close_fd;
        }
-       
-       if (cfg.ctrl_init)
-               err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &tl.log, cfg.data_area, &tl.log_size);
-       else if (cfg.host_gen)
-               err = nvme_get_new_host_telemetry(dev_fd(dev), &tl.log, cfg.data_area, &tl.log_size);
-       else
-               err = nvme_get_host_telemetry(dev_fd(dev), &tl.log, cfg.data_area, &tl.log_size);
 
-       if (err < 0) {
-               fprintf(stderr, "get-telemetry-log: %s\n",
-                       nvme_strerror(errno));
-               goto close_fd;
-       } else if (err > 0) {
-               nvme_show_status(err);
-               fprintf(stderr, "Failed to acquire telemetry log %d!\n", err);
-               goto close_fd;
+       if (cfg.cfg_file) {
+               char *conf_str = 0;
+               size_t length;
+
+               err = read_file2buffer(cfg.cfg_file, &conf_str, &length);
+               if (err) {
+                       SOLIDIGM_LOG_WARNING("Failed to open JSON configuration file %s: %s!",
+                               cfg.cfg_file, strerror(err));
+                       goto close_fd;
+               }
+               json_tokener * jstok = json_tokener_new();
+
+               tl.configuration = json_tokener_parse_ex(jstok, conf_str, length);
+               if (jstok->err != json_tokener_success) {
+                       SOLIDIGM_LOG_WARNING("Parsing error on JSON configuration file %s: %s (at offset %d)",
+                                            cfg.cfg_file,
+                                            json_tokener_error_desc(jstok->err),
+                                            jstok->char_offset);
+                       json_tokener_free(jstok);
+                       err = EINVAL;
+                       goto close_fd;
+               }
+               json_tokener_free(jstok);
        }
 
-       solidigm_telemetry_log_reason_id_parse(&tl);
-       solidigm_telemetry_log_cod_parse(&tl);
-       
+       if (!cfg.is_input_file) {
+               if (cfg.ctrl_init)
+                       err = nvme_get_ctrl_telemetry(dev_fd(dev), true,
+                                                     &tl.log, cfg.data_area,
+                                                     &tl.log_size);
+               else if (cfg.host_gen)
+                       err = nvme_get_new_host_telemetry(dev_fd(dev), &tl.log,
+                                                         cfg.data_area,
+                                                         &tl.log_size);
+               else
+                       err = nvme_get_host_telemetry(dev_fd(dev), &tl.log,
+                                                     cfg.data_area,
+                                                     &tl.log_size);
+
+               if (err < 0) {
+                       SOLIDIGM_LOG_WARNING("get-telemetry-log: %s",
+                                            nvme_strerror(errno));
+                       goto close_fd;
+               } else if (err > 0) {
+                       nvme_show_status(err);
+                       SOLIDIGM_LOG_WARNING("Failed to acquire telemetry log %d!", err);
+                       goto close_fd;
+               }
+       }
+       solidigm_telemetry_log_header_parse(&tl);
+       if (cfg.cfg_file)
+               solidigm_telemetry_log_data_areas_parse(&tl, cfg.data_area);
+       else
+               solidigm_telemetry_log_cod_parse(&tl);
+
        json_print_object(tl.root, NULL);
        json_free_object(tl.root);
        printf("\n");
 
-       free(tl.log);
-
 close_fd:
-       dev_close(dev);
+       if (!cfg.is_input_file) {
+               /* Redundant close() to make static code analysis happy */
+               close(dev->direct.fd);
+               dev_close(dev);
+       }
 ret:
+       json_free_object(tl.configuration);
+       free(tl.log);
        return err;
-}
\ No newline at end of file
+}
index 518c53ebf93aeaf8b7b34f38efaf0c365b995687..a659fd9ceaa5fbdc48dc612e6d672c5bbd0f1670 100644 (file)
@@ -110,14 +110,16 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
 
                UNKNOWN = 0xFF,
        };
+       json_object *telemetry_header = NULL;
        json_object *COD_offset = NULL;
        json_object *reason_id = NULL;
-       if (!json_object_object_get_ex(tl->root, "reason_identifier", &reason_id)) {
-                       return;
-       }
-       if  (!json_object_object_get_ex(reason_id, "OemDataMapOffset", &COD_offset)) {
-                       return;
-       }
+
+       if (!json_object_object_get_ex(tl->root, "telemetryHeader", &telemetry_header))
+               return;
+       if (!json_object_object_get_ex(telemetry_header, "reasonIdentifier", &reason_id))
+               return;
+       if  (!json_object_object_get_ex(reason_id, "OemDataMapOffset", &COD_offset))
+               return;
 
        __u64 offset = json_object_get_int(COD_offset);
 
@@ -126,7 +128,7 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
        }
 
        if ((offset + sizeof(struct cod_header)) > tl->log_size) {
-               fprintf(stderr, "COD map header out of bounds.\n");
+               SOLIDIGM_LOG_WARNING("Warning: COD map header out of bounds.");
                return;
        }
 
@@ -134,11 +136,11 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
 
        uint32_t signature = be32_to_cpu(data->header.Signature);
        if ( signature != OEMSIGNATURE){
-               fprintf(stderr, "Unsupported COD data signature %x!\n", signature);
+               SOLIDIGM_LOG_WARNING("Warning: Unsupported COD data signature %x!", signature);
                return;
        }
        if ((offset + data->header.MapSizeInBytes) > tl->log_size){
-               fprintf(stderr, "COD map data out of bounds.\n");
+               SOLIDIGM_LOG_WARNING("Warning: COD map data out of bounds.");
                return;
        }
 
@@ -148,7 +150,7 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
        for (int i =0 ; i < data->header.EntryCount; i++) {
                if ((offset + sizeof(struct cod_header) + (i + 1) * sizeof(struct cod_item)) >
                tl->log_size){
-                       fprintf(stderr, "COD data out of bounds at item %d!\n", i);
+                       SOLIDIGM_LOG_WARNING("Warning: COD data out of bounds at item %d!", i);
                        return;
                }
                struct cod_item item = data->items[i];
@@ -163,7 +165,7 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
                switch(item.dataFieldType){
                        case(INTEGER):
                                if (item.issigned) {
-                                       json_object_object_add(cod, key, 
+                                       json_object_object_add(cod, key,
                                                json_object_new_int64(le64_to_cpu(*(uint64_t *)val)));
                                } else {
                                        json_object_add_value_uint64(cod, key, le64_to_cpu(*(uint64_t *)val));
@@ -173,19 +175,19 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
                                json_object_add_value_float(cod, key, *(float *) val);
                                break;
                        case(STRING):
-                               json_object_object_add(cod, key, 
+                               json_object_object_add(cod, key,
                                        json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes));
                                break;
                        case(TWO_BYTE_ASCII):
-                               json_object_object_add(cod, key, 
+                               json_object_object_add(cod, key,
                                        json_object_new_string_len((const char *)val,2));
                                break;
                        case(FOUR_BYTE_ASCII):
-                               json_object_object_add(cod, key, 
+                               json_object_object_add(cod, key,
                                        json_object_new_string_len((const char *)val, 4));
                                break;
                        default:
-                               fprintf(stderr,"Unknown COD field type (%d)\n", item.DataFieldMapUid);
+                               SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid);
                                
                }
        }
index f8ffb4156659aa9012446702ff474dd9d29a3dc1..7f3a12ae4a6729beb3d055b0910e8817c3e0a8f2 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: MIT-0
+/* SPDX-License-Identifier: MIT-0 */
 /*
  * Copyright (c) 2022 Solidigm.
  *
diff --git a/plugins/solidigm/solidigm-telemetry/config.c b/plugins/solidigm/solidigm-telemetry/config.c
new file mode 100644 (file)
index 0000000..1466e94
--- /dev/null
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+#include <stdbool.h>
+#include "util/json.h"
+#include <stdio.h>
+
+// max 16 bit unsigned integer nummber 65535
+#define MAX_16BIT_NUM_AS_STRING_SIZE  6
+
+static bool config_get_by_version(const json_object *obj, int version_major,
+                                 int version_minor, json_object **value)
+{
+       char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
+       char str_subkey[MAX_16BIT_NUM_AS_STRING_SIZE];
+
+       snprintf(str_key, sizeof(str_key), "%d", version_major);
+       snprintf(str_subkey, sizeof(str_subkey), "%d", version_minor);
+       json_object *major_obj = NULL;
+
+       if (!json_object_object_get_ex(obj, str_key, &major_obj))
+               return false;
+       if  (!json_object_object_get_ex(major_obj, str_subkey, value))
+               return false;
+       return value != NULL;
+}
+
+bool solidigm_config_get_by_token_version(const json_object *obj, int token_id,
+                                         int version_major, int version_minor,
+                                         json_object **value)
+{
+       json_object *token_obj = NULL;
+       char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
+
+       snprintf(str_key, sizeof(str_key), "%d", token_id);
+       if (!json_object_object_get_ex(obj, str_key, &token_obj))
+               return false;
+       if  (!config_get_by_version(token_obj, version_major, version_minor, value))
+               return false;
+       return value != NULL;
+}
diff --git a/plugins/solidigm/solidigm-telemetry/config.h b/plugins/solidigm/solidigm-telemetry/config.h
new file mode 100644 (file)
index 0000000..e320258
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: MIT-0 */
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+#include <stdbool.h>
+#include "util/json.h"
+
+bool solidigm_config_get_by_token_version(const json_object *obj, int key, int subkey, int subsubkey, json_object **value);
diff --git a/plugins/solidigm/solidigm-telemetry/data-area.c b/plugins/solidigm/solidigm-telemetry/data-area.c
new file mode 100644 (file)
index 0000000..4421188
--- /dev/null
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#include "common.h"
+#include "data-area.h"
+#include "config.h"
+#include <ctype.h>
+
+#define SIGNED_INT_PREFIX "int"
+#define BITS_IN_BYTE 8
+
+#define MAX_WARNING_SIZE 1024
+
+static bool telemetry_log_get_value(const struct telemetry_log *tl,
+                                   uint32_t offset_bit, uint32_t size_bit,
+                                   bool is_signed, json_object **val_obj)
+{
+       uint32_t offset_bit_from_byte;
+       uint32_t additional_size_byte;
+       uint32_t offset_byte;
+       uint32_t val;
+
+       if (size_bit == 0) {
+               char err_msg[MAX_WARNING_SIZE];
+
+               snprintf(err_msg, MAX_WARNING_SIZE,
+                        "Value with size_bit=0 not supported.");
+               *val_obj = json_object_new_string(err_msg);
+
+               return false;
+       }
+       additional_size_byte = (size_bit - 1) ? (size_bit - 1) / BITS_IN_BYTE : 0;
+       offset_byte = offset_bit / BITS_IN_BYTE;
+
+       if (offset_byte > (tl->log_size - additional_size_byte)) {
+               char err_msg[MAX_WARNING_SIZE];
+
+               snprintf(err_msg, MAX_WARNING_SIZE,
+                       "Value offset greater than binary size (%u > %lu).",
+                        offset_byte, tl->log_size);
+               *val_obj = json_object_new_string(err_msg);
+
+               return false;
+       }
+
+       offset_bit_from_byte = offset_bit - (offset_byte * BITS_IN_BYTE);
+
+       if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * BITS_IN_BYTE)) {
+               char err_msg[MAX_WARNING_SIZE];
+
+               snprintf(err_msg, MAX_WARNING_SIZE,
+                        "Value crossing 64 bit, byte aligned bounday, "
+                        "not supported. size_bit=%u, offset_bit_from_byte=%u.",
+                         size_bit, offset_bit_from_byte);
+               *val_obj = json_object_new_string(err_msg);
+
+               return false;
+       }
+
+       val = *(uint64_t *)(((char *)tl->log) + offset_byte);
+       val >>= offset_bit_from_byte;
+       if (size_bit < 64)
+               val &= (1ULL << size_bit) - 1;
+       if (is_signed) {
+               if (val >> (size_bit - 1))
+                       val |= -1ULL << size_bit;
+               *val_obj = json_object_new_int64(val);
+       } else {
+               *val_obj = json_object_new_uint64(val);
+       }
+
+       return true;
+}
+
+static int telemetry_log_structure_parse(const struct telemetry_log *tl,
+                                        json_object *struct_def,
+                                        size_t parent_offset_bit,
+                                        json_object *output,
+                                        json_object *metadata)
+{
+       json_object *obj_arraySizeArray = NULL;
+       json_object *obj = NULL;
+       json_object *obj_memberList;
+       json_object *major_dimension;
+       json_object *sub_output;
+       bool is_enumeration = false;
+       bool has_member_list;
+       const char *type = "";
+       const char *name;
+       size_t array_rank;
+       size_t offset_bit;
+       size_t size_bit;
+       uint32_t linear_array_pos_bit;
+
+       if (!json_object_object_get_ex(struct_def, "name", &obj)) {
+               SOLIDIGM_LOG_WARNING("Warning: Structure definition missing property 'name': %s",
+                                    json_object_to_json_string(struct_def));
+               return  -1;
+       }
+
+       name = json_object_get_string(obj);
+
+       if (metadata) {
+               json_object_get(obj);
+               json_object_object_add(metadata, "objName", obj);
+       }
+
+       if (json_object_object_get_ex(struct_def, "type", &obj))
+               type = json_object_get_string(obj);
+
+       if (!json_object_object_get_ex(struct_def, "offsetBit", &obj)) {
+               SOLIDIGM_LOG_WARNING("Warning: Structure definition missing "
+                                    "property 'offsetBit': %s",
+                                    json_object_to_json_string(struct_def));
+               return  -1;
+       }
+
+       offset_bit = json_object_get_uint64(obj);
+
+       if (!json_object_object_get_ex(struct_def, "sizeBit", &obj)) {
+               SOLIDIGM_LOG_WARNING("Warning: Structure definition missing "
+                                    "property 'sizeBit': %s",
+                                    json_object_to_json_string(struct_def));
+               return  -1;
+       }
+
+       size_bit = json_object_get_uint64(obj);
+
+       if (json_object_object_get_ex(struct_def, "enum", &obj))
+               is_enumeration = json_object_get_boolean(obj);
+
+       has_member_list = json_object_object_get_ex(struct_def,
+                                                   "memberList",
+                                                   &obj_memberList);
+
+       if (!json_object_object_get_ex(struct_def, "arraySize",
+                                      &obj_arraySizeArray)) {
+               SOLIDIGM_LOG_WARNING("Warning: Structure definition missing "
+                                    "property 'arraySize': %s",
+                                    json_object_to_json_string(struct_def));
+               return  -1;
+       }
+
+       array_rank = json_object_array_length(obj_arraySizeArray);
+       if (array_rank == 0) {
+               SOLIDIGM_LOG_WARNING("Warning: Structure property 'arraySize' "
+                                    "don't support flexible array: %s",
+                                    json_object_to_json_string(struct_def));
+               return -1;
+       }
+       uint32_t array_size_dimension[array_rank];
+
+       for (size_t i = 0; i < array_rank; i++) {
+               json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i);
+
+               array_size_dimension[i] = json_object_get_uint64(dimension);
+               major_dimension = dimension;
+       }
+       if (array_rank > 1) {
+               uint32_t linear_pos_per_index = array_size_dimension[0];
+               uint32_t prev_index_offset_bit = 0;
+               json_object *dimension_output;
+
+               for (int i = 1; i < (array_rank - 1); i++)
+                       linear_pos_per_index *= array_size_dimension[i];
+
+               dimension_output = json_create_array();
+               if (json_object_get_type(output) == json_type_array)
+                       json_object_array_add(output, dimension_output);
+               else
+                       json_object_add_value_array(output, name, dimension_output);
+
+               /*
+                * Make sure major_dimension object will not be
+                * deleted from memory when deleted from array
+                */
+               json_object_get(major_dimension);
+               json_object_array_del_idx(obj_arraySizeArray, array_rank - 1, 1);
+
+               for (int i = 0 ; i < array_size_dimension[0]; i++) {
+                       json_object *sub_array = json_create_array();
+                       size_t offset;
+
+                       offset = parent_offset_bit + prev_index_offset_bit;
+
+                       json_object_array_add(dimension_output, sub_array);
+                       telemetry_log_structure_parse(tl, struct_def,
+                                                     offset, sub_array, NULL);
+                       prev_index_offset_bit += linear_pos_per_index * size_bit;
+               }
+
+               json_object_array_put_idx(obj_arraySizeArray, array_rank - 1,
+                                         major_dimension);
+
+               return 0;
+       }
+
+       linear_array_pos_bit = 0;
+       sub_output = output;
+
+       if (array_size_dimension[0] > 1) {
+               sub_output = json_create_array();
+               if (json_object_get_type(output) == json_type_array)
+                       json_object_array_add(output, sub_output);
+               else
+                       json_object_add_value_array(output, name, sub_output);
+       }
+
+       for (uint32_t j = 0; j < array_size_dimension[0]; j++) {
+               if (is_enumeration || !has_member_list) {
+                       bool is_signed = !strncmp(type, SIGNED_INT_PREFIX, sizeof(SIGNED_INT_PREFIX)-1);
+                       json_object *val_obj;
+                       size_t offset;
+
+                       offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
+                       if (telemetry_log_get_value(tl, offset, size_bit, is_signed, &val_obj)) {
+                               if (array_size_dimension[0] > 1)
+                                       json_object_array_put_idx(sub_output, j, val_obj);
+                               else
+                                       json_object_object_add(sub_output, name, val_obj);
+                       } else {
+                               SOLIDIGM_LOG_WARNING("Warning: %s From property '%s', "
+                                                    "array index %u, structure definition: %s",
+                                                    json_object_get_string(val_obj),
+                                                    name, j, json_object_to_json_string(struct_def));
+                               json_free_object(val_obj);
+                       }
+               } else {
+                       json_object *sub_sub_output = json_object_new_object();
+                       int num_members;
+
+                       if (array_size_dimension[0] > 1)
+                               json_object_array_put_idx(sub_output, j, sub_sub_output);
+                       else
+                               json_object_add_value_object(sub_output, name, sub_sub_output);
+
+                       num_members = json_object_array_length(obj_memberList);
+                       for (int k = 0; k < num_members; k++) {
+                               json_object *member = json_object_array_get_idx(obj_memberList, k);
+                               size_t offset;
+
+                               offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
+                               telemetry_log_structure_parse(tl, member, offset,
+                                                             sub_sub_output, NULL);
+                       }
+               }
+               linear_array_pos_bit += size_bit;
+       }
+       return 0;
+}
+
+static int telemetry_log_data_area_get_offset(const struct telemetry_log *tl,
+                                             enum nvme_telemetry_da da,
+                                             uint32_t *offset, uint32_t *size)
+{
+       uint32_t offset_blocks = 1;
+       uint32_t last_block = tl->log->dalb1;
+       uint32_t last;
+
+       switch (da) {
+       case NVME_TELEMETRY_DA_1:
+               offset_blocks = 1;
+               last_block = tl->log->dalb1;
+               break;
+       case NVME_TELEMETRY_DA_2:
+               offset_blocks = tl->log->dalb1 + 1;
+               last_block = tl->log->dalb2;
+               break;
+       case NVME_TELEMETRY_DA_3:
+               offset_blocks = tl->log->dalb2 + 1;
+               last_block = tl->log->dalb3;
+               break;
+       case NVME_TELEMETRY_DA_4:
+               offset_blocks = tl->log->dalb3 + 1;
+               last_block = tl->log->dalb4;
+               break;
+       default:
+               return -1;
+       }
+
+       *offset = offset_blocks * NVME_LOG_TELEM_BLOCK_SIZE;
+       last = (last_block + 1) * NVME_LOG_TELEM_BLOCK_SIZE;
+       *size = last - *offset;
+       if ((*offset > tl->log_size) || (last > tl->log_size) || (last <= *offset)) {
+               SOLIDIGM_LOG_WARNING("Warning: Data Area %d don't fit this Telemetry log.", da);
+               return -1;
+       }
+
+       return 0;
+}
+
+struct toc_item {
+       uint32_t OffsetBytes;
+       uint32_t ContentSizeBytes;
+};
+
+struct data_area_header {
+       uint8_t versionMajor;
+       uint8_t versionMinor;
+       uint16_t TableOfContentsCount;
+       uint32_t DataAreaSize;
+       uint8_t Reserved[8];
+};
+
+struct table_of_contents {
+       struct data_area_header header;
+       struct toc_item items[];
+};
+
+struct telemetry_object_header {
+       uint16_t versionMajor;
+       uint16_t versionMinor;
+       uint32_t Token;
+       uint8_t CoreId;
+       uint8_t Reserved[3];
+};
+
+
+static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
+                                             enum nvme_telemetry_da da,
+                                             json_object *toc_array,
+                                             json_object *tele_obj_array)
+{
+
+       const struct telemetry_object_header *header;
+       const struct table_of_contents *toc;
+       char *payload;
+       uint32_t da_offset;
+       uint32_t da_size;
+
+       if (telemetry_log_data_area_get_offset(tl, da, &da_offset, &da_size))
+               return;
+
+       toc = (struct table_of_contents *)(((char *)tl->log) + da_offset);
+       payload = (char *) tl->log;
+
+       for (int i = 0; i < toc->header.TableOfContentsCount; i++) {
+               json_object *structure_definition = NULL;
+               json_object *toc_item;
+               uint32_t obj_offset;
+               bool has_struct;
+
+               if ((char *)&toc->items[i] > (((char *)toc) + da_size - sizeof(const struct toc_item))) {
+                       SOLIDIGM_LOG_WARNING("Warning: Data Area %d, "
+                                            "Table of Contents item %d "
+                                            "crossed Data Area size.", da, i);
+                       return;
+               }
+
+               obj_offset = toc->items[i].OffsetBytes;
+               if ((obj_offset + sizeof(const struct telemetry_object_header)) > da_size) {
+                       SOLIDIGM_LOG_WARNING("Warning: Data Area %d, item %d "
+                                            "data, crossed Data Area size.", da, i);
+                       continue;
+               }
+
+               toc_item = json_create_object();
+               json_object_array_add(toc_array, toc_item);
+               json_object_add_value_uint(toc_item, "dataArea", da);
+               json_object_add_value_uint(toc_item, "dataAreaIndex", i);
+               json_object_add_value_uint(toc_item, "dataAreaOffset", obj_offset);
+               json_object_add_value_uint(toc_item, "fileOffset", obj_offset + da_offset);
+               json_object_add_value_uint(toc_item, "size", toc->items[i].ContentSizeBytes);
+
+               header = (const struct telemetry_object_header *) (payload + da_offset + obj_offset);
+               json_object_add_value_uint(toc_item, "telemMajor", header->versionMajor);
+               json_object_add_value_uint(toc_item, "telemMinor", header->versionMinor);
+               json_object_add_value_uint(toc_item, "objectId", header->Token);
+               json_object_add_value_uint(toc_item, "mediaBankId", header->CoreId);
+
+               has_struct = solidigm_config_get_by_token_version(tl->configuration,
+                                                                 header->Token,
+                                                                 header->versionMajor,
+                                                                 header->versionMinor,
+                                                                 &structure_definition);
+
+               if (has_struct) {
+                       json_object *tele_obj_item = json_create_object();
+
+                       json_object_array_add(tele_obj_array, tele_obj_item);
+                       json_object_get(toc_item);
+                       json_object_add_value_object(tele_obj_item, "metadata", toc_item);
+                       json_object *parsed_struct = json_object_new_object();
+
+                       json_object_add_value_object(tele_obj_item, "objectData", parsed_struct);
+                       json_object *obj_hasTelemObjHdr = NULL;
+                       uint32_t header_offset = sizeof(const struct telemetry_object_header);
+                       uint32_t file_offset;
+
+                       if (json_object_object_get_ex(structure_definition,
+                                                     "hasTelemObjHdr",
+                                                      &obj_hasTelemObjHdr)) {
+                               bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr);
+
+                               if (hasHeader)
+                                       header_offset = 0;
+                       }
+
+                       file_offset = da_offset + obj_offset + header_offset;
+                       telemetry_log_structure_parse(tl, structure_definition,
+                                                     BITS_IN_BYTE * file_offset,
+                                                     parsed_struct, toc_item);
+               }
+       }
+}
+
+int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl,
+                                           enum nvme_telemetry_da last_da)
+{
+       json_object *tele_obj_array = json_create_array();
+       json_object *toc_array = json_create_array();
+
+       json_object_add_value_array(tl->root, "tableOfContents", toc_array);
+       json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array);
+
+       for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++)
+               telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array);
+
+       return 0;
+}
diff --git a/plugins/solidigm/solidigm-telemetry/data-area.h b/plugins/solidigm/solidigm-telemetry/data-area.h
new file mode 100644 (file)
index 0000000..2e78caf
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT-0 */
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+#include "common.h"
+#include "telemetry-log.h"
+
+int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl,
+                                           enum nvme_telemetry_da last_da);
diff --git a/plugins/solidigm/solidigm-telemetry/header.c b/plugins/solidigm/solidigm-telemetry/header.c
new file mode 100644 (file)
index 0000000..d1a379c
--- /dev/null
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * 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,
+                                                json_object *reason_id)
+{
+       const struct reason_indentifier_1_0 *ri;
+       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++) {
+               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,
+                                                json_object *reason_id)
+{
+       const struct reason_indentifier_1_1 *ri;
+       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++) {
+               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,
+                                                json_object *reason_id)
+{
+       const struct reason_indentifier_1_2 *ri;
+       json_object *dp_reserved;
+       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++) {
+               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++) {
+               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, json_object *reason_id)
+{
+       const struct reason_indentifier_1_0 *ri1_0 =
+               (struct reason_indentifier_1_0 *) tl->log->rsnident;
+       __u16 version_major = le16_to_cpu(ri1_0->versionMajor);
+       __u16 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);
+               }
+       }
+}
+
+bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl)
+{
+       const struct nvme_telemetry_log *log;
+       json_object *ieee_oui_id;
+       json_object *reason_id;
+       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++) {
+               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;
+}
similarity index 50%
rename from plugins/solidigm/solidigm-telemetry/reason-id.h
rename to plugins/solidigm/solidigm-telemetry/header.h
index d47d186d2029516a1c7b6845affc3cf90d8ac3db..332a165d0446f5cc6b1f93021351b9d1b46e2bb6 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: MIT-0
+/* SPDX-License-Identifier: MIT-0 */
 /*
  * Copyright (c) 2022 Solidigm.
  *
@@ -6,4 +6,4 @@
  */
 
 #include "telemetry-log.h"
-void solidigm_telemetry_log_reason_id_parse(struct telemetry_log *tl);
+bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl);
index 5fd560342073c7d40a1b20769954defd355e785a..53ab452c21ec97e3b0aa8cbfbfb946d055f95b84 100644 (file)
@@ -1,4 +1,6 @@
 sources += [
   'plugins/solidigm/solidigm-telemetry/cod.c',
-  'plugins/solidigm/solidigm-telemetry/reason-id.c',
+  'plugins/solidigm/solidigm-telemetry/header.c',
+  'plugins/solidigm/solidigm-telemetry/config.c',
+  'plugins/solidigm/solidigm-telemetry/data-area.c',
 ]
diff --git a/plugins/solidigm/solidigm-telemetry/reason-id.c b/plugins/solidigm/solidigm-telemetry/reason-id.c
deleted file mode 100644 (file)
index 9007b89..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-// SPDX-License-Identifier: MIT-0
-/*
- * Copyright (c) 2022 Solidigm.
- *
- * Author: leonardo.da.cunha@solidigm.com
- */
-
-#include "common.h"
-#include "reason-id.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
-};
-
-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
-};
-
-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
-};
-#pragma pack(pop, reason_indentifier)
-
-static void telemetry_log_reason_id_parse1_0_ext(struct telemetry_log *tl, json_object *reason_id)
-{
-       const struct reason_indentifier_1_0 *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)));
-       json_object *reserved = json_create_array();
-       json_object_add_value_array(reason_id, "Reserved", reserved);
-       for ( int i=0; i < sizeof(ri->Reserved); i++) {
-               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(struct telemetry_log *tl, json_object *reason_id)
-{
-       const struct reason_indentifier_1_1 *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));
-       json_object *reserved = json_create_array();
-       json_object_add_value_array(reason_id, "Reserved", reserved);
-       for ( int i=0; i < sizeof(ri->Reserved); i++) {
-               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(struct telemetry_log *tl, json_object *reason_id)
-{
-       const struct reason_indentifier_1_2 *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);
-       json_object *reserved = json_create_array();
-       json_object_add_value_array(reason_id, "Reserved2", reserved);
-       for ( int i=0; i < sizeof(ri->Reserved2); i++) {
-               json_object *val = json_object_new_int(ri->Reserved2[i]);
-               json_object_array_add(reserved, val);
-       }
-       json_object *dp_reserved = json_create_array();
-       json_object_add_value_array(reason_id, "DualPortReserved", dp_reserved);
-       for ( int i=0; i < sizeof(ri->DualPortReserved); i++) {
-               json_object *val =  json_object_new_int(ri->DualPortReserved[i]);
-               json_object_array_add(dp_reserved, val);
-       }
-}
-
-void solidigm_telemetry_log_reason_id_parse(struct telemetry_log *tl)
-{
-       json_object *reason_id = json_create_object();
-       struct reason_indentifier_1_0 * ri1_0 = (struct reason_indentifier_1_0 *) tl->log->rsnident;
-       __u16 version_major = le16_to_cpu(ri1_0->versionMajor);
-       __u16 version_minor = le16_to_cpu(ri1_0->versionMinor);
-       json_object_add_value_object(tl->root, "reason_identifier", reason_id);
-       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_object_add(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);
-               }
-       }
-}
index 1b18a7e731abdb8805e552afe5d124b270430d9e..9e8773a0b52745f7a56712c66995d4620563cbae 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: MIT-0
+/* SPDX-License-Identifier: MIT-0 */
 /*
  * Copyright (c) 2022 Solidigm.
  *
 
 #include "libnvme.h"
 #include "util/json.h"
+#include <assert.h>
+
+#if !defined __cplusplus
+#define static_assert _Static_assert
+#endif
+
+#define VA_ARGS(...), ##__VA_ARGS__
+#define SOLIDIGM_LOG_WARNING(format, ...) fprintf(stderr, format"\n" VA_ARGS(__VA_ARGS__))
+
+#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
 
 struct telemetry_log {
        struct nvme_telemetry_log *log;
        size_t log_size;
        json_object *root;
+       json_object *configuration;
 };
 
 #endif /* _SOLIDIGM_TELEMETRY_LOG_H */
\ No newline at end of file