blob: 36087a6e4cddde0ccd56722ef7850dea60a51b98 [file] [log] [blame]
Lei YU3c341df2020-09-27 13:24:53 +08001#include "config.h"
2
George Liua3a9d2a2024-04-03 09:30:45 +08003#include "iei_oem.hpp"
Lei YU6505e9d2020-09-21 17:34:32 +08004
Lei YUebd3d092020-09-27 18:11:48 +08005#include "sdbus_wrapper.hpp"
Lei YU3c341df2020-09-27 13:24:53 +08006#include "utils.hpp"
7
Lei YU6505e9d2020-09-21 17:34:32 +08008#include <ipmid/api.h>
9
Lei YU8a454c52020-09-23 16:52:46 +080010#include <phosphor-logging/log.hpp>
Lei YU8a454c52020-09-23 16:52:46 +080011
12#include <optional>
13
Lei YU17bc93d2020-09-23 19:55:07 +080014namespace
15{
16constexpr auto FIRMWARE_TYPE_OFFSET = 0;
17constexpr auto FIRMWARE_TYPE_SIZE = 1;
18constexpr auto FIRMWARE_VERSION_OFFSET =
19 FIRMWARE_TYPE_OFFSET + FIRMWARE_TYPE_SIZE;
20constexpr auto FIRMWARE_VERSION_SIZE = 15;
21constexpr auto FIRMWARE_BUILDTIME_OFFSET =
22 FIRMWARE_VERSION_OFFSET + FIRMWARE_VERSION_SIZE;
23constexpr auto FIRMWARE_BUILDTIME_SIZE = 20;
Lei YUebd3d092020-09-27 18:11:48 +080024constexpr auto FIRMWARE_MIN_SIZE = FIRMWARE_BUILDTIME_OFFSET;
Lei YU17bc93d2020-09-23 19:55:07 +080025
26static_assert(FIRMWARE_VERSION_OFFSET == 1);
27static_assert(FIRMWARE_BUILDTIME_OFFSET == 16);
28} // namespace
29
Lei YU6505e9d2020-09-21 17:34:32 +080030namespace ipmi
31{
32
Lei YU8a454c52020-09-23 16:52:46 +080033#define UNUSED(x) (void)(x)
Lei YU6505e9d2020-09-21 17:34:32 +080034
Lei YU8a454c52020-09-23 16:52:46 +080035using namespace phosphor::logging;
George Liua3a9d2a2024-04-03 09:30:45 +080036using namespace iei;
Lei YU8a454c52020-09-23 16:52:46 +080037
38static void registerOEMFunctions() __attribute__((constructor));
Lei YUebd3d092020-09-27 18:11:48 +080039static auto& bus = getBus();
Lei YU8a454c52020-09-23 16:52:46 +080040
41struct ParsedAssetInfo
Lei YU6505e9d2020-09-21 17:34:32 +080042{
Lei YU8a454c52020-09-23 16:52:46 +080043 uint8_t rwFlag;
44 uint8_t deviceType;
45 uint8_t infoType;
46 uint8_t maskAllPresentLen;
47 std::vector<uint8_t> enableStatus;
48 std::vector<uint8_t> maskPresent;
49 std::vector<uint8_t> maskAllPresent;
50 uint8_t allInfoDone;
51 uint16_t totalMessageLen;
52 std::vector<uint8_t> data;
53};
54
55void dumpAssetInfo(const ParsedAssetInfo& info)
56{
Lei YU6505e9d2020-09-21 17:34:32 +080057 fprintf(stderr,
Lei YU8a454c52020-09-23 16:52:46 +080058 "AssetInfo: rw %d, deviceType 0x%02x, infoType 0x%02x, "
59 "maskAllPresentLen %u\n",
60 info.rwFlag, info.deviceType, info.infoType,
61 info.maskAllPresentLen);
62 fprintf(stderr, "enableStatus ");
63 for (const auto& d : info.enableStatus)
64 {
65 fprintf(stderr, "0x%02x ", d);
66 }
67 fprintf(stderr, "\nmaskPresent ");
68 for (const auto& d : info.maskPresent)
69 {
70 fprintf(stderr, "0x%02x ", d);
71 }
72 fprintf(stderr, "\nmaskAllPresent ");
73 for (const auto& d : info.maskAllPresent)
74 {
75 fprintf(stderr, "0x%02x ", d);
76 }
77 fprintf(stderr, "\nallInfoDone %d, totalMessageLen %u\n", info.allInfoDone,
78 info.totalMessageLen);
79 fprintf(stderr, "data: ");
80 for (const auto& d : info.data)
81 {
82 fprintf(stderr, "0x%02x ", d);
83 }
84 fprintf(stderr, "\n");
85}
86
87std::optional<ParsedAssetInfo> parseAssetInfo(const AssetInfoHeader* h)
88{
89 auto len = h->maskAllPresentLen;
90 if (len == 0)
91 {
92 // This is invalid
93 return {};
94 }
95
96 ParsedAssetInfo info;
97 info.rwFlag = h->rwFlag;
98 info.deviceType = h->deviceType;
99 info.infoType = h->infoType;
100 info.maskAllPresentLen = len;
101 info.enableStatus.resize(len);
102 info.maskPresent.resize(len);
103 info.maskAllPresent.resize(len);
104 const uint8_t* p = &h->enableStatus;
105 memcpy(info.enableStatus.data(), p, len);
106 p += len;
107 memcpy(info.maskPresent.data(), p, len);
108 p += len;
109 memcpy(info.maskAllPresent.data(), p, len);
110 p += len;
111 info.allInfoDone = *p++;
112 info.totalMessageLen = *reinterpret_cast<const uint16_t*>(p);
113 p += sizeof(uint16_t);
114 auto dataLen = info.totalMessageLen - (sizeof(AssetInfoHeader) + 3 * len);
115 info.data.resize(dataLen);
116 memcpy(info.data.data(), p, dataLen);
117
Lei YU17bc93d2020-09-23 19:55:07 +0800118 // dumpAssetInfo(info);
Lei YU8a454c52020-09-23 16:52:46 +0800119 return info;
120}
121
Lei YU17bc93d2020-09-23 19:55:07 +0800122void parseBIOSInfo(const std::vector<uint8_t>& data)
123{
Lei YUebd3d092020-09-27 18:11:48 +0800124 if (data.size() < FIRMWARE_MIN_SIZE)
125 {
126 return;
127 }
Lei YU17bc93d2020-09-23 19:55:07 +0800128 bios_version_devname dev = static_cast<bios_version_devname>(data[0]);
129 std::string version{data.data() + FIRMWARE_VERSION_OFFSET,
130 data.data() + FIRMWARE_VERSION_SIZE};
131 std::string buildTime;
132 if (dev == bios_version_devname::BIOS)
133 {
134 buildTime.assign(reinterpret_cast<const char*>(
135 data.data() + FIRMWARE_BUILDTIME_OFFSET),
136 FIRMWARE_BUILDTIME_SIZE);
Lei YU3c341df2020-09-27 13:24:53 +0800137
138 // Set BIOS version
139 auto service = utils::getService(bus, BIOS_OBJPATH, VERSION_IFACE);
140 utils::setProperty(bus, service.c_str(), BIOS_OBJPATH, VERSION_IFACE,
141 VERSION, version);
Lei YU17bc93d2020-09-23 19:55:07 +0800142 }
143
144 printf("Dev %s, version %s, build time %s\n",
145 bios_devname[static_cast<int>(dev)].data(), version.c_str(),
146 buildTime.c_str());
147}
148
George Liua3a9d2a2024-04-03 09:30:45 +0800149ipmi_ret_t ipmiOemIEIAssetInfo(ipmi_netfn_t /* netfn */, ipmi_cmd_t /* cmd */,
150 ipmi_request_t request, ipmi_response_t response,
151 ipmi_data_len_t /* data_len */,
152 ipmi_context_t /* context */)
Lei YU8a454c52020-09-23 16:52:46 +0800153{
154 auto header = reinterpret_cast<AssetInfoHeader*>(request);
155 uint8_t* res = reinterpret_cast<uint8_t*>(response);
156 UNUSED(res);
157
158 auto info = parseAssetInfo(header);
159 auto deviceType = info->deviceType;
160 if (deviceType != 0x05)
161 {
162 log<level::WARNING>("Device type not supported yet");
163 return IPMI_CC_UNSPECIFIED_ERROR;
164 }
165
166 // For now we only support BIOS type
Lei YU17bc93d2020-09-23 19:55:07 +0800167 parseBIOSInfo(info->data);
Lei YU8a454c52020-09-23 16:52:46 +0800168
Lei YU17bc93d2020-09-23 19:55:07 +0800169 return IPMI_CC_OK;
Lei YU6505e9d2020-09-21 17:34:32 +0800170}
171
172void registerOEMFunctions(void)
173{
George Liua3a9d2a2024-04-03 09:30:45 +0800174 ipmi_register_callback(NETFN_OEM_IEI, CMD_OEM_ASSET_INFO, nullptr,
175 ipmiOemIEIAssetInfo, SYSTEM_INTERFACE);
Lei YU6505e9d2020-09-21 17:34:32 +0800176}
177
178} // namespace ipmi