16c7fed4cSGilbert Chen #include "terminus.hpp"
26c7fed4cSGilbert Chen
3b6d3943dSDung Cao #include "dbus_impl_fru.hpp"
46c7fed4cSGilbert Chen #include "terminus_manager.hpp"
56c7fed4cSGilbert Chen
6*fe252795SManojkiran Eda #include <libpldm/platform.h>
7*fe252795SManojkiran Eda
8b8cf46b8SThu Nguyen #include <common/utils.hpp>
9b8cf46b8SThu Nguyen
10de2a132aSGilbert Chen #include <ranges>
11de2a132aSGilbert Chen
126c7fed4cSGilbert Chen namespace pldm
136c7fed4cSGilbert Chen {
146c7fed4cSGilbert Chen namespace platform_mc
156c7fed4cSGilbert Chen {
166c7fed4cSGilbert Chen
Terminus(pldm_tid_t tid,uint64_t supportedTypes,sdeventplus::Event & event)17fdf61cc3SChaul Ly Terminus::Terminus(pldm_tid_t tid, uint64_t supportedTypes,
18fdf61cc3SChaul Ly sdeventplus::Event& event) :
1977e6fe7aSGilbert Chen initialized(false), maxBufferSize(PLDM_PLATFORM_EVENT_MSG_MAX_BUFFER_SIZE),
20f48015b3SDung Cao synchronyConfigurationSupported(0), pollEvent(false), tid(tid),
21fdf61cc3SChaul Ly supportedTypes(supportedTypes), event(event)
226c7fed4cSGilbert Chen {}
236c7fed4cSGilbert Chen
doesSupportType(uint8_t type)246c7fed4cSGilbert Chen bool Terminus::doesSupportType(uint8_t type)
256c7fed4cSGilbert Chen {
266c7fed4cSGilbert Chen return supportedTypes.test(type);
276c7fed4cSGilbert Chen }
286c7fed4cSGilbert Chen
doesSupportCommand(uint8_t type,uint8_t command)296c7fed4cSGilbert Chen bool Terminus::doesSupportCommand(uint8_t type, uint8_t command)
306c7fed4cSGilbert Chen {
316c7fed4cSGilbert Chen if (!doesSupportType(type))
326c7fed4cSGilbert Chen {
336c7fed4cSGilbert Chen return false;
346c7fed4cSGilbert Chen }
356c7fed4cSGilbert Chen
366c7fed4cSGilbert Chen try
376c7fed4cSGilbert Chen {
386c7fed4cSGilbert Chen const size_t idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (command / 8);
396c7fed4cSGilbert Chen if (idx >= supportedCmds.size())
406c7fed4cSGilbert Chen {
416c7fed4cSGilbert Chen return false;
426c7fed4cSGilbert Chen }
436c7fed4cSGilbert Chen
446c7fed4cSGilbert Chen if (supportedCmds[idx] & (1 << (command % 8)))
456c7fed4cSGilbert Chen {
466c7fed4cSGilbert Chen lg2::info(
476c7fed4cSGilbert Chen "PLDM type {TYPE} command {CMD} is supported by terminus {TID}",
486c7fed4cSGilbert Chen "TYPE", type, "CMD", command, "TID", getTid());
496c7fed4cSGilbert Chen return true;
506c7fed4cSGilbert Chen }
516c7fed4cSGilbert Chen }
526c7fed4cSGilbert Chen catch (const std::exception& e)
536c7fed4cSGilbert Chen {
546c7fed4cSGilbert Chen return false;
556c7fed4cSGilbert Chen }
566c7fed4cSGilbert Chen
576c7fed4cSGilbert Chen return false;
586c7fed4cSGilbert Chen }
596c7fed4cSGilbert Chen
findTerminusName()60b8cf46b8SThu Nguyen std::optional<std::string_view> Terminus::findTerminusName()
61b8cf46b8SThu Nguyen {
62b8cf46b8SThu Nguyen auto it = std::find_if(
63b8cf46b8SThu Nguyen entityAuxiliaryNamesTbl.begin(), entityAuxiliaryNamesTbl.end(),
64b8cf46b8SThu Nguyen [](const std::shared_ptr<EntityAuxiliaryNames>& entityAuxiliaryNames) {
65b8cf46b8SThu Nguyen const auto& [key, entityNames] = *entityAuxiliaryNames;
66b8cf46b8SThu Nguyen /**
6704ac9971SManojkiran Eda * There is only one Overall system container entity in one
6804ac9971SManojkiran Eda * terminus. The entity auxiliary name PDR of that terminus with the
6904ac9971SManojkiran Eda * that type of containerID will include terminus name.
7004ac9971SManojkiran Eda */
7116c2a0a0SPatrick Williams return (
7216c2a0a0SPatrick Williams entityAuxiliaryNames &&
73b8cf46b8SThu Nguyen key.containerId == PLDM_PLATFORM_ENTITY_SYSTEM_CONTAINER_ID &&
74b8cf46b8SThu Nguyen entityNames.size());
75b8cf46b8SThu Nguyen });
76b8cf46b8SThu Nguyen
77b8cf46b8SThu Nguyen if (it != entityAuxiliaryNamesTbl.end())
78b8cf46b8SThu Nguyen {
79b8cf46b8SThu Nguyen const auto& [key, entityNames] = **it;
80b8cf46b8SThu Nguyen if (!entityNames.size())
81b8cf46b8SThu Nguyen {
82b8cf46b8SThu Nguyen return std::nullopt;
83b8cf46b8SThu Nguyen }
84b8cf46b8SThu Nguyen return entityNames[0].second;
85b8cf46b8SThu Nguyen }
86b8cf46b8SThu Nguyen
87b8cf46b8SThu Nguyen return std::nullopt;
88b8cf46b8SThu Nguyen }
89b8cf46b8SThu Nguyen
createInventoryPath(std::string tName)903c5486d4SThu Nguyen bool Terminus::createInventoryPath(std::string tName)
913c5486d4SThu Nguyen {
923c5486d4SThu Nguyen if (tName.empty())
933c5486d4SThu Nguyen {
943c5486d4SThu Nguyen return false;
953c5486d4SThu Nguyen }
963c5486d4SThu Nguyen
97b6d3943dSDung Cao /* inventory object is created */
98b6d3943dSDung Cao if (inventoryItemBoardInft)
99b6d3943dSDung Cao {
100b6d3943dSDung Cao return false;
101b6d3943dSDung Cao }
102b6d3943dSDung Cao
1033c5486d4SThu Nguyen inventoryPath = "/xyz/openbmc_project/inventory/system/board/" + tName;
1043c5486d4SThu Nguyen try
1053c5486d4SThu Nguyen {
106b6d3943dSDung Cao inventoryItemBoardInft =
107b6d3943dSDung Cao std::make_unique<pldm::dbus_api::PldmEntityReq>(
1083c5486d4SThu Nguyen utils::DBusHandler::getBus(), inventoryPath.c_str());
1093c5486d4SThu Nguyen return true;
1103c5486d4SThu Nguyen }
1113c5486d4SThu Nguyen catch (const sdbusplus::exception_t& e)
1123c5486d4SThu Nguyen {
1133c5486d4SThu Nguyen lg2::error(
1143c5486d4SThu Nguyen "Failed to create Inventory Board interface for device {PATH}",
1153c5486d4SThu Nguyen "PATH", inventoryPath);
1163c5486d4SThu Nguyen }
1173c5486d4SThu Nguyen
1183c5486d4SThu Nguyen return false;
1193c5486d4SThu Nguyen }
1203c5486d4SThu Nguyen
parseTerminusPDRs()121de2a132aSGilbert Chen void Terminus::parseTerminusPDRs()
122de2a132aSGilbert Chen {
123de2a132aSGilbert Chen for (auto& pdr : pdrs)
124de2a132aSGilbert Chen {
12536b36938SPavithra Barithaya auto pdrHdr = new (pdr.data()) pldm_pdr_hdr;
126de2a132aSGilbert Chen switch (pdrHdr->type)
127de2a132aSGilbert Chen {
128de2a132aSGilbert Chen case PLDM_SENSOR_AUXILIARY_NAMES_PDR:
129de2a132aSGilbert Chen {
130de2a132aSGilbert Chen auto sensorAuxNames = parseSensorAuxiliaryNamesPDR(pdr);
131de2a132aSGilbert Chen if (!sensorAuxNames)
132de2a132aSGilbert Chen {
133de2a132aSGilbert Chen lg2::error(
134de2a132aSGilbert Chen "Failed to parse PDR with type {TYPE} handle {HANDLE}",
135de2a132aSGilbert Chen "TYPE", pdrHdr->type, "HANDLE",
136de2a132aSGilbert Chen static_cast<uint32_t>(pdrHdr->record_handle));
137de2a132aSGilbert Chen continue;
138de2a132aSGilbert Chen }
139de2a132aSGilbert Chen sensorAuxiliaryNamesTbl.emplace_back(std::move(sensorAuxNames));
140de2a132aSGilbert Chen break;
141de2a132aSGilbert Chen }
142de2a132aSGilbert Chen case PLDM_NUMERIC_SENSOR_PDR:
143de2a132aSGilbert Chen {
144de2a132aSGilbert Chen auto parsedPdr = parseNumericSensorPDR(pdr);
145de2a132aSGilbert Chen if (!parsedPdr)
146de2a132aSGilbert Chen {
147de2a132aSGilbert Chen lg2::error(
148de2a132aSGilbert Chen "Failed to parse PDR with type {TYPE} handle {HANDLE}",
149de2a132aSGilbert Chen "TYPE", pdrHdr->type, "HANDLE",
150de2a132aSGilbert Chen static_cast<uint32_t>(pdrHdr->record_handle));
151de2a132aSGilbert Chen continue;
152de2a132aSGilbert Chen }
153de2a132aSGilbert Chen numericSensorPdrs.emplace_back(std::move(parsedPdr));
154de2a132aSGilbert Chen break;
155de2a132aSGilbert Chen }
156de2a132aSGilbert Chen case PLDM_COMPACT_NUMERIC_SENSOR_PDR:
157de2a132aSGilbert Chen {
158de2a132aSGilbert Chen auto parsedPdr = parseCompactNumericSensorPDR(pdr);
159de2a132aSGilbert Chen if (!parsedPdr)
160de2a132aSGilbert Chen {
161de2a132aSGilbert Chen lg2::error(
162de2a132aSGilbert Chen "Failed to parse PDR with type {TYPE} handle {HANDLE}",
163de2a132aSGilbert Chen "TYPE", pdrHdr->type, "HANDLE",
164de2a132aSGilbert Chen static_cast<uint32_t>(pdrHdr->record_handle));
165de2a132aSGilbert Chen continue;
166de2a132aSGilbert Chen }
167de2a132aSGilbert Chen auto sensorAuxNames = parseCompactNumericSensorNames(pdr);
168de2a132aSGilbert Chen if (!sensorAuxNames)
169de2a132aSGilbert Chen {
170de2a132aSGilbert Chen lg2::error(
171de2a132aSGilbert Chen "Failed to parse sensor name PDR with type {TYPE} handle {HANDLE}",
172de2a132aSGilbert Chen "TYPE", pdrHdr->type, "HANDLE",
173de2a132aSGilbert Chen static_cast<uint32_t>(pdrHdr->record_handle));
174de2a132aSGilbert Chen continue;
175de2a132aSGilbert Chen }
176de2a132aSGilbert Chen compactNumericSensorPdrs.emplace_back(std::move(parsedPdr));
177de2a132aSGilbert Chen sensorAuxiliaryNamesTbl.emplace_back(std::move(sensorAuxNames));
178de2a132aSGilbert Chen break;
179de2a132aSGilbert Chen }
180b8cf46b8SThu Nguyen case PLDM_ENTITY_AUXILIARY_NAMES_PDR:
181b8cf46b8SThu Nguyen {
182b8cf46b8SThu Nguyen auto entityNames = parseEntityAuxiliaryNamesPDR(pdr);
183b8cf46b8SThu Nguyen if (!entityNames)
184b8cf46b8SThu Nguyen {
185b8cf46b8SThu Nguyen lg2::error(
186b8cf46b8SThu Nguyen "Failed to parse sensor name PDR with type {TYPE} handle {HANDLE}",
187b8cf46b8SThu Nguyen "TYPE", pdrHdr->type, "HANDLE",
188b8cf46b8SThu Nguyen static_cast<uint32_t>(pdrHdr->record_handle));
189b8cf46b8SThu Nguyen continue;
190b8cf46b8SThu Nguyen }
191b8cf46b8SThu Nguyen entityAuxiliaryNamesTbl.emplace_back(std::move(entityNames));
192b8cf46b8SThu Nguyen break;
193b8cf46b8SThu Nguyen }
194de2a132aSGilbert Chen default:
195de2a132aSGilbert Chen {
196de2a132aSGilbert Chen lg2::error("Unsupported PDR with type {TYPE} handle {HANDLE}",
197de2a132aSGilbert Chen "TYPE", pdrHdr->type, "HANDLE",
198de2a132aSGilbert Chen static_cast<uint32_t>(pdrHdr->record_handle));
199de2a132aSGilbert Chen break;
200de2a132aSGilbert Chen }
201de2a132aSGilbert Chen }
202de2a132aSGilbert Chen }
203b8cf46b8SThu Nguyen
204b8cf46b8SThu Nguyen auto tName = findTerminusName();
205b8cf46b8SThu Nguyen if (tName && !tName.value().empty())
206b8cf46b8SThu Nguyen {
207b8cf46b8SThu Nguyen lg2::info("Terminus {TID} has Auxiliary Name {NAME}.", "TID", tid,
208b8cf46b8SThu Nguyen "NAME", tName.value());
209b8cf46b8SThu Nguyen terminusName = static_cast<std::string>(tName.value());
210b8cf46b8SThu Nguyen }
2113c5486d4SThu Nguyen
2123c5486d4SThu Nguyen if (terminusName.empty() &&
2133c5486d4SThu Nguyen (numericSensorPdrs.size() || compactNumericSensorPdrs.size()))
2143c5486d4SThu Nguyen {
2153c5486d4SThu Nguyen lg2::error(
2163c5486d4SThu Nguyen "Terminus ID {TID}: DOES NOT have name. Skip Adding sensors.",
2173c5486d4SThu Nguyen "TID", tid);
2183c5486d4SThu Nguyen return;
2193c5486d4SThu Nguyen }
2203c5486d4SThu Nguyen
2213c5486d4SThu Nguyen if (createInventoryPath(terminusName))
2223c5486d4SThu Nguyen {
223b6d3943dSDung Cao lg2::error("Terminus ID {TID}: Created Inventory path {PATH}.", "TID",
224b6d3943dSDung Cao tid, "PATH", inventoryPath);
2253c5486d4SThu Nguyen }
2263c5486d4SThu Nguyen
227fdf61cc3SChaul Ly addNextSensorFromPDRs();
2283c5486d4SThu Nguyen }
2293c5486d4SThu Nguyen
addNextSensorFromPDRs()230fdf61cc3SChaul Ly void Terminus::addNextSensorFromPDRs()
2313c5486d4SThu Nguyen {
232fdf61cc3SChaul Ly sensorCreationEvent.reset();
233fdf61cc3SChaul Ly
234fdf61cc3SChaul Ly if (terminusName.empty())
235fdf61cc3SChaul Ly {
236fdf61cc3SChaul Ly lg2::error(
237fdf61cc3SChaul Ly "Terminus ID {TID}: DOES NOT have name. Skip Adding sensors.",
238fdf61cc3SChaul Ly "TID", tid);
239fdf61cc3SChaul Ly return;
2403c5486d4SThu Nguyen }
241fdf61cc3SChaul Ly
242fdf61cc3SChaul Ly auto pdrIt = sensorPdrIt;
243fdf61cc3SChaul Ly
244fdf61cc3SChaul Ly if (pdrIt < numericSensorPdrs.size())
245fdf61cc3SChaul Ly {
246fdf61cc3SChaul Ly const auto& pdr = numericSensorPdrs[pdrIt];
247fdf61cc3SChaul Ly // Defer adding the next Numeric Sensor
248fdf61cc3SChaul Ly sensorCreationEvent = std::make_unique<sdeventplus::source::Defer>(
249fdf61cc3SChaul Ly event,
250fdf61cc3SChaul Ly std::bind(std::mem_fn(&Terminus::addNumericSensor), this, pdr));
251fdf61cc3SChaul Ly }
252fdf61cc3SChaul Ly else if (pdrIt < numericSensorPdrs.size() + compactNumericSensorPdrs.size())
253fdf61cc3SChaul Ly {
254fdf61cc3SChaul Ly pdrIt -= numericSensorPdrs.size();
255fdf61cc3SChaul Ly const auto& pdr = compactNumericSensorPdrs[pdrIt];
256fdf61cc3SChaul Ly // Defer adding the next Compact Numeric Sensor
257fdf61cc3SChaul Ly sensorCreationEvent = std::make_unique<sdeventplus::source::Defer>(
258fdf61cc3SChaul Ly event, std::bind(std::mem_fn(&Terminus::addCompactNumericSensor),
259fdf61cc3SChaul Ly this, pdr));
260fdf61cc3SChaul Ly }
261fdf61cc3SChaul Ly else
262fdf61cc3SChaul Ly {
263fdf61cc3SChaul Ly sensorPdrIt = 0;
264fdf61cc3SChaul Ly return;
265fdf61cc3SChaul Ly }
266fdf61cc3SChaul Ly
267fdf61cc3SChaul Ly // Move the iteration to the next sensor PDR
268fdf61cc3SChaul Ly sensorPdrIt++;
269de2a132aSGilbert Chen }
270de2a132aSGilbert Chen
getSensorAuxiliaryNames(SensorId id)271366507c8SPatrick Williams std::shared_ptr<SensorAuxiliaryNames> Terminus::getSensorAuxiliaryNames(
272366507c8SPatrick Williams SensorId id)
273de2a132aSGilbert Chen {
274de2a132aSGilbert Chen auto it = std::find_if(
275de2a132aSGilbert Chen sensorAuxiliaryNamesTbl.begin(), sensorAuxiliaryNamesTbl.end(),
276de2a132aSGilbert Chen [id](
277de2a132aSGilbert Chen const std::shared_ptr<SensorAuxiliaryNames>& sensorAuxiliaryNames) {
27816c2a0a0SPatrick Williams const auto& [sensorId, sensorCnt, sensorNames] =
27916c2a0a0SPatrick Williams *sensorAuxiliaryNames;
280de2a132aSGilbert Chen return sensorId == id;
281de2a132aSGilbert Chen });
282de2a132aSGilbert Chen
283de2a132aSGilbert Chen if (it != sensorAuxiliaryNamesTbl.end())
284de2a132aSGilbert Chen {
285de2a132aSGilbert Chen return *it;
286de2a132aSGilbert Chen }
287de2a132aSGilbert Chen return nullptr;
288de2a132aSGilbert Chen };
289de2a132aSGilbert Chen
parseSensorAuxiliaryNamesPDR(const std::vector<uint8_t> & pdrData)290366507c8SPatrick Williams std::shared_ptr<SensorAuxiliaryNames> Terminus::parseSensorAuxiliaryNamesPDR(
291366507c8SPatrick Williams const std::vector<uint8_t>& pdrData)
292de2a132aSGilbert Chen {
293de2a132aSGilbert Chen constexpr uint8_t nullTerminator = 0;
294de2a132aSGilbert Chen auto pdr = reinterpret_cast<const struct pldm_sensor_auxiliary_names_pdr*>(
295de2a132aSGilbert Chen pdrData.data());
296de2a132aSGilbert Chen const uint8_t* ptr = pdr->names;
297b8cf46b8SThu Nguyen std::vector<AuxiliaryNames> sensorAuxNames{};
298de2a132aSGilbert Chen char16_t alignedBuffer[PLDM_STR_UTF_16_MAX_LEN];
299de2a132aSGilbert Chen for ([[maybe_unused]] const auto& sensor :
300de2a132aSGilbert Chen std::views::iota(0, static_cast<int>(pdr->sensor_count)))
301de2a132aSGilbert Chen {
302de2a132aSGilbert Chen const uint8_t nameStringCount = static_cast<uint8_t>(*ptr);
303de2a132aSGilbert Chen ptr += sizeof(uint8_t);
304b8cf46b8SThu Nguyen AuxiliaryNames nameStrings{};
305de2a132aSGilbert Chen for ([[maybe_unused]] const auto& count :
306de2a132aSGilbert Chen std::views::iota(0, static_cast<int>(nameStringCount)))
307de2a132aSGilbert Chen {
308de2a132aSGilbert Chen std::string_view nameLanguageTag(
309de2a132aSGilbert Chen reinterpret_cast<const char*>(ptr));
310de2a132aSGilbert Chen ptr += nameLanguageTag.size() + sizeof(nullTerminator);
311de2a132aSGilbert Chen
312de2a132aSGilbert Chen int u16NameStringLen = 0;
313de2a132aSGilbert Chen for (int i = 0; ptr[i] != 0 || ptr[i + 1] != 0; i += 2)
314de2a132aSGilbert Chen {
315de2a132aSGilbert Chen u16NameStringLen++;
316de2a132aSGilbert Chen }
317de2a132aSGilbert Chen /* include terminator */
318de2a132aSGilbert Chen u16NameStringLen++;
319de2a132aSGilbert Chen
320de2a132aSGilbert Chen std::fill(std::begin(alignedBuffer), std::end(alignedBuffer), 0);
321de2a132aSGilbert Chen if (u16NameStringLen > PLDM_STR_UTF_16_MAX_LEN)
322de2a132aSGilbert Chen {
32338a09d25SChau Ly lg2::error("Sensor name too long.");
324de2a132aSGilbert Chen return nullptr;
325de2a132aSGilbert Chen }
326de2a132aSGilbert Chen memcpy(alignedBuffer, ptr, u16NameStringLen * sizeof(uint16_t));
327de2a132aSGilbert Chen std::u16string u16NameString(alignedBuffer, u16NameStringLen);
328f1e32c17Stal-yac ptr += u16NameString.size() * sizeof(uint16_t);
329de2a132aSGilbert Chen std::transform(u16NameString.cbegin(), u16NameString.cend(),
330de2a132aSGilbert Chen u16NameString.begin(),
331de2a132aSGilbert Chen [](uint16_t utf16) { return be16toh(utf16); });
332de2a132aSGilbert Chen std::string nameString =
333de2a132aSGilbert Chen std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
334de2a132aSGilbert Chen char16_t>{}
335de2a132aSGilbert Chen .to_bytes(u16NameString);
336b8cf46b8SThu Nguyen nameStrings.emplace_back(std::make_pair(
337b8cf46b8SThu Nguyen nameLanguageTag, pldm::utils::trimNameForDbus(nameString)));
338de2a132aSGilbert Chen }
339de2a132aSGilbert Chen sensorAuxNames.emplace_back(std::move(nameStrings));
340de2a132aSGilbert Chen }
341de2a132aSGilbert Chen return std::make_shared<SensorAuxiliaryNames>(
342de2a132aSGilbert Chen pdr->sensor_id, pdr->sensor_count, std::move(sensorAuxNames));
343de2a132aSGilbert Chen }
344de2a132aSGilbert Chen
parseEntityAuxiliaryNamesPDR(const std::vector<uint8_t> & pdrData)345366507c8SPatrick Williams std::shared_ptr<EntityAuxiliaryNames> Terminus::parseEntityAuxiliaryNamesPDR(
346366507c8SPatrick Williams const std::vector<uint8_t>& pdrData)
347b8cf46b8SThu Nguyen {
348b8cf46b8SThu Nguyen auto names_offset = sizeof(struct pldm_pdr_hdr) +
349b8cf46b8SThu Nguyen PLDM_PDR_ENTITY_AUXILIARY_NAME_PDR_MIN_LENGTH;
350b8cf46b8SThu Nguyen auto names_size = pdrData.size() - names_offset;
351b8cf46b8SThu Nguyen
35216c2a0a0SPatrick Williams size_t decodedPdrSize =
35316c2a0a0SPatrick Williams sizeof(struct pldm_entity_auxiliary_names_pdr) + names_size;
354b8cf46b8SThu Nguyen auto vPdr = std::vector<char>(decodedPdrSize);
35536b36938SPavithra Barithaya auto decodedPdr = new (vPdr.data()) pldm_entity_auxiliary_names_pdr;
356b8cf46b8SThu Nguyen
357b8cf46b8SThu Nguyen auto rc = decode_entity_auxiliary_names_pdr(pdrData.data(), pdrData.size(),
358b8cf46b8SThu Nguyen decodedPdr, decodedPdrSize);
359b8cf46b8SThu Nguyen
360b8cf46b8SThu Nguyen if (rc)
361b8cf46b8SThu Nguyen {
362b8cf46b8SThu Nguyen lg2::error(
363b8cf46b8SThu Nguyen "Failed to decode Entity Auxiliary Name PDR data, error {RC}.",
364b8cf46b8SThu Nguyen "RC", rc);
365b8cf46b8SThu Nguyen return nullptr;
366b8cf46b8SThu Nguyen }
367b8cf46b8SThu Nguyen
368b8cf46b8SThu Nguyen auto vNames =
369b8cf46b8SThu Nguyen std::vector<pldm_entity_auxiliary_name>(decodedPdr->name_string_count);
370b8cf46b8SThu Nguyen decodedPdr->names = vNames.data();
371b8cf46b8SThu Nguyen
372b8cf46b8SThu Nguyen rc = decode_pldm_entity_auxiliary_names_pdr_index(decodedPdr);
373b8cf46b8SThu Nguyen if (rc)
374b8cf46b8SThu Nguyen {
375b8cf46b8SThu Nguyen lg2::error("Failed to decode Entity Auxiliary Name, error {RC}.", "RC",
376b8cf46b8SThu Nguyen rc);
377b8cf46b8SThu Nguyen return nullptr;
378b8cf46b8SThu Nguyen }
379b8cf46b8SThu Nguyen
380b8cf46b8SThu Nguyen AuxiliaryNames nameStrings{};
381b8cf46b8SThu Nguyen for (const auto& count :
382b8cf46b8SThu Nguyen std::views::iota(0, static_cast<int>(decodedPdr->name_string_count)))
383b8cf46b8SThu Nguyen {
384b8cf46b8SThu Nguyen std::string_view nameLanguageTag =
385b8cf46b8SThu Nguyen static_cast<std::string_view>(decodedPdr->names[count].tag);
386b8cf46b8SThu Nguyen const size_t u16NameStringLen =
387b8cf46b8SThu Nguyen std::char_traits<char16_t>::length(decodedPdr->names[count].name);
388b8cf46b8SThu Nguyen std::u16string u16NameString(decodedPdr->names[count].name,
389b8cf46b8SThu Nguyen u16NameStringLen);
390b8cf46b8SThu Nguyen std::transform(u16NameString.cbegin(), u16NameString.cend(),
391b8cf46b8SThu Nguyen u16NameString.begin(),
392b8cf46b8SThu Nguyen [](uint16_t utf16) { return be16toh(utf16); });
393b8cf46b8SThu Nguyen std::string nameString =
394b8cf46b8SThu Nguyen std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}
395b8cf46b8SThu Nguyen .to_bytes(u16NameString);
396b8cf46b8SThu Nguyen nameStrings.emplace_back(std::make_pair(
397b8cf46b8SThu Nguyen nameLanguageTag, pldm::utils::trimNameForDbus(nameString)));
398b8cf46b8SThu Nguyen }
399b8cf46b8SThu Nguyen
400b8cf46b8SThu Nguyen EntityKey key{decodedPdr->container.entity_type,
401b8cf46b8SThu Nguyen decodedPdr->container.entity_instance_num,
402b8cf46b8SThu Nguyen decodedPdr->container.entity_container_id};
403b8cf46b8SThu Nguyen
404b8cf46b8SThu Nguyen return std::make_shared<EntityAuxiliaryNames>(key, nameStrings);
405b8cf46b8SThu Nguyen }
406b8cf46b8SThu Nguyen
parseNumericSensorPDR(const std::vector<uint8_t> & pdr)407366507c8SPatrick Williams std::shared_ptr<pldm_numeric_sensor_value_pdr> Terminus::parseNumericSensorPDR(
408366507c8SPatrick Williams const std::vector<uint8_t>& pdr)
409de2a132aSGilbert Chen {
410de2a132aSGilbert Chen const uint8_t* ptr = pdr.data();
411de2a132aSGilbert Chen auto parsedPdr = std::make_shared<pldm_numeric_sensor_value_pdr>();
412de2a132aSGilbert Chen auto rc = decode_numeric_sensor_pdr_data(ptr, pdr.size(), parsedPdr.get());
413de2a132aSGilbert Chen if (rc)
414de2a132aSGilbert Chen {
415de2a132aSGilbert Chen return nullptr;
416de2a132aSGilbert Chen }
417de2a132aSGilbert Chen return parsedPdr;
418de2a132aSGilbert Chen }
419de2a132aSGilbert Chen
addNumericSensor(const std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr)4203c5486d4SThu Nguyen void Terminus::addNumericSensor(
4213c5486d4SThu Nguyen const std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr)
4223c5486d4SThu Nguyen {
42338a09d25SChau Ly if (!pdr)
4243c5486d4SThu Nguyen {
42538a09d25SChau Ly lg2::error(
42638a09d25SChau Ly "Terminus ID {TID}: Skip adding Numeric Sensor - invalid pointer to PDR.",
42738a09d25SChau Ly "TID", tid);
428fdf61cc3SChaul Ly addNextSensorFromPDRs();
42938a09d25SChau Ly }
43038a09d25SChau Ly
43138a09d25SChau Ly auto sensorId = pdr->sensor_id;
43238a09d25SChau Ly auto sensorNames = getSensorNames(sensorId);
43338a09d25SChau Ly
43438a09d25SChau Ly if (sensorNames.empty())
4353c5486d4SThu Nguyen {
43638a09d25SChau Ly lg2::error(
43738a09d25SChau Ly "Terminus ID {TID}: Failed to get name for Numeric Sensor {SID}",
43838a09d25SChau Ly "TID", tid, "SID", sensorId);
439fdf61cc3SChaul Ly addNextSensorFromPDRs();
4403c5486d4SThu Nguyen }
44138a09d25SChau Ly
44238a09d25SChau Ly std::string sensorName = sensorNames.front();
4433c5486d4SThu Nguyen
4443c5486d4SThu Nguyen try
4453c5486d4SThu Nguyen {
4463c5486d4SThu Nguyen auto sensor = std::make_shared<NumericSensor>(
4473c5486d4SThu Nguyen tid, true, pdr, sensorName, inventoryPath);
4483c5486d4SThu Nguyen lg2::info("Created NumericSensor {NAME}", "NAME", sensorName);
4493c5486d4SThu Nguyen numericSensors.emplace_back(sensor);
4503c5486d4SThu Nguyen }
4513c5486d4SThu Nguyen catch (const sdbusplus::exception_t& e)
4523c5486d4SThu Nguyen {
4533c5486d4SThu Nguyen lg2::error(
4543c5486d4SThu Nguyen "Failed to create NumericSensor. error - {ERROR} sensorname - {NAME}",
4553c5486d4SThu Nguyen "ERROR", e, "NAME", sensorName);
4563c5486d4SThu Nguyen }
457fdf61cc3SChaul Ly
458fdf61cc3SChaul Ly addNextSensorFromPDRs();
4593c5486d4SThu Nguyen }
4603c5486d4SThu Nguyen
parseCompactNumericSensorNames(const std::vector<uint8_t> & sPdr)461366507c8SPatrick Williams std::shared_ptr<SensorAuxiliaryNames> Terminus::parseCompactNumericSensorNames(
462366507c8SPatrick Williams const std::vector<uint8_t>& sPdr)
463de2a132aSGilbert Chen {
464de2a132aSGilbert Chen std::vector<std::vector<std::pair<NameLanguageTag, SensorName>>>
465de2a132aSGilbert Chen sensorAuxNames{};
466b8cf46b8SThu Nguyen AuxiliaryNames nameStrings{};
46736b36938SPavithra Barithaya
468de2a132aSGilbert Chen auto pdr =
469de2a132aSGilbert Chen reinterpret_cast<const pldm_compact_numeric_sensor_pdr*>(sPdr.data());
470de2a132aSGilbert Chen
471de2a132aSGilbert Chen if (sPdr.size() <
472de2a132aSGilbert Chen (sizeof(pldm_compact_numeric_sensor_pdr) - sizeof(uint8_t)))
473de2a132aSGilbert Chen {
474de2a132aSGilbert Chen return nullptr;
475de2a132aSGilbert Chen }
476de2a132aSGilbert Chen
477de2a132aSGilbert Chen if (!pdr->sensor_name_length ||
478de2a132aSGilbert Chen (sPdr.size() < (sizeof(pldm_compact_numeric_sensor_pdr) -
479de2a132aSGilbert Chen sizeof(uint8_t) + pdr->sensor_name_length)))
480de2a132aSGilbert Chen {
481de2a132aSGilbert Chen return nullptr;
482de2a132aSGilbert Chen }
483de2a132aSGilbert Chen
484de2a132aSGilbert Chen std::string nameString(reinterpret_cast<const char*>(pdr->sensor_name),
485de2a132aSGilbert Chen pdr->sensor_name_length);
486b8cf46b8SThu Nguyen nameStrings.emplace_back(
487b8cf46b8SThu Nguyen std::make_pair("en", pldm::utils::trimNameForDbus(nameString)));
488de2a132aSGilbert Chen sensorAuxNames.emplace_back(std::move(nameStrings));
489de2a132aSGilbert Chen
490de2a132aSGilbert Chen return std::make_shared<SensorAuxiliaryNames>(pdr->sensor_id, 1,
491de2a132aSGilbert Chen std::move(sensorAuxNames));
492de2a132aSGilbert Chen }
493de2a132aSGilbert Chen
494de2a132aSGilbert Chen std::shared_ptr<pldm_compact_numeric_sensor_pdr>
parseCompactNumericSensorPDR(const std::vector<uint8_t> & sPdr)495de2a132aSGilbert Chen Terminus::parseCompactNumericSensorPDR(const std::vector<uint8_t>& sPdr)
496de2a132aSGilbert Chen {
497de2a132aSGilbert Chen auto pdr =
498de2a132aSGilbert Chen reinterpret_cast<const pldm_compact_numeric_sensor_pdr*>(sPdr.data());
499de2a132aSGilbert Chen if (sPdr.size() < sizeof(pldm_compact_numeric_sensor_pdr))
500de2a132aSGilbert Chen {
501de2a132aSGilbert Chen // Handle error: input data too small to contain valid pdr
502de2a132aSGilbert Chen return nullptr;
503de2a132aSGilbert Chen }
504de2a132aSGilbert Chen auto parsedPdr = std::make_shared<pldm_compact_numeric_sensor_pdr>();
505de2a132aSGilbert Chen
506de2a132aSGilbert Chen parsedPdr->hdr = pdr->hdr;
507de2a132aSGilbert Chen parsedPdr->terminus_handle = pdr->terminus_handle;
508de2a132aSGilbert Chen parsedPdr->sensor_id = pdr->sensor_id;
509de2a132aSGilbert Chen parsedPdr->entity_type = pdr->entity_type;
510de2a132aSGilbert Chen parsedPdr->entity_instance = pdr->entity_instance;
511de2a132aSGilbert Chen parsedPdr->container_id = pdr->container_id;
512de2a132aSGilbert Chen parsedPdr->sensor_name_length = pdr->sensor_name_length;
513de2a132aSGilbert Chen parsedPdr->base_unit = pdr->base_unit;
514de2a132aSGilbert Chen parsedPdr->unit_modifier = pdr->unit_modifier;
515de2a132aSGilbert Chen parsedPdr->occurrence_rate = pdr->occurrence_rate;
516de2a132aSGilbert Chen parsedPdr->range_field_support = pdr->range_field_support;
517de2a132aSGilbert Chen parsedPdr->warning_high = pdr->warning_high;
518de2a132aSGilbert Chen parsedPdr->warning_low = pdr->warning_low;
519de2a132aSGilbert Chen parsedPdr->critical_high = pdr->critical_high;
520de2a132aSGilbert Chen parsedPdr->critical_low = pdr->critical_low;
521de2a132aSGilbert Chen parsedPdr->fatal_high = pdr->fatal_high;
522de2a132aSGilbert Chen parsedPdr->fatal_low = pdr->fatal_low;
523de2a132aSGilbert Chen return parsedPdr;
524de2a132aSGilbert Chen }
525de2a132aSGilbert Chen
addCompactNumericSensor(const std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr)5263c5486d4SThu Nguyen void Terminus::addCompactNumericSensor(
5273c5486d4SThu Nguyen const std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr)
5283c5486d4SThu Nguyen {
52938a09d25SChau Ly if (!pdr)
5303c5486d4SThu Nguyen {
53138a09d25SChau Ly lg2::error(
53238a09d25SChau Ly "Terminus ID {TID}: Skip adding Compact Numeric Sensor - invalid pointer to PDR.",
53338a09d25SChau Ly "TID", tid);
534fdf61cc3SChaul Ly addNextSensorFromPDRs();
53538a09d25SChau Ly }
53638a09d25SChau Ly
53738a09d25SChau Ly auto sensorId = pdr->sensor_id;
53838a09d25SChau Ly auto sensorNames = getSensorNames(sensorId);
53938a09d25SChau Ly
54038a09d25SChau Ly if (sensorNames.empty())
5413c5486d4SThu Nguyen {
54238a09d25SChau Ly lg2::error(
54338a09d25SChau Ly "Terminus ID {TID}: Failed to get name for Compact Numeric Sensor {SID}",
54438a09d25SChau Ly "TID", tid, "SID", sensorId);
545fdf61cc3SChaul Ly addNextSensorFromPDRs();
5463c5486d4SThu Nguyen }
54738a09d25SChau Ly
54838a09d25SChau Ly std::string sensorName = sensorNames.front();
5493c5486d4SThu Nguyen
5503c5486d4SThu Nguyen try
5513c5486d4SThu Nguyen {
5523c5486d4SThu Nguyen auto sensor = std::make_shared<NumericSensor>(
5533c5486d4SThu Nguyen tid, true, pdr, sensorName, inventoryPath);
5543c5486d4SThu Nguyen lg2::info("Created Compact NumericSensor {NAME}", "NAME", sensorName);
5553c5486d4SThu Nguyen numericSensors.emplace_back(sensor);
5563c5486d4SThu Nguyen }
5573c5486d4SThu Nguyen catch (const sdbusplus::exception_t& e)
5583c5486d4SThu Nguyen {
5593c5486d4SThu Nguyen lg2::error(
5603c5486d4SThu Nguyen "Failed to create Compact NumericSensor. error - {ERROR} sensorname - {NAME}",
5613c5486d4SThu Nguyen "ERROR", e, "NAME", sensorName);
5623c5486d4SThu Nguyen }
563fdf61cc3SChaul Ly
564fdf61cc3SChaul Ly addNextSensorFromPDRs();
5653c5486d4SThu Nguyen }
5663c5486d4SThu Nguyen
getSensorObject(SensorId id)56777e6fe7aSGilbert Chen std::shared_ptr<NumericSensor> Terminus::getSensorObject(SensorId id)
56877e6fe7aSGilbert Chen {
56977e6fe7aSGilbert Chen if (terminusName.empty())
57077e6fe7aSGilbert Chen {
57177e6fe7aSGilbert Chen lg2::error(
57277e6fe7aSGilbert Chen "Terminus ID {TID}: DOES NOT have terminus name. No numeric sensor object.",
57377e6fe7aSGilbert Chen "TID", tid);
57477e6fe7aSGilbert Chen return nullptr;
57577e6fe7aSGilbert Chen }
57677e6fe7aSGilbert Chen if (!numericSensors.size())
57777e6fe7aSGilbert Chen {
57877e6fe7aSGilbert Chen lg2::error("Terminus ID {TID} name {NAME}: DOES NOT have sensor.",
57977e6fe7aSGilbert Chen "TID", tid, "NAME", terminusName);
58077e6fe7aSGilbert Chen return nullptr;
58177e6fe7aSGilbert Chen }
58277e6fe7aSGilbert Chen
58377e6fe7aSGilbert Chen for (auto& sensor : numericSensors)
58477e6fe7aSGilbert Chen {
58577e6fe7aSGilbert Chen if (!sensor)
58677e6fe7aSGilbert Chen {
58777e6fe7aSGilbert Chen continue;
58877e6fe7aSGilbert Chen }
58977e6fe7aSGilbert Chen
59077e6fe7aSGilbert Chen if (sensor->sensorId == id)
59177e6fe7aSGilbert Chen {
59277e6fe7aSGilbert Chen return sensor;
59377e6fe7aSGilbert Chen }
59477e6fe7aSGilbert Chen }
59577e6fe7aSGilbert Chen
59677e6fe7aSGilbert Chen return nullptr;
59777e6fe7aSGilbert Chen }
598b6d3943dSDung Cao
599b6d3943dSDung Cao /** @brief Check if a pointer is go through end of table
600b6d3943dSDung Cao * @param[in] table - pointer to FRU record table
601b6d3943dSDung Cao * @param[in] p - pointer to each record of FRU record table
602b6d3943dSDung Cao * @param[in] tableSize - FRU table size
603b6d3943dSDung Cao */
isTableEnd(const uint8_t * table,const uint8_t * p,const size_t tableSize)604b6d3943dSDung Cao static bool isTableEnd(const uint8_t* table, const uint8_t* p,
605b6d3943dSDung Cao const size_t tableSize)
606b6d3943dSDung Cao {
607b6d3943dSDung Cao auto offset = p - table;
608b6d3943dSDung Cao return (tableSize - offset) < sizeof(struct pldm_fru_record_data_format);
609b6d3943dSDung Cao }
610b6d3943dSDung Cao
updateInventoryWithFru(const uint8_t * fruData,const size_t fruLen)611b6d3943dSDung Cao void Terminus::updateInventoryWithFru(const uint8_t* fruData,
612b6d3943dSDung Cao const size_t fruLen)
613b6d3943dSDung Cao {
614b6d3943dSDung Cao auto tmp = getTerminusName();
615b6d3943dSDung Cao if (!tmp || tmp.value().empty())
616b6d3943dSDung Cao {
617b6d3943dSDung Cao lg2::error(
618b6d3943dSDung Cao "Terminus ID {TID}: Failed to update Inventory with Fru Data - error : Terminus name is empty.",
619b6d3943dSDung Cao "TID", tid);
620b6d3943dSDung Cao return;
621b6d3943dSDung Cao }
622b6d3943dSDung Cao
623b6d3943dSDung Cao if (createInventoryPath(static_cast<std::string>(tmp.value())))
624b6d3943dSDung Cao {
625b6d3943dSDung Cao lg2::info("Terminus ID {TID}: Created Inventory path.", "TID", tid);
626b6d3943dSDung Cao }
627b6d3943dSDung Cao
628b6d3943dSDung Cao auto ptr = fruData;
629b6d3943dSDung Cao while (!isTableEnd(fruData, ptr, fruLen))
630b6d3943dSDung Cao {
631b6d3943dSDung Cao auto record = reinterpret_cast<const pldm_fru_record_data_format*>(ptr);
632b6d3943dSDung Cao ptr += sizeof(pldm_fru_record_data_format) -
633b6d3943dSDung Cao sizeof(pldm_fru_record_tlv);
634b6d3943dSDung Cao
635b6d3943dSDung Cao if (!record->num_fru_fields)
636b6d3943dSDung Cao {
637b6d3943dSDung Cao lg2::error(
638b6d3943dSDung Cao "Invalid number of fields {NUM} of Record ID Type {TYPE} of terminus {TID}",
639b6d3943dSDung Cao "NUM", record->num_fru_fields, "TYPE", record->record_type,
640b6d3943dSDung Cao "TID", tid);
641b6d3943dSDung Cao return;
642b6d3943dSDung Cao }
643b6d3943dSDung Cao
644b6d3943dSDung Cao if (record->record_type != PLDM_FRU_RECORD_TYPE_GENERAL)
645b6d3943dSDung Cao {
646b6d3943dSDung Cao lg2::error(
647b6d3943dSDung Cao "Does not support Fru Record ID Type {TYPE} of terminus {TID}",
648b6d3943dSDung Cao "TYPE", record->record_type, "TID", tid);
649b6d3943dSDung Cao
650b6d3943dSDung Cao for ([[maybe_unused]] const auto& idx :
651b6d3943dSDung Cao std::views::iota(0, static_cast<int>(record->num_fru_fields)))
652b6d3943dSDung Cao {
653b6d3943dSDung Cao auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(ptr);
654b6d3943dSDung Cao ptr += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
655b6d3943dSDung Cao }
656b6d3943dSDung Cao continue;
657b6d3943dSDung Cao }
658b6d3943dSDung Cao /* FRU General record type */
659b6d3943dSDung Cao for ([[maybe_unused]] const auto& idx :
660b6d3943dSDung Cao std::views::iota(0, static_cast<int>(record->num_fru_fields)))
661b6d3943dSDung Cao {
662b6d3943dSDung Cao auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(ptr);
663b6d3943dSDung Cao std::string fruField{};
664b6d3943dSDung Cao if (tlv->type != PLDM_FRU_FIELD_TYPE_IANA)
665b6d3943dSDung Cao {
666b6d3943dSDung Cao auto strOptional =
667b6d3943dSDung Cao pldm::utils::fruFieldValuestring(tlv->value, tlv->length);
668b6d3943dSDung Cao if (!strOptional)
669b6d3943dSDung Cao {
670b6d3943dSDung Cao ptr += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
671b6d3943dSDung Cao continue;
672b6d3943dSDung Cao }
673b6d3943dSDung Cao fruField = strOptional.value();
674b6d3943dSDung Cao
675b6d3943dSDung Cao if (fruField.empty())
676b6d3943dSDung Cao {
677b6d3943dSDung Cao ptr += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
678b6d3943dSDung Cao continue;
679b6d3943dSDung Cao }
680b6d3943dSDung Cao }
681b6d3943dSDung Cao
682b6d3943dSDung Cao switch (tlv->type)
683b6d3943dSDung Cao {
684b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_MODEL:
685b6d3943dSDung Cao inventoryItemBoardInft->model(fruField);
686b6d3943dSDung Cao break;
687b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_PN:
688b6d3943dSDung Cao inventoryItemBoardInft->partNumber(fruField);
689b6d3943dSDung Cao break;
690b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_SN:
691b6d3943dSDung Cao inventoryItemBoardInft->serialNumber(fruField);
692b6d3943dSDung Cao break;
693b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_MANUFAC:
694b6d3943dSDung Cao inventoryItemBoardInft->manufacturer(fruField);
695b6d3943dSDung Cao break;
696b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_NAME:
697b6d3943dSDung Cao inventoryItemBoardInft->names({fruField});
698b6d3943dSDung Cao break;
699b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_VERSION:
700b6d3943dSDung Cao inventoryItemBoardInft->version(fruField);
701b6d3943dSDung Cao break;
702b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_ASSET_TAG:
703b6d3943dSDung Cao inventoryItemBoardInft->assetTag(fruField);
704b6d3943dSDung Cao break;
705b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_VENDOR:
706b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_CHASSIS:
707b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_SKU:
708b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_DESC:
709b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_EC_LVL:
710b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_OTHER:
711b6d3943dSDung Cao break;
712b6d3943dSDung Cao case PLDM_FRU_FIELD_TYPE_IANA:
713b6d3943dSDung Cao auto iana =
714b6d3943dSDung Cao pldm::utils::fruFieldParserU32(tlv->value, tlv->length);
715b6d3943dSDung Cao if (!iana)
716b6d3943dSDung Cao {
717b6d3943dSDung Cao ptr += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
718b6d3943dSDung Cao continue;
719b6d3943dSDung Cao }
720b6d3943dSDung Cao break;
721b6d3943dSDung Cao }
722b6d3943dSDung Cao ptr += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
723b6d3943dSDung Cao }
724b6d3943dSDung Cao }
725b6d3943dSDung Cao }
726b6d3943dSDung Cao
getSensorNames(const SensorId & sensorId)72738a09d25SChau Ly std::vector<std::string> Terminus::getSensorNames(const SensorId& sensorId)
72838a09d25SChau Ly {
72938a09d25SChau Ly std::vector<std::string> sensorNames;
73038a09d25SChau Ly std::string defaultName =
73138a09d25SChau Ly std::format("{}_Sensor_{}", terminusName, unsigned(sensorId));
73238a09d25SChau Ly // To ensure there's always a default name at offset 0
73338a09d25SChau Ly sensorNames.emplace_back(defaultName);
73438a09d25SChau Ly
73538a09d25SChau Ly auto sensorAuxiliaryNames = getSensorAuxiliaryNames(sensorId);
73638a09d25SChau Ly if (!sensorAuxiliaryNames)
73738a09d25SChau Ly {
73838a09d25SChau Ly return sensorNames;
73938a09d25SChau Ly }
74038a09d25SChau Ly
74138a09d25SChau Ly const auto& [id, sensorCount, nameMap] = *sensorAuxiliaryNames;
74238a09d25SChau Ly for (const unsigned int& i :
74338a09d25SChau Ly std::views::iota(0, static_cast<int>(sensorCount)))
74438a09d25SChau Ly {
74538a09d25SChau Ly auto sensorName = defaultName;
74638a09d25SChau Ly if (i > 0)
74738a09d25SChau Ly {
74838a09d25SChau Ly // Sensor name at offset 0 will be the default name
74938a09d25SChau Ly sensorName += "_" + std::to_string(i);
75038a09d25SChau Ly }
75138a09d25SChau Ly
75238a09d25SChau Ly for (const auto& [languageTag, name] : nameMap[i])
75338a09d25SChau Ly {
75438a09d25SChau Ly if (languageTag == "en" && !name.empty())
75538a09d25SChau Ly {
75638a09d25SChau Ly sensorName = std::format("{}_{}", terminusName, name);
75738a09d25SChau Ly }
75838a09d25SChau Ly }
75938a09d25SChau Ly
76038a09d25SChau Ly if (i >= sensorNames.size())
76138a09d25SChau Ly {
76238a09d25SChau Ly sensorNames.emplace_back(sensorName);
76338a09d25SChau Ly }
76438a09d25SChau Ly else
76538a09d25SChau Ly {
76638a09d25SChau Ly sensorNames[i] = sensorName;
76738a09d25SChau Ly }
76838a09d25SChau Ly }
76938a09d25SChau Ly
77038a09d25SChau Ly return sensorNames;
77138a09d25SChau Ly }
77238a09d25SChau Ly
7736c7fed4cSGilbert Chen } // namespace platform_mc
7746c7fed4cSGilbert Chen } // namespace pldm
775