blob: 194583fb126876a0d55078120a5a20c760d346e0 [file] [log] [blame]
Gilbert Chen6c7fed42022-02-22 15:40:17 +00001#include "terminus.hpp"
2
3#include "libpldm/platform.h"
4
5#include "terminus_manager.hpp"
6
Gilbert Chende2a1322022-05-24 15:35:21 +01007#include <ranges>
8
Gilbert Chen6c7fed42022-02-22 15:40:17 +00009namespace pldm
10{
11namespace platform_mc
12{
13
14Terminus::Terminus(pldm_tid_t tid, uint64_t supportedTypes) :
15 initialized(false), tid(tid), supportedTypes(supportedTypes)
16{}
17
18bool Terminus::doesSupportType(uint8_t type)
19{
20 return supportedTypes.test(type);
21}
22
23bool Terminus::doesSupportCommand(uint8_t type, uint8_t command)
24{
25 if (!doesSupportType(type))
26 {
27 return false;
28 }
29
30 try
31 {
32 const size_t idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (command / 8);
33 if (idx >= supportedCmds.size())
34 {
35 return false;
36 }
37
38 if (supportedCmds[idx] & (1 << (command % 8)))
39 {
40 lg2::info(
41 "PLDM type {TYPE} command {CMD} is supported by terminus {TID}",
42 "TYPE", type, "CMD", command, "TID", getTid());
43 return true;
44 }
45 }
46 catch (const std::exception& e)
47 {
48 return false;
49 }
50
51 return false;
52}
53
Gilbert Chende2a1322022-05-24 15:35:21 +010054void Terminus::parseTerminusPDRs()
55{
56 std::vector<std::shared_ptr<pldm_numeric_sensor_value_pdr>>
57 numericSensorPdrs{};
58 std::vector<std::shared_ptr<pldm_compact_numeric_sensor_pdr>>
59 compactNumericSensorPdrs{};
60
61 for (auto& pdr : pdrs)
62 {
63 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
64 switch (pdrHdr->type)
65 {
66 case PLDM_SENSOR_AUXILIARY_NAMES_PDR:
67 {
68 auto sensorAuxNames = parseSensorAuxiliaryNamesPDR(pdr);
69 if (!sensorAuxNames)
70 {
71 lg2::error(
72 "Failed to parse PDR with type {TYPE} handle {HANDLE}",
73 "TYPE", pdrHdr->type, "HANDLE",
74 static_cast<uint32_t>(pdrHdr->record_handle));
75 continue;
76 }
77 sensorAuxiliaryNamesTbl.emplace_back(std::move(sensorAuxNames));
78 break;
79 }
80 case PLDM_NUMERIC_SENSOR_PDR:
81 {
82 auto parsedPdr = parseNumericSensorPDR(pdr);
83 if (!parsedPdr)
84 {
85 lg2::error(
86 "Failed to parse PDR with type {TYPE} handle {HANDLE}",
87 "TYPE", pdrHdr->type, "HANDLE",
88 static_cast<uint32_t>(pdrHdr->record_handle));
89 continue;
90 }
91 numericSensorPdrs.emplace_back(std::move(parsedPdr));
92 break;
93 }
94 case PLDM_COMPACT_NUMERIC_SENSOR_PDR:
95 {
96 auto parsedPdr = parseCompactNumericSensorPDR(pdr);
97 if (!parsedPdr)
98 {
99 lg2::error(
100 "Failed to parse PDR with type {TYPE} handle {HANDLE}",
101 "TYPE", pdrHdr->type, "HANDLE",
102 static_cast<uint32_t>(pdrHdr->record_handle));
103 continue;
104 }
105 auto sensorAuxNames = parseCompactNumericSensorNames(pdr);
106 if (!sensorAuxNames)
107 {
108 lg2::error(
109 "Failed to parse sensor name PDR with type {TYPE} handle {HANDLE}",
110 "TYPE", pdrHdr->type, "HANDLE",
111 static_cast<uint32_t>(pdrHdr->record_handle));
112 continue;
113 }
114 compactNumericSensorPdrs.emplace_back(std::move(parsedPdr));
115 sensorAuxiliaryNamesTbl.emplace_back(std::move(sensorAuxNames));
116 break;
117 }
118 default:
119 {
120 lg2::error("Unsupported PDR with type {TYPE} handle {HANDLE}",
121 "TYPE", pdrHdr->type, "HANDLE",
122 static_cast<uint32_t>(pdrHdr->record_handle));
123 break;
124 }
125 }
126 }
127}
128
129std::shared_ptr<SensorAuxiliaryNames>
130 Terminus::getSensorAuxiliaryNames(SensorId id)
131{
132 auto it = std::find_if(
133 sensorAuxiliaryNamesTbl.begin(), sensorAuxiliaryNamesTbl.end(),
134 [id](
135 const std::shared_ptr<SensorAuxiliaryNames>& sensorAuxiliaryNames) {
136 const auto& [sensorId, sensorCnt, sensorNames] = *sensorAuxiliaryNames;
137 return sensorId == id;
138 });
139
140 if (it != sensorAuxiliaryNamesTbl.end())
141 {
142 return *it;
143 }
144 return nullptr;
145};
146
147std::shared_ptr<SensorAuxiliaryNames>
148 Terminus::parseSensorAuxiliaryNamesPDR(const std::vector<uint8_t>& pdrData)
149{
150 constexpr uint8_t nullTerminator = 0;
151 auto pdr = reinterpret_cast<const struct pldm_sensor_auxiliary_names_pdr*>(
152 pdrData.data());
153 const uint8_t* ptr = pdr->names;
154 std::vector<std::vector<std::pair<NameLanguageTag, SensorName>>>
155 sensorAuxNames{};
156 char16_t alignedBuffer[PLDM_STR_UTF_16_MAX_LEN];
157 for ([[maybe_unused]] const auto& sensor :
158 std::views::iota(0, static_cast<int>(pdr->sensor_count)))
159 {
160 const uint8_t nameStringCount = static_cast<uint8_t>(*ptr);
161 ptr += sizeof(uint8_t);
162 std::vector<std::pair<NameLanguageTag, SensorName>> nameStrings{};
163 for ([[maybe_unused]] const auto& count :
164 std::views::iota(0, static_cast<int>(nameStringCount)))
165 {
166 std::string_view nameLanguageTag(
167 reinterpret_cast<const char*>(ptr));
168 ptr += nameLanguageTag.size() + sizeof(nullTerminator);
169
170 int u16NameStringLen = 0;
171 for (int i = 0; ptr[i] != 0 || ptr[i + 1] != 0; i += 2)
172 {
173 u16NameStringLen++;
174 }
175 /* include terminator */
176 u16NameStringLen++;
177
178 std::fill(std::begin(alignedBuffer), std::end(alignedBuffer), 0);
179 if (u16NameStringLen > PLDM_STR_UTF_16_MAX_LEN)
180 {
181 lg2::error("Sensor name to long.");
182 return nullptr;
183 }
184 memcpy(alignedBuffer, ptr, u16NameStringLen * sizeof(uint16_t));
185 std::u16string u16NameString(alignedBuffer, u16NameStringLen);
186 ptr += (u16NameString.size() + sizeof(nullTerminator)) *
187 sizeof(uint16_t);
188 std::transform(u16NameString.cbegin(), u16NameString.cend(),
189 u16NameString.begin(),
190 [](uint16_t utf16) { return be16toh(utf16); });
191 std::string nameString =
192 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
193 char16_t>{}
194 .to_bytes(u16NameString);
195 std::replace(nameString.begin(), nameString.end(), ' ', '_');
196 auto nullTerminatorPos = nameString.find('\0');
197 if (nullTerminatorPos != std::string::npos)
198 {
199 nameString.erase(nullTerminatorPos);
200 }
201 nameStrings.emplace_back(
202 std::make_pair(nameLanguageTag, nameString));
203 }
204 sensorAuxNames.emplace_back(std::move(nameStrings));
205 }
206 return std::make_shared<SensorAuxiliaryNames>(
207 pdr->sensor_id, pdr->sensor_count, std::move(sensorAuxNames));
208}
209
210std::shared_ptr<pldm_numeric_sensor_value_pdr>
211 Terminus::parseNumericSensorPDR(const std::vector<uint8_t>& pdr)
212{
213 const uint8_t* ptr = pdr.data();
214 auto parsedPdr = std::make_shared<pldm_numeric_sensor_value_pdr>();
215 auto rc = decode_numeric_sensor_pdr_data(ptr, pdr.size(), parsedPdr.get());
216 if (rc)
217 {
218 return nullptr;
219 }
220 return parsedPdr;
221}
222
223std::shared_ptr<SensorAuxiliaryNames>
224 Terminus::parseCompactNumericSensorNames(const std::vector<uint8_t>& sPdr)
225{
226 std::vector<std::vector<std::pair<NameLanguageTag, SensorName>>>
227 sensorAuxNames{};
228 std::vector<std::pair<NameLanguageTag, SensorName>> nameStrings{};
229 auto pdr =
230 reinterpret_cast<const pldm_compact_numeric_sensor_pdr*>(sPdr.data());
231
232 if (sPdr.size() <
233 (sizeof(pldm_compact_numeric_sensor_pdr) - sizeof(uint8_t)))
234 {
235 return nullptr;
236 }
237
238 if (!pdr->sensor_name_length ||
239 (sPdr.size() < (sizeof(pldm_compact_numeric_sensor_pdr) -
240 sizeof(uint8_t) + pdr->sensor_name_length)))
241 {
242 return nullptr;
243 }
244
245 std::string nameString(reinterpret_cast<const char*>(pdr->sensor_name),
246 pdr->sensor_name_length);
247 std::replace(nameString.begin(), nameString.end(), ' ', '_');
248 auto nullTerminatorPos = nameString.find('\0');
249 if (nullTerminatorPos != std::string::npos)
250 {
251 nameString.erase(nullTerminatorPos);
252 }
253 nameStrings.emplace_back(std::make_pair("en", nameString));
254 sensorAuxNames.emplace_back(std::move(nameStrings));
255
256 return std::make_shared<SensorAuxiliaryNames>(pdr->sensor_id, 1,
257 std::move(sensorAuxNames));
258}
259
260std::shared_ptr<pldm_compact_numeric_sensor_pdr>
261 Terminus::parseCompactNumericSensorPDR(const std::vector<uint8_t>& sPdr)
262{
263 auto pdr =
264 reinterpret_cast<const pldm_compact_numeric_sensor_pdr*>(sPdr.data());
265 if (sPdr.size() < sizeof(pldm_compact_numeric_sensor_pdr))
266 {
267 // Handle error: input data too small to contain valid pdr
268 return nullptr;
269 }
270 auto parsedPdr = std::make_shared<pldm_compact_numeric_sensor_pdr>();
271
272 parsedPdr->hdr = pdr->hdr;
273 parsedPdr->terminus_handle = pdr->terminus_handle;
274 parsedPdr->sensor_id = pdr->sensor_id;
275 parsedPdr->entity_type = pdr->entity_type;
276 parsedPdr->entity_instance = pdr->entity_instance;
277 parsedPdr->container_id = pdr->container_id;
278 parsedPdr->sensor_name_length = pdr->sensor_name_length;
279 parsedPdr->base_unit = pdr->base_unit;
280 parsedPdr->unit_modifier = pdr->unit_modifier;
281 parsedPdr->occurrence_rate = pdr->occurrence_rate;
282 parsedPdr->range_field_support = pdr->range_field_support;
283 parsedPdr->warning_high = pdr->warning_high;
284 parsedPdr->warning_low = pdr->warning_low;
285 parsedPdr->critical_high = pdr->critical_high;
286 parsedPdr->critical_low = pdr->critical_low;
287 parsedPdr->fatal_high = pdr->fatal_high;
288 parsedPdr->fatal_low = pdr->fatal_low;
289 return parsedPdr;
290}
291
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000292} // namespace platform_mc
293} // namespace pldm