xref: /openbmc/pldm/platform-mc/terminus.cpp (revision fe2527954be36a3013dc6b8c8ff13ae649bb58a6)
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