blob: bffab0f2808eefb787760d3d7689ade0df86d447 [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
George Liu666f96a2024-06-03 19:41:40 +080010#include <phosphor-logging/lg2.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;
George Liu2ae54232024-04-03 09:40:27 +080018constexpr auto FIRMWARE_VERSION_OFFSET = FIRMWARE_TYPE_OFFSET +
19 FIRMWARE_TYPE_SIZE;
Lei YU17bc93d2020-09-23 19:55:07 +080020constexpr auto FIRMWARE_VERSION_SIZE = 15;
George Liu2ae54232024-04-03 09:40:27 +080021constexpr auto FIRMWARE_BUILDTIME_OFFSET = FIRMWARE_VERSION_OFFSET +
22 FIRMWARE_VERSION_SIZE;
Lei YU17bc93d2020-09-23 19:55:07 +080023constexpr 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
George Liua3a9d2a2024-04-03 09:30:45 +080035using namespace iei;
Lei YU8a454c52020-09-23 16:52:46 +080036
37static void registerOEMFunctions() __attribute__((constructor));
Lei YUebd3d092020-09-27 18:11:48 +080038static auto& bus = getBus();
Lei YU8a454c52020-09-23 16:52:46 +080039
40struct ParsedAssetInfo
Lei YU6505e9d2020-09-21 17:34:32 +080041{
Lei YU8a454c52020-09-23 16:52:46 +080042 uint8_t rwFlag;
43 uint8_t deviceType;
44 uint8_t infoType;
45 uint8_t maskAllPresentLen;
46 std::vector<uint8_t> enableStatus;
47 std::vector<uint8_t> maskPresent;
48 std::vector<uint8_t> maskAllPresent;
49 uint8_t allInfoDone;
50 uint16_t totalMessageLen;
51 std::vector<uint8_t> data;
52};
53
54void dumpAssetInfo(const ParsedAssetInfo& info)
55{
Lei YU6505e9d2020-09-21 17:34:32 +080056 fprintf(stderr,
Lei YU8a454c52020-09-23 16:52:46 +080057 "AssetInfo: rw %d, deviceType 0x%02x, infoType 0x%02x, "
58 "maskAllPresentLen %u\n",
59 info.rwFlag, info.deviceType, info.infoType,
60 info.maskAllPresentLen);
61 fprintf(stderr, "enableStatus ");
62 for (const auto& d : info.enableStatus)
63 {
64 fprintf(stderr, "0x%02x ", d);
65 }
66 fprintf(stderr, "\nmaskPresent ");
67 for (const auto& d : info.maskPresent)
68 {
69 fprintf(stderr, "0x%02x ", d);
70 }
71 fprintf(stderr, "\nmaskAllPresent ");
72 for (const auto& d : info.maskAllPresent)
73 {
74 fprintf(stderr, "0x%02x ", d);
75 }
76 fprintf(stderr, "\nallInfoDone %d, totalMessageLen %u\n", info.allInfoDone,
77 info.totalMessageLen);
78 fprintf(stderr, "data: ");
79 for (const auto& d : info.data)
80 {
81 fprintf(stderr, "0x%02x ", d);
82 }
83 fprintf(stderr, "\n");
84}
85
86std::optional<ParsedAssetInfo> parseAssetInfo(const AssetInfoHeader* h)
87{
88 auto len = h->maskAllPresentLen;
89 if (len == 0)
90 {
91 // This is invalid
92 return {};
93 }
94
95 ParsedAssetInfo info;
96 info.rwFlag = h->rwFlag;
97 info.deviceType = h->deviceType;
98 info.infoType = h->infoType;
99 info.maskAllPresentLen = len;
100 info.enableStatus.resize(len);
101 info.maskPresent.resize(len);
102 info.maskAllPresent.resize(len);
103 const uint8_t* p = &h->enableStatus;
104 memcpy(info.enableStatus.data(), p, len);
105 p += len;
106 memcpy(info.maskPresent.data(), p, len);
107 p += len;
108 memcpy(info.maskAllPresent.data(), p, len);
109 p += len;
110 info.allInfoDone = *p++;
111 info.totalMessageLen = *reinterpret_cast<const uint16_t*>(p);
112 p += sizeof(uint16_t);
113 auto dataLen = info.totalMessageLen - (sizeof(AssetInfoHeader) + 3 * len);
114 info.data.resize(dataLen);
115 memcpy(info.data.data(), p, dataLen);
116
Lei YU17bc93d2020-09-23 19:55:07 +0800117 // dumpAssetInfo(info);
Lei YU8a454c52020-09-23 16:52:46 +0800118 return info;
119}
120
Lei YU17bc93d2020-09-23 19:55:07 +0800121void parseBIOSInfo(const std::vector<uint8_t>& data)
122{
Lei YUebd3d092020-09-27 18:11:48 +0800123 if (data.size() < FIRMWARE_MIN_SIZE)
124 {
125 return;
126 }
Lei YU17bc93d2020-09-23 19:55:07 +0800127 bios_version_devname dev = static_cast<bios_version_devname>(data[0]);
128 std::string version{data.data() + FIRMWARE_VERSION_OFFSET,
129 data.data() + FIRMWARE_VERSION_SIZE};
130 std::string buildTime;
131 if (dev == bios_version_devname::BIOS)
132 {
133 buildTime.assign(reinterpret_cast<const char*>(
134 data.data() + FIRMWARE_BUILDTIME_OFFSET),
135 FIRMWARE_BUILDTIME_SIZE);
Lei YU3c341df2020-09-27 13:24:53 +0800136
137 // Set BIOS version
138 auto service = utils::getService(bus, BIOS_OBJPATH, VERSION_IFACE);
139 utils::setProperty(bus, service.c_str(), BIOS_OBJPATH, VERSION_IFACE,
140 VERSION, version);
Lei YU17bc93d2020-09-23 19:55:07 +0800141 }
142
143 printf("Dev %s, version %s, build time %s\n",
144 bios_devname[static_cast<int>(dev)].data(), version.c_str(),
145 buildTime.c_str());
146}
147
George Liua3a9d2a2024-04-03 09:30:45 +0800148ipmi_ret_t ipmiOemIEIAssetInfo(ipmi_netfn_t /* netfn */, ipmi_cmd_t /* cmd */,
149 ipmi_request_t request, ipmi_response_t response,
150 ipmi_data_len_t /* data_len */,
151 ipmi_context_t /* context */)
Lei YU8a454c52020-09-23 16:52:46 +0800152{
153 auto header = reinterpret_cast<AssetInfoHeader*>(request);
154 uint8_t* res = reinterpret_cast<uint8_t*>(response);
155 UNUSED(res);
156
157 auto info = parseAssetInfo(header);
158 auto deviceType = info->deviceType;
159 if (deviceType != 0x05)
160 {
George Liu666f96a2024-06-03 19:41:40 +0800161 lg2::info("Device type ({DEVICE_TYPE}) not supported yet",
162 "DEVICE_TYPE", deviceType);
Lei YU8a454c52020-09-23 16:52:46 +0800163 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