blob: 625bbffcb5c0f98b3509bfff7dfbd9a3800670cc [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
George Liu131de1e2024-06-04 11:07:47 +08005#include <ipmid/api.hpp>
6#include <ipmid/utils.hpp>
George Liu666f96a2024-06-03 19:41:40 +08007#include <phosphor-logging/lg2.hpp>
George Liu131de1e2024-06-04 11:07:47 +08008#include <sdbusplus/bus.hpp>
Lei YU8a454c52020-09-23 16:52:46 +08009
10#include <optional>
11
Lei YU17bc93d2020-09-23 19:55:07 +080012namespace
13{
14constexpr auto FIRMWARE_TYPE_OFFSET = 0;
15constexpr auto FIRMWARE_TYPE_SIZE = 1;
George Liu2ae54232024-04-03 09:40:27 +080016constexpr auto FIRMWARE_VERSION_OFFSET = FIRMWARE_TYPE_OFFSET +
17 FIRMWARE_TYPE_SIZE;
Lei YU17bc93d2020-09-23 19:55:07 +080018constexpr auto FIRMWARE_VERSION_SIZE = 15;
George Liu2ae54232024-04-03 09:40:27 +080019constexpr auto FIRMWARE_BUILDTIME_OFFSET = FIRMWARE_VERSION_OFFSET +
20 FIRMWARE_VERSION_SIZE;
Lei YU17bc93d2020-09-23 19:55:07 +080021constexpr auto FIRMWARE_BUILDTIME_SIZE = 20;
Lei YUebd3d092020-09-27 18:11:48 +080022constexpr auto FIRMWARE_MIN_SIZE = FIRMWARE_BUILDTIME_OFFSET;
Lei YU17bc93d2020-09-23 19:55:07 +080023
24static_assert(FIRMWARE_VERSION_OFFSET == 1);
25static_assert(FIRMWARE_BUILDTIME_OFFSET == 16);
26} // namespace
27
Lei YU6505e9d2020-09-21 17:34:32 +080028namespace ipmi
29{
30
Lei YU8a454c52020-09-23 16:52:46 +080031#define UNUSED(x) (void)(x)
Lei YU6505e9d2020-09-21 17:34:32 +080032
George Liua3a9d2a2024-04-03 09:30:45 +080033using namespace iei;
Lei YU8a454c52020-09-23 16:52:46 +080034
35static void registerOEMFunctions() __attribute__((constructor));
Lei YU8a454c52020-09-23 16:52:46 +080036
37struct ParsedAssetInfo
Lei YU6505e9d2020-09-21 17:34:32 +080038{
Lei YU8a454c52020-09-23 16:52:46 +080039 uint8_t rwFlag;
40 uint8_t deviceType;
41 uint8_t infoType;
42 uint8_t maskAllPresentLen;
43 std::vector<uint8_t> enableStatus;
44 std::vector<uint8_t> maskPresent;
45 std::vector<uint8_t> maskAllPresent;
46 uint8_t allInfoDone;
47 uint16_t totalMessageLen;
48 std::vector<uint8_t> data;
49};
50
51void dumpAssetInfo(const ParsedAssetInfo& info)
52{
Lei YU6505e9d2020-09-21 17:34:32 +080053 fprintf(stderr,
Lei YU8a454c52020-09-23 16:52:46 +080054 "AssetInfo: rw %d, deviceType 0x%02x, infoType 0x%02x, "
55 "maskAllPresentLen %u\n",
56 info.rwFlag, info.deviceType, info.infoType,
57 info.maskAllPresentLen);
58 fprintf(stderr, "enableStatus ");
59 for (const auto& d : info.enableStatus)
60 {
61 fprintf(stderr, "0x%02x ", d);
62 }
63 fprintf(stderr, "\nmaskPresent ");
64 for (const auto& d : info.maskPresent)
65 {
66 fprintf(stderr, "0x%02x ", d);
67 }
68 fprintf(stderr, "\nmaskAllPresent ");
69 for (const auto& d : info.maskAllPresent)
70 {
71 fprintf(stderr, "0x%02x ", d);
72 }
73 fprintf(stderr, "\nallInfoDone %d, totalMessageLen %u\n", info.allInfoDone,
74 info.totalMessageLen);
75 fprintf(stderr, "data: ");
76 for (const auto& d : info.data)
77 {
78 fprintf(stderr, "0x%02x ", d);
79 }
80 fprintf(stderr, "\n");
81}
82
83std::optional<ParsedAssetInfo> parseAssetInfo(const AssetInfoHeader* h)
84{
85 auto len = h->maskAllPresentLen;
86 if (len == 0)
87 {
88 // This is invalid
89 return {};
90 }
91
92 ParsedAssetInfo info;
93 info.rwFlag = h->rwFlag;
94 info.deviceType = h->deviceType;
95 info.infoType = h->infoType;
96 info.maskAllPresentLen = len;
97 info.enableStatus.resize(len);
98 info.maskPresent.resize(len);
99 info.maskAllPresent.resize(len);
100 const uint8_t* p = &h->enableStatus;
101 memcpy(info.enableStatus.data(), p, len);
102 p += len;
103 memcpy(info.maskPresent.data(), p, len);
104 p += len;
105 memcpy(info.maskAllPresent.data(), p, len);
106 p += len;
107 info.allInfoDone = *p++;
108 info.totalMessageLen = *reinterpret_cast<const uint16_t*>(p);
109 p += sizeof(uint16_t);
110 auto dataLen = info.totalMessageLen - (sizeof(AssetInfoHeader) + 3 * len);
111 info.data.resize(dataLen);
112 memcpy(info.data.data(), p, dataLen);
113
Lei YU17bc93d2020-09-23 19:55:07 +0800114 // dumpAssetInfo(info);
Lei YU8a454c52020-09-23 16:52:46 +0800115 return info;
116}
117
Lei YU17bc93d2020-09-23 19:55:07 +0800118void parseBIOSInfo(const std::vector<uint8_t>& data)
119{
Lei YUebd3d092020-09-27 18:11:48 +0800120 if (data.size() < FIRMWARE_MIN_SIZE)
121 {
122 return;
123 }
Lei YU17bc93d2020-09-23 19:55:07 +0800124 bios_version_devname dev = static_cast<bios_version_devname>(data[0]);
125 std::string version{data.data() + FIRMWARE_VERSION_OFFSET,
126 data.data() + FIRMWARE_VERSION_SIZE};
127 std::string buildTime;
128 if (dev == bios_version_devname::BIOS)
129 {
130 buildTime.assign(reinterpret_cast<const char*>(
131 data.data() + FIRMWARE_BUILDTIME_OFFSET),
132 FIRMWARE_BUILDTIME_SIZE);
Lei YU3c341df2020-09-27 13:24:53 +0800133
George Liu131de1e2024-06-04 11:07:47 +0800134 try
135 {
136 // Set BIOS version
137 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
138 auto service = getService(*dbus, VERSION_IFACE, BIOS_OBJPATH);
139 setDbusProperty(*dbus, service, BIOS_OBJPATH, VERSION_IFACE,
140 VERSION, version);
141 }
142 catch (const std::exception& e)
143 {
144 lg2::error("Failed to set BIOS version: {VERSION}, error: {ERROR}",
145 "VERSION", version, "ERROR", e);
146 }
Lei YU17bc93d2020-09-23 19:55:07 +0800147 }
148
149 printf("Dev %s, version %s, build time %s\n",
150 bios_devname[static_cast<int>(dev)].data(), version.c_str(),
151 buildTime.c_str());
152}
153
George Liua3a9d2a2024-04-03 09:30:45 +0800154ipmi_ret_t ipmiOemIEIAssetInfo(ipmi_netfn_t /* netfn */, ipmi_cmd_t /* cmd */,
155 ipmi_request_t request, ipmi_response_t response,
156 ipmi_data_len_t /* data_len */,
157 ipmi_context_t /* context */)
Lei YU8a454c52020-09-23 16:52:46 +0800158{
159 auto header = reinterpret_cast<AssetInfoHeader*>(request);
160 uint8_t* res = reinterpret_cast<uint8_t*>(response);
161 UNUSED(res);
162
163 auto info = parseAssetInfo(header);
164 auto deviceType = info->deviceType;
165 if (deviceType != 0x05)
166 {
George Liu666f96a2024-06-03 19:41:40 +0800167 lg2::info("Device type ({DEVICE_TYPE}) not supported yet",
168 "DEVICE_TYPE", deviceType);
Lei YU8a454c52020-09-23 16:52:46 +0800169 return IPMI_CC_UNSPECIFIED_ERROR;
170 }
171
172 // For now we only support BIOS type
Lei YU17bc93d2020-09-23 19:55:07 +0800173 parseBIOSInfo(info->data);
Lei YU8a454c52020-09-23 16:52:46 +0800174
Lei YU17bc93d2020-09-23 19:55:07 +0800175 return IPMI_CC_OK;
Lei YU6505e9d2020-09-21 17:34:32 +0800176}
177
178void registerOEMFunctions(void)
179{
George Liua3a9d2a2024-04-03 09:30:45 +0800180 ipmi_register_callback(NETFN_OEM_IEI, CMD_OEM_ASSET_INFO, nullptr,
181 ipmiOemIEIAssetInfo, SYSTEM_INTERFACE);
Lei YU6505e9d2020-09-21 17:34:32 +0800182}
183
184} // namespace ipmi