blob: e427af87632a3ef73c71f9fcc25419200bb7161c [file] [log] [blame]
Lei YU6505e9d2020-09-21 17:34:32 +08001#include "inspur_oem.hpp"
2
3#include <ipmid/api.h>
4
Lei YU8a454c52020-09-23 16:52:46 +08005#include <phosphor-logging/log.hpp>
6#include <sdbusplus/bus.hpp>
7
8#include <optional>
9
Lei YU17bc93d2020-09-23 19:55:07 +080010namespace
11{
12constexpr auto FIRMWARE_TYPE_OFFSET = 0;
13constexpr auto FIRMWARE_TYPE_SIZE = 1;
14constexpr auto FIRMWARE_VERSION_OFFSET =
15 FIRMWARE_TYPE_OFFSET + FIRMWARE_TYPE_SIZE;
16constexpr auto FIRMWARE_VERSION_SIZE = 15;
17constexpr auto FIRMWARE_BUILDTIME_OFFSET =
18 FIRMWARE_VERSION_OFFSET + FIRMWARE_VERSION_SIZE;
19constexpr auto FIRMWARE_BUILDTIME_SIZE = 20;
20
21static_assert(FIRMWARE_VERSION_OFFSET == 1);
22static_assert(FIRMWARE_BUILDTIME_OFFSET == 16);
23} // namespace
24
Lei YU6505e9d2020-09-21 17:34:32 +080025namespace ipmi
26{
27
Lei YU8a454c52020-09-23 16:52:46 +080028#define UNUSED(x) (void)(x)
Lei YU6505e9d2020-09-21 17:34:32 +080029
Lei YU8a454c52020-09-23 16:52:46 +080030using namespace phosphor::logging;
Lei YU17bc93d2020-09-23 19:55:07 +080031using namespace inspur;
Lei YU8a454c52020-09-23 16:52:46 +080032
33static void registerOEMFunctions() __attribute__((constructor));
34sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
35
36struct ParsedAssetInfo
Lei YU6505e9d2020-09-21 17:34:32 +080037{
Lei YU8a454c52020-09-23 16:52:46 +080038 uint8_t rwFlag;
39 uint8_t deviceType;
40 uint8_t infoType;
41 uint8_t maskAllPresentLen;
42 std::vector<uint8_t> enableStatus;
43 std::vector<uint8_t> maskPresent;
44 std::vector<uint8_t> maskAllPresent;
45 uint8_t allInfoDone;
46 uint16_t totalMessageLen;
47 std::vector<uint8_t> data;
48};
49
50void dumpAssetInfo(const ParsedAssetInfo& info)
51{
Lei YU6505e9d2020-09-21 17:34:32 +080052 fprintf(stderr,
Lei YU8a454c52020-09-23 16:52:46 +080053 "AssetInfo: rw %d, deviceType 0x%02x, infoType 0x%02x, "
54 "maskAllPresentLen %u\n",
55 info.rwFlag, info.deviceType, info.infoType,
56 info.maskAllPresentLen);
57 fprintf(stderr, "enableStatus ");
58 for (const auto& d : info.enableStatus)
59 {
60 fprintf(stderr, "0x%02x ", d);
61 }
62 fprintf(stderr, "\nmaskPresent ");
63 for (const auto& d : info.maskPresent)
64 {
65 fprintf(stderr, "0x%02x ", d);
66 }
67 fprintf(stderr, "\nmaskAllPresent ");
68 for (const auto& d : info.maskAllPresent)
69 {
70 fprintf(stderr, "0x%02x ", d);
71 }
72 fprintf(stderr, "\nallInfoDone %d, totalMessageLen %u\n", info.allInfoDone,
73 info.totalMessageLen);
74 fprintf(stderr, "data: ");
75 for (const auto& d : info.data)
76 {
77 fprintf(stderr, "0x%02x ", d);
78 }
79 fprintf(stderr, "\n");
80}
81
82std::optional<ParsedAssetInfo> parseAssetInfo(const AssetInfoHeader* h)
83{
84 auto len = h->maskAllPresentLen;
85 if (len == 0)
86 {
87 // This is invalid
88 return {};
89 }
90
91 ParsedAssetInfo info;
92 info.rwFlag = h->rwFlag;
93 info.deviceType = h->deviceType;
94 info.infoType = h->infoType;
95 info.maskAllPresentLen = len;
96 info.enableStatus.resize(len);
97 info.maskPresent.resize(len);
98 info.maskAllPresent.resize(len);
99 const uint8_t* p = &h->enableStatus;
100 memcpy(info.enableStatus.data(), p, len);
101 p += len;
102 memcpy(info.maskPresent.data(), p, len);
103 p += len;
104 memcpy(info.maskAllPresent.data(), p, len);
105 p += len;
106 info.allInfoDone = *p++;
107 info.totalMessageLen = *reinterpret_cast<const uint16_t*>(p);
108 p += sizeof(uint16_t);
109 auto dataLen = info.totalMessageLen - (sizeof(AssetInfoHeader) + 3 * len);
110 info.data.resize(dataLen);
111 memcpy(info.data.data(), p, dataLen);
112
Lei YU17bc93d2020-09-23 19:55:07 +0800113 // dumpAssetInfo(info);
Lei YU8a454c52020-09-23 16:52:46 +0800114 return info;
115}
116
Lei YU17bc93d2020-09-23 19:55:07 +0800117void parseBIOSInfo(const std::vector<uint8_t>& data)
118{
119 bios_version_devname dev = static_cast<bios_version_devname>(data[0]);
120 std::string version{data.data() + FIRMWARE_VERSION_OFFSET,
121 data.data() + FIRMWARE_VERSION_SIZE};
122 std::string buildTime;
123 if (dev == bios_version_devname::BIOS)
124 {
125 buildTime.assign(reinterpret_cast<const char*>(
126 data.data() + FIRMWARE_BUILDTIME_OFFSET),
127 FIRMWARE_BUILDTIME_SIZE);
128 }
129
130 printf("Dev %s, version %s, build time %s\n",
131 bios_devname[static_cast<int>(dev)].data(), version.c_str(),
132 buildTime.c_str());
133}
134
Lei YU8a454c52020-09-23 16:52:46 +0800135ipmi_ret_t ipmiOemInspurAssetInfo(ipmi_netfn_t /* netfn */,
136 ipmi_cmd_t /* cmd */, ipmi_request_t request,
137 ipmi_response_t response,
138 ipmi_data_len_t /* data_len */,
139 ipmi_context_t /* context */)
140{
141 auto header = reinterpret_cast<AssetInfoHeader*>(request);
142 uint8_t* res = reinterpret_cast<uint8_t*>(response);
143 UNUSED(res);
144
145 auto info = parseAssetInfo(header);
146 auto deviceType = info->deviceType;
147 if (deviceType != 0x05)
148 {
149 log<level::WARNING>("Device type not supported yet");
150 return IPMI_CC_UNSPECIFIED_ERROR;
151 }
152
153 // For now we only support BIOS type
Lei YU17bc93d2020-09-23 19:55:07 +0800154 parseBIOSInfo(info->data);
Lei YU8a454c52020-09-23 16:52:46 +0800155
Lei YU17bc93d2020-09-23 19:55:07 +0800156 return IPMI_CC_OK;
Lei YU6505e9d2020-09-21 17:34:32 +0800157}
158
159void registerOEMFunctions(void)
160{
161 ipmi_register_callback(NETFN_OEM_INSPUR, CMD_OEM_ASSET_INFO, nullptr,
162 ipmiOemInspurAssetInfo, SYSTEM_INTERFACE);
163}
164
165} // namespace ipmi