289 lines
9.3 KiB
C
289 lines
9.3 KiB
C
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
/*
|
||
|
* Copyright (c) 2024
|
||
|
*/
|
||
|
#include <stdio.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include "common.h"
|
||
|
#include "util/types.h"
|
||
|
#include "util/logging.h"
|
||
|
#include "nvme-print.h"
|
||
|
#include "ocp-hardware-component-log.h"
|
||
|
#include "ocp-print.h"
|
||
|
|
||
|
//#define HWCOMP_DUMMY
|
||
|
|
||
|
#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 */
|
||
|
|
||
|
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 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,
|
||
|
.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;
|
||
|
}
|
||
|
|
||
|
args.log = log->desc,
|
||
|
|
||
|
#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;
|
||
|
}
|
||
|
|
||
|
ocp_show_hwcomp_log(&log, id, list, fmt);
|
||
|
|
||
|
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;
|
||
|
}
|