From 1baac61a912aca6a9654eedb0ca06c830efdf270 Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Sat, 7 Sep 2024 20:54:47 +0900 Subject: [PATCH] ocp: split ocp-hwcomp log This is to reduce the ocp-nvme.c code size. Signed-off-by: Tokunori Ikegami --- plugins/ocp/meson.build | 1 + plugins/ocp/ocp-hardware-component-log.c | 469 +++++++++++++++++++++++ plugins/ocp/ocp-hardware-component-log.h | 12 + plugins/ocp/ocp-nvme.c | 459 +--------------------- plugins/ocp/ocp-nvme.h | 2 +- 5 files changed, 486 insertions(+), 457 deletions(-) create mode 100644 plugins/ocp/ocp-hardware-component-log.c create mode 100644 plugins/ocp/ocp-hardware-component-log.h diff --git a/plugins/ocp/meson.build b/plugins/ocp/meson.build index 7835444493..6430c101d0 100644 --- a/plugins/ocp/meson.build +++ b/plugins/ocp/meson.build @@ -5,5 +5,6 @@ sources += [ 'plugins/ocp/ocp-smart-extended-log.c', 'plugins/ocp/ocp-fw-activation-history.c', 'plugins/ocp/ocp-telemetry-decode.c', + 'plugins/ocp/ocp-hardware-component-log.c', ] diff --git a/plugins/ocp/ocp-hardware-component-log.c b/plugins/ocp/ocp-hardware-component-log.c new file mode 100644 index 0000000000..8d638c97ce --- /dev/null +++ b/plugins/ocp/ocp-hardware-component-log.c @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024 + */ +#include +#include + +#include "common.h" +#include "util/logging.h" +#include "nvme-print.h" + +#define LID_HWCOMP 0xc6 +#define HWCOMP_RSVD2_LEN 14 +#define GUID_LEN 16 +#define HWCOMP_SIZE_LEN 16 +#define HWCOMP_RSVD48_LEN 16 +//#define HWCOMP_DUMMY + +struct __packed hwcomp_desc { + __le64 date_lot_size; + __le64 add_info_size; + __le32 id; + __le64 mfg; + __le64 rev; + __le64 mfg_code; +}; + +struct __packed hwcomp_log { + __le16 ver; + __u8 rsvd2[HWCOMP_RSVD2_LEN]; + __u8 guid[GUID_LEN]; + __u8 size[HWCOMP_SIZE_LEN]; + __u8 rsvd48[HWCOMP_RSVD48_LEN]; + struct hwcomp_desc *desc; +}; + +struct hwcomp_desc_entry { + struct hwcomp_desc *desc; + __u64 date_lot_size; + __u8 *date_lot_code; + __u64 add_info_size; + __u8 *add_info; + __u64 desc_size; +}; + +enum hwcomp_id { + HWCOMP_ID_RSVD, + HWCOMP_ID_ASIC, + HWCOMP_ID_NAND, + HWCOMP_ID_DRAM, + HWCOMP_ID_PMIC, + HWCOMP_ID_PCB, + HWCOMP_ID_CAP, + HWCOMP_ID_REG, + HWCOMP_ID_CASE, + HWCOMP_ID_SN, + HWCOMP_ID_COUNTRY, + HWCOMP_ID_HW_REV, + HWCOMP_ID_VENDOR = 0x8000, + HWCOMP_ID_MAX = 0xffff, +}; + +#define print_info_array(...) \ + do { \ + if (log_level >= LOG_INFO) \ + print_array(__VA_ARGS__); \ + } while (false) + +#define print_info_error(...) \ + do { \ + if (log_level >= LOG_INFO) \ + fprintf(stderr, __VA_ARGS__); \ + } while (false) + +#ifdef HWCOMP_DUMMY +static __u8 hwcomp_dummy[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdc, 0x57, 0x0f, 0x9f, 0xb9, 0x31, 0x6b, 0xb7, + 0xd0, 0x4e, 0xcd, 0x30, 0x1f, 0x82, 0xb6, 0xbc, + 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 +}; +#endif /* HWCOMP_DUMMY */ + +static const char *hwcomp_id_to_string(__u32 id) +{ + switch (id) { + case HWCOMP_ID_ASIC: + return "Controller ASIC component"; + case HWCOMP_ID_NAND: + return "NAND Component"; + case HWCOMP_ID_DRAM: + return "DRAM Component"; + case HWCOMP_ID_PMIC: + return "PMIC Component"; + case HWCOMP_ID_PCB: + return "PCB Component"; + case HWCOMP_ID_CAP: + return "capacitor component"; + case HWCOMP_ID_REG: + return "registor component"; + case HWCOMP_ID_CASE: + return "case component"; + case HWCOMP_ID_SN: + return "Device Serial Number"; + case HWCOMP_ID_COUNTRY: + return "Country of Origin"; + case HWCOMP_ID_HW_REV: + return "Global Device Hardware Revision"; + case HWCOMP_ID_VENDOR ... HWCOMP_ID_MAX: + return "Vendor Unique Component"; + case HWCOMP_ID_RSVD: + default: + break; + } + + return "Reserved"; +} + +static void print_hwcomp_desc(struct hwcomp_desc_entry *e, bool list, int num) +{ + printf(" Component %d: %s\n", num, hwcomp_id_to_string(le32_to_cpu(e->desc->id))); + + if (list) + return; + + printf(" Date/Lot Size: 0x%"PRIx64"\n", (uint64_t)e->date_lot_size); + printf(" Additional Information Size: 0x%"PRIx64"\n", (uint64_t)e->add_info_size); + printf(" Identifier: 0x%08x\n", le32_to_cpu(e->desc->id)); + printf(" Manufacture: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg)); + printf(" Revision: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->rev)); + printf(" Manufacture Code: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg_code)); + print_array(" Date/Lot Code", e->date_lot_code, e->date_lot_size); + print_array(" Additional Information", e->add_info, e->add_info_size); +} + +static void print_hwcomp_log_normal(struct hwcomp_log *log, __u32 id, bool list) +{ + size_t date_lot_code_offset = sizeof(struct hwcomp_desc); + int num = 1; + struct hwcomp_desc_entry e = { log->desc }; + + long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + + printf("Log Identifier: 0x%02xh\n", LID_HWCOMP); + printf("Log Page Version: 0x%x\n", le16_to_cpu(log->ver)); + print_array("Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2)); + print_array("Log page GUID", log->guid, ARRAY_SIZE(log->guid)); + printf("Hardware Component Log Size: 0x%"PRIx64"\n", (uint64_t)log_size); + print_array("Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48)); + printf("Component Descriptions\n"); + while (log_size > 0) { + e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32); + e.date_lot_code = e.date_lot_size ? (__u8 *)e.desc + date_lot_code_offset : NULL; + e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32); + e.add_info = e.add_info_size ? e.date_lot_code ? e.date_lot_code + e.date_lot_size : + (__u8 *)e.desc + date_lot_code_offset : NULL; + if (!id || id == le32_to_cpu(e.desc->id)) + print_hwcomp_desc(&e, list, num++); + e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size; + e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size); + log_size -= e.desc_size; + } +} + +static void print_hwcomp_desc_json(struct hwcomp_desc_entry *e, struct json_object *r) +{ + obj_add_str(r, "Description", hwcomp_id_to_string(le32_to_cpu(e->desc->id))); + obj_add_nprix64(r, "Date/Lot Size", e->date_lot_size); + obj_add_nprix64(r, "Additional Information Size", e->add_info_size); + obj_add_uint_0nx(r, "Identifier", le32_to_cpu(e->desc->id), 8); + obj_add_0nprix64(r, "Manufacture", le64_to_cpu(e->desc->mfg), 16); + obj_add_0nprix64(r, "Revision", le64_to_cpu(e->desc->rev), 16); + obj_add_0nprix64(r, "Manufacture Code", le64_to_cpu(e->desc->mfg_code), 16); + obj_add_byte_array(r, "Date/Lot Code", e->date_lot_code, e->date_lot_size); + obj_add_byte_array(r, "Additional Information", e->add_info, e->add_info_size); +} + +static void print_hwcomp_desc_list_json(struct json_object *r, struct hwcomp_desc_entry *e, + bool list, int num) +{ + _cleanup_free_ char *k = NULL; + + if (asprintf(&k, "Component %d", num) < 0) + return; + + if (list) { + obj_add_str(r, k, hwcomp_id_to_string(le32_to_cpu(e->desc->id))); + return; + } + + print_hwcomp_desc_json(e, obj_create_array_obj(r, k)); +} + +static void print_hwcomp_descs_json(struct hwcomp_desc *desc, long double log_size, __u32 id, + bool list, struct json_object *r) +{ + size_t date_lot_code_offset = sizeof(struct hwcomp_desc); + struct hwcomp_desc_entry e = { desc }; + int num = 1; + + while (log_size > 0) { + e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32); + e.date_lot_code = e.date_lot_size ? + (__u8 *)e.desc + date_lot_code_offset : NULL; + e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32); + e.add_info = e.add_info_size ? e.date_lot_code ? + e.date_lot_code + e.date_lot_size : + (__u8 *)e.desc + date_lot_code_offset : NULL; + if (!id || id == le32_to_cpu(e.desc->id)) + print_hwcomp_desc_list_json(r, &e, list, num++); + e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size; + e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size); + log_size -= e.desc_size; + } +} + +static void print_hwcomp_log_json(struct hwcomp_log *log, __u32 id, bool list) +{ + struct json_object *r = json_create_object(); + + long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + + obj_add_uint_02x(r, "Log Identifier", LID_HWCOMP); + obj_add_uint_0x(r, "Log Page Version", le16_to_cpu(log->ver)); + obj_add_byte_array(r, "Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2)); + obj_add_byte_array(r, "Log page GUID", log->guid, ARRAY_SIZE(log->guid)); + obj_add_nprix64(r, "Hardware Component Log Size", (unsigned long long)log_size); + obj_add_byte_array(r, "Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48)); + print_hwcomp_descs_json(log->desc, log_size, id, list, + obj_create_array_obj(r, "Component Descriptions")); + + json_print(r); +} + +static void print_hwcomp_log_binary(struct hwcomp_log *log) +{ + long double desc_len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + + d_raw((unsigned char *)log, offsetof(struct hwcomp_log, desc) + desc_len); +} + +static int get_hwcomp_log_data(struct nvme_dev *dev, struct hwcomp_log *log) +{ + int ret = 0; + size_t desc_offset = offsetof(struct hwcomp_log, desc); + struct nvme_get_log_args args = { + .lpo = desc_offset, + .log = log->desc, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .lid = LID_HWCOMP, + .nsid = NVME_NSID_ALL, + }; + +#ifdef HWCOMP_DUMMY + memcpy(log, hwcomp_dummy, desc_offset); +#else /* HWCOMP_DUMMY */ + ret = nvme_get_log_simple(dev_fd(dev), LID_HWCOMP, desc_offset, log); + if (ret) { + print_info_error("error: ocp: failed to get log simple (hwcomp: %02X, ret: %d)\n", + LID_HWCOMP, ret); + return ret; + } +#endif /* HWCOMP_DUMMY */ + + print_info("id: %02Xh\n", LID_HWCOMP); + print_info("version: %04Xh\n", log->ver); + print_info_array("guid", log->guid, ARRAY_SIZE(log->guid)); + print_info("size: %s\n", uint128_t_to_string(le128_to_cpu(log->size))); + + args.len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + log->desc = calloc(1, args.len); + if (!log->desc) { + fprintf(stderr, "error: ocp: calloc: %s\n", strerror(errno)); + return -1; + } + +#ifdef HWCOMP_DUMMY + memcpy(log->desc, &hwcomp_dummy[desc_offset], args.len); +#else /* HWCOMP_DUMMY */ + ret = nvme_get_log_page(dev_fd(dev), NVME_LOG_PAGE_PDU_SIZE, &args); + if (ret) { + print_info_error("error: ocp: failed to get log page (hwcomp: %02X, ret: %d)\n", + LID_HWCOMP, ret); + return ret; + } +#endif /* HWCOMP_DUMMY */ + + return ret; +} + +static int get_hwcomp_log(struct nvme_dev *dev, __u32 id, bool list) +{ + _cleanup_free_ __u8 *desc = NULL; + + int ret; + nvme_print_flags_t fmt; + struct hwcomp_log log = { + .desc = (struct hwcomp_desc *)desc, + }; + + ret = validate_output_format(nvme_cfg.output_format, &fmt); + if (ret < 0) { + fprintf(stderr, "error: ocp: invalid output format\n"); + return ret; + } + + ret = get_hwcomp_log_data(dev, &log); + if (ret) { + print_info_error("error: ocp: failed get hwcomp log: %02X data, ret: %d\n", + LID_HWCOMP, ret); + return ret; + } + + switch (fmt) { + case NORMAL: + print_hwcomp_log_normal(&log, id, list); + break; + case JSON: + print_hwcomp_log_json(&log, id, list); + break; + case BINARY: + print_hwcomp_log_binary(&log); + break; + default: + fprintf(stderr, "unhandled output format\n"); + break; + } + + return 0; +} + +int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + int ret = 0; + const char *desc = "retrieve hardware component log"; + struct config { + __u64 id; + bool list; + } cfg = { 0 }; + const char *id_desc = "component identifier"; + const char *list_desc = "list component descriptions"; + + OPT_VALS(id) = { + VAL_LONG("asic", HWCOMP_ID_ASIC), + VAL_LONG("nand", HWCOMP_ID_NAND), + VAL_LONG("dram", HWCOMP_ID_DRAM), + VAL_LONG("pmic", HWCOMP_ID_PMIC), + VAL_LONG("pcb", HWCOMP_ID_PCB), + VAL_LONG("cap", HWCOMP_ID_CAP), + VAL_LONG("reg", HWCOMP_ID_REG), + VAL_LONG("case", HWCOMP_ID_CASE), + VAL_LONG("sn", HWCOMP_ID_SN), + VAL_LONG("country", HWCOMP_ID_COUNTRY), + VAL_LONG("hw-rev", HWCOMP_ID_HW_REV), + VAL_LONG("vendor", HWCOMP_ID_VENDOR), + VAL_END() + }; + + NVME_ARGS(opts, OPT_LONG("comp-id", 'i', &cfg.id, id_desc, id), + OPT_FLAG("list", 'l', &cfg.list, list_desc)); + + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; + + ret = get_hwcomp_log(dev, cfg.id, cfg.list); + if (ret) + fprintf(stderr, "error: ocp: failed to get hwcomp log: %02X, ret: %d\n", LID_HWCOMP, + ret); + + return ret; +} diff --git a/plugins/ocp/ocp-hardware-component-log.h b/plugins/ocp/ocp-hardware-component-log.h new file mode 100644 index 0000000000..df67b25af4 --- /dev/null +++ b/plugins/ocp/ocp-hardware-component-log.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2024 + */ +#include "cmd.h" + +#ifndef OCP_HARDWARE_COMPONENT_LOG_H +#define OCP_HARDWARE_COMPONENT_LOG_H + +int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); + +#endif /* OCP_HARDWARE_COMPONENT_LOG_H */ diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index 05886ba77a..8c36b6a2b2 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -30,177 +30,12 @@ #include "ocp-clear-features.h" #include "ocp-fw-activation-history.h" #include "ocp-telemetry-decode.h" +#include "ocp-hardware-component-log.h" #define CREATE_CMD #include "ocp-nvme.h" #include "ocp-utils.h" -#define LID_HWCOMP 0xc6 -#define HWCOMP_RSVD2_LEN 14 -#define GUID_LEN 16 -#define HWCOMP_SIZE_LEN 16 -#define HWCOMP_RSVD48_LEN 16 -//#define HWCOMP_DUMMY - -struct __packed hwcomp_desc { - __le64 date_lot_size; - __le64 add_info_size; - __le32 id; - __le64 mfg; - __le64 rev; - __le64 mfg_code; -}; - -struct __packed hwcomp_log { - __le16 ver; - __u8 rsvd2[HWCOMP_RSVD2_LEN]; - __u8 guid[GUID_LEN]; - __u8 size[HWCOMP_SIZE_LEN]; - __u8 rsvd48[HWCOMP_RSVD48_LEN]; - struct hwcomp_desc *desc; -}; - -struct hwcomp_desc_entry { - struct hwcomp_desc *desc; - __u64 date_lot_size; - __u8 *date_lot_code; - __u64 add_info_size; - __u8 *add_info; - __u64 desc_size; -}; - -enum hwcomp_id { - HWCOMP_ID_RSVD, - HWCOMP_ID_ASIC, - HWCOMP_ID_NAND, - HWCOMP_ID_DRAM, - HWCOMP_ID_PMIC, - HWCOMP_ID_PCB, - HWCOMP_ID_CAP, - HWCOMP_ID_REG, - HWCOMP_ID_CASE, - HWCOMP_ID_SN, - HWCOMP_ID_COUNTRY, - HWCOMP_ID_HW_REV, - HWCOMP_ID_VENDOR = 0x8000, - HWCOMP_ID_MAX = 0xffff, -}; - -#define print_info_array(...) \ - do { \ - if (log_level >= LOG_INFO) \ - print_array(__VA_ARGS__); \ - } while (false) - -#define print_info_error(...) \ - do { \ - if (log_level >= LOG_INFO) \ - fprintf(stderr, __VA_ARGS__); \ - } while (false) - -#ifdef HWCOMP_DUMMY -static __u8 hwcomp_dummy[] = { - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xdc, 0x57, 0x0f, 0x9f, 0xb9, 0x31, 0x6b, 0xb7, - 0xd0, 0x4e, 0xcd, 0x30, 0x1f, 0x82, 0xb6, 0xbc, - 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 -}; -#endif /* HWCOMP_DUMMY */ - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -4308,295 +4143,7 @@ static int set_error_injection(int argc, char **argv, struct command *cmd, struc return error_injection_set(dev, &cfg, !argconfig_parse_seen(opts, "no-uuid")); } -static const char *hwcomp_id_to_string(__u32 id) -{ - switch (id) { - case HWCOMP_ID_ASIC: - return "Controller ASIC component"; - case HWCOMP_ID_NAND: - return "NAND Component"; - case HWCOMP_ID_DRAM: - return "DRAM Component"; - case HWCOMP_ID_PMIC: - return "PMIC Component"; - case HWCOMP_ID_PCB: - return "PCB Component"; - case HWCOMP_ID_CAP: - return "capacitor component"; - case HWCOMP_ID_REG: - return "registor component"; - case HWCOMP_ID_CASE: - return "case component"; - case HWCOMP_ID_SN: - return "Device Serial Number"; - case HWCOMP_ID_COUNTRY: - return "Country of Origin"; - case HWCOMP_ID_HW_REV: - return "Global Device Hardware Revision"; - case HWCOMP_ID_VENDOR ... HWCOMP_ID_MAX: - return "Vendor Unique Component"; - case HWCOMP_ID_RSVD: - default: - break; - } - - return "Reserved"; -} - -static void print_hwcomp_desc(struct hwcomp_desc_entry *e, bool list, int num) -{ - printf(" Component %d: %s\n", num, hwcomp_id_to_string(le32_to_cpu(e->desc->id))); - - if (list) - return; - - printf(" Date/Lot Size: 0x%"PRIx64"\n", (uint64_t)e->date_lot_size); - printf(" Additional Information Size: 0x%"PRIx64"\n", (uint64_t)e->add_info_size); - printf(" Identifier: 0x%08x\n", le32_to_cpu(e->desc->id)); - printf(" Manufacture: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg)); - printf(" Revision: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->rev)); - printf(" Manufacture Code: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg_code)); - print_array(" Date/Lot Code", e->date_lot_code, e->date_lot_size); - print_array(" Additional Information", e->add_info, e->add_info_size); -} - -static void print_hwcomp_log_normal(struct hwcomp_log *log, __u32 id, bool list) -{ - size_t date_lot_code_offset = sizeof(struct hwcomp_desc); - int num = 1; - struct hwcomp_desc_entry e = { log->desc }; - - long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); - - printf("Log Identifier: 0x%02xh\n", LID_HWCOMP); - printf("Log Page Version: 0x%x\n", le16_to_cpu(log->ver)); - print_array("Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2)); - print_array("Log page GUID", log->guid, ARRAY_SIZE(log->guid)); - printf("Hardware Component Log Size: 0x%"PRIx64"\n", (uint64_t)log_size); - print_array("Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48)); - printf("Component Descriptions\n"); - while (log_size > 0) { - e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32); - e.date_lot_code = e.date_lot_size ? (__u8 *)e.desc + date_lot_code_offset : NULL; - e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32); - e.add_info = e.add_info_size ? e.date_lot_code ? e.date_lot_code + e.date_lot_size : - (__u8 *)e.desc + date_lot_code_offset : NULL; - if (!id || id == le32_to_cpu(e.desc->id)) - print_hwcomp_desc(&e, list, num++); - e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size; - e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size); - log_size -= e.desc_size; - } -} - -static void print_hwcomp_desc_json(struct hwcomp_desc_entry *e, struct json_object *r) -{ - obj_add_str(r, "Description", hwcomp_id_to_string(le32_to_cpu(e->desc->id))); - obj_add_nprix64(r, "Date/Lot Size", e->date_lot_size); - obj_add_nprix64(r, "Additional Information Size", e->add_info_size); - obj_add_uint_0nx(r, "Identifier", le32_to_cpu(e->desc->id), 8); - obj_add_0nprix64(r, "Manufacture", le64_to_cpu(e->desc->mfg), 16); - obj_add_0nprix64(r, "Revision", le64_to_cpu(e->desc->rev), 16); - obj_add_0nprix64(r, "Manufacture Code", le64_to_cpu(e->desc->mfg_code), 16); - obj_add_byte_array(r, "Date/Lot Code", e->date_lot_code, e->date_lot_size); - obj_add_byte_array(r, "Additional Information", e->add_info, e->add_info_size); -} - -static void print_hwcomp_desc_list_json(struct json_object *r, struct hwcomp_desc_entry *e, - bool list, int num) +static int hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - _cleanup_free_ char *k = NULL; - - if (asprintf(&k, "Component %d", num) < 0) - return; - - if (list) { - obj_add_str(r, k, hwcomp_id_to_string(le32_to_cpu(e->desc->id))); - return; - } - - print_hwcomp_desc_json(e, obj_create_array_obj(r, k)); -} - -static void print_hwcomp_descs_json(struct hwcomp_desc *desc, long double log_size, __u32 id, - bool list, struct json_object *r) -{ - size_t date_lot_code_offset = sizeof(struct hwcomp_desc); - struct hwcomp_desc_entry e = { desc }; - int num = 1; - - while (log_size > 0) { - e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32); - e.date_lot_code = e.date_lot_size ? - (__u8 *)e.desc + date_lot_code_offset : NULL; - e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32); - e.add_info = e.add_info_size ? e.date_lot_code ? - e.date_lot_code + e.date_lot_size : - (__u8 *)e.desc + date_lot_code_offset : NULL; - if (!id || id == le32_to_cpu(e.desc->id)) - print_hwcomp_desc_list_json(r, &e, list, num++); - e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size; - e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size); - log_size -= e.desc_size; - } -} - -static void print_hwcomp_log_json(struct hwcomp_log *log, __u32 id, bool list) -{ - struct json_object *r = json_create_object(); - - long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); - - obj_add_uint_02x(r, "Log Identifier", LID_HWCOMP); - obj_add_uint_0x(r, "Log Page Version", le16_to_cpu(log->ver)); - obj_add_byte_array(r, "Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2)); - obj_add_byte_array(r, "Log page GUID", log->guid, ARRAY_SIZE(log->guid)); - obj_add_nprix64(r, "Hardware Component Log Size", (unsigned long long)log_size); - obj_add_byte_array(r, "Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48)); - print_hwcomp_descs_json(log->desc, log_size, id, list, - obj_create_array_obj(r, "Component Descriptions")); - - json_print(r); -} - -static void print_hwcomp_log_binary(struct hwcomp_log *log) -{ - long double desc_len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); - - d_raw((unsigned char *)log, offsetof(struct hwcomp_log, desc) + desc_len); -} - -static int get_hwcomp_log_data(struct nvme_dev *dev, struct hwcomp_log *log) -{ - int ret = 0; - size_t desc_offset = offsetof(struct hwcomp_log, desc); - struct nvme_get_log_args args = { - .lpo = desc_offset, - .log = log->desc, - .args_size = sizeof(args), - .fd = dev_fd(dev), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .lid = LID_HWCOMP, - .nsid = NVME_NSID_ALL, - }; - -#ifdef HWCOMP_DUMMY - memcpy(log, hwcomp_dummy, desc_offset); -#else /* HWCOMP_DUMMY */ - ret = nvme_get_log_simple(dev_fd(dev), LID_HWCOMP, desc_offset, log); - if (ret) { - print_info_error("error: ocp: failed to get log simple (hwcomp: %02X, ret: %d)\n", - LID_HWCOMP, ret); - return ret; - } -#endif /* HWCOMP_DUMMY */ - - print_info("id: %02Xh\n", LID_HWCOMP); - print_info("version: %04Xh\n", log->ver); - print_info_array("guid", log->guid, ARRAY_SIZE(log->guid)); - print_info("size: %s\n", uint128_t_to_string(le128_to_cpu(log->size))); - - args.len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); - log->desc = calloc(1, args.len); - if (!log->desc) { - fprintf(stderr, "error: ocp: calloc: %s\n", strerror(errno)); - return -1; - } - -#ifdef HWCOMP_DUMMY - memcpy(log->desc, &hwcomp_dummy[desc_offset], args.len); -#else /* HWCOMP_DUMMY */ - ret = nvme_get_log_page(dev_fd(dev), NVME_LOG_PAGE_PDU_SIZE, &args); - if (ret) { - print_info_error("error: ocp: failed to get log page (hwcomp: %02X, ret: %d)\n", - LID_HWCOMP, ret); - return ret; - } -#endif /* HWCOMP_DUMMY */ - - return ret; -} - -static int get_hwcomp_log(struct nvme_dev *dev, __u32 id, bool list) -{ - _cleanup_free_ __u8 *desc = NULL; - - int ret; - nvme_print_flags_t fmt; - struct hwcomp_log log = { - .desc = (struct hwcomp_desc *)desc, - }; - - ret = validate_output_format(nvme_cfg.output_format, &fmt); - if (ret < 0) { - fprintf(stderr, "error: ocp: invalid output format\n"); - return ret; - } - - ret = get_hwcomp_log_data(dev, &log); - if (ret) { - print_info_error("error: ocp: failed get hwcomp log: %02X data, ret: %d\n", - LID_HWCOMP, ret); - return ret; - } - - switch (fmt) { - case NORMAL: - print_hwcomp_log_normal(&log, id, list); - break; - case JSON: - print_hwcomp_log_json(&log, id, list); - break; - case BINARY: - print_hwcomp_log_binary(&log); - break; - default: - fprintf(stderr, "unhandled output format\n"); - break; - } - - return 0; -} - -static int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) -{ - _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; - int ret = 0; - const char *desc = "retrieve hardware component log"; - struct config { - __u64 id; - bool list; - } cfg = { 0 }; - const char *id_desc = "component identifier"; - const char *list_desc = "list component descriptions"; - - OPT_VALS(id) = { - VAL_LONG("asic", HWCOMP_ID_ASIC), - VAL_LONG("nand", HWCOMP_ID_NAND), - VAL_LONG("dram", HWCOMP_ID_DRAM), - VAL_LONG("pmic", HWCOMP_ID_PMIC), - VAL_LONG("pcb", HWCOMP_ID_PCB), - VAL_LONG("cap", HWCOMP_ID_CAP), - VAL_LONG("reg", HWCOMP_ID_REG), - VAL_LONG("case", HWCOMP_ID_CASE), - VAL_LONG("sn", HWCOMP_ID_SN), - VAL_LONG("country", HWCOMP_ID_COUNTRY), - VAL_LONG("hw-rev", HWCOMP_ID_HW_REV), - VAL_LONG("vendor", HWCOMP_ID_VENDOR), - VAL_END() - }; - - NVME_ARGS(opts, OPT_LONG("comp-id", 'i', &cfg.id, id_desc, id), - OPT_FLAG("list", 'l', &cfg.list, list_desc)); - - ret = parse_and_open(&dev, argc, argv, desc, opts); - if (ret) - return ret; - - ret = get_hwcomp_log(dev, cfg.id, cfg.list); - if (ret) - fprintf(stderr, "error: ocp: failed to get hwcomp log: %02X, ret: %d\n", LID_HWCOMP, - ret); - - return ret; + return ocp_hwcomp_log(argc, argv, cmd, plugin); } diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h index dfd9aff61f..9f711a6114 100644 --- a/plugins/ocp/ocp-nvme.h +++ b/plugins/ocp/ocp-nvme.h @@ -38,7 +38,7 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION), ENTRY("tcg-configuration-log", "Retrieve TCG Configuration Log Page", ocp_tcg_configuration_log) ENTRY("get-error-injection", "Return set of error injection", get_error_injection) ENTRY("set-error-injection", "Inject error conditions", set_error_injection) - ENTRY("hardware-component-log", "retrieve hardware component log", ocp_hwcomp_log) + ENTRY("hardware-component-log", "retrieve hardware component log", hwcomp_log) ) );