Handle FRU records from host
- Get FRU record table from host and traverse the entity structure
from the FRU record set PDR, and create D-Bus object.
- When the FRU field type is a PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE
, the location code is used to populate the
xyz.openbmc_project.Inventory.Decorator.LocationCode D-Bus
interface for the corresponding FRU.
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I482c4d371f76b4881109ef420dfd9543e1aa810b
diff --git a/libpldmresponder/pdr_utils.cpp b/libpldmresponder/pdr_utils.cpp
index 7e5e491..06832a1 100644
--- a/libpldmresponder/pdr_utils.cpp
+++ b/libpldmresponder/pdr_utils.cpp
@@ -1,3 +1,5 @@
+#include "libpldm/fru.h"
+
#include "pdr.hpp"
#include <libpldm/platform.h>
@@ -16,6 +18,15 @@
{
namespace pdr_utils
{
+// Refer: DSP0257_1.0.0 Table 2
+// 7: uint16_t(FRU Record Set Identifier), uint8_t(FRU Record Type),
+// uint8_t(Number of FRU fields), uint8_t(Encoding Type for FRU fields),
+// uint8_t(FRU Field Type), uint8_t(FRU Field Length)
+static constexpr uint8_t fruRecordDataFormatLength = 7;
+
+// // 2: 1byte FRU Field Type, 1byte FRU Field Length
+static constexpr uint8_t fruFieldTypeLength = 2;
+
pldm_pdr* Repo::getPdr() const
{
return repo;
@@ -196,6 +207,58 @@
std::move(sensorInfo));
}
+std::vector<FruRecordDataFormat> parseFruRecordTable(const uint8_t* fruData,
+ size_t fruLen)
+{
+ // Refer: DSP0257_1.0.0 Table 2
+ // 7: uint16_t(FRU Record Set Identifier), uint8_t(FRU Record Type),
+ // uint8_t(Number of FRU fields), uint8_t(Encoding Type for FRU fields),
+ // uint8_t(FRU Field Type), uint8_t(FRU Field Length)
+ if (fruLen < fruRecordDataFormatLength)
+ {
+ lg2::error("Invalid fru len: {FRULEN}", "FRULEN", fruLen);
+ return {};
+ }
+
+ std::vector<FruRecordDataFormat> frus;
+
+ size_t index = 0;
+ while (index < fruLen)
+ {
+ FruRecordDataFormat fru;
+
+ auto record = reinterpret_cast<const pldm_fru_record_data_format*>(
+ fruData + index);
+ fru.fruRSI = (int)le16toh(record->record_set_id);
+ fru.fruRecType = record->record_type;
+ fru.fruNum = record->num_fru_fields;
+ fru.fruEncodeType = record->encoding_type;
+
+ index += 5;
+
+ std::ranges::for_each(std::views::iota(0, (int)record->num_fru_fields),
+ [fruData, &fru, &index](int) {
+ auto tlv =
+ reinterpret_cast<const pldm_fru_record_tlv*>(fruData + index);
+ FruTLV frutlv;
+ frutlv.fruFieldType = tlv->type;
+ frutlv.fruFieldLen = tlv->length;
+ frutlv.fruFieldValue.resize(tlv->length);
+ for (const auto& i : std::views::iota(0, (int)tlv->length))
+ {
+ memcpy(frutlv.fruFieldValue.data() + i, tlv->value + i, 1);
+ }
+ fru.fruTLV.push_back(frutlv);
+
+ // 2: 1byte FRU Field Type, 1byte FRU Field Length
+ index += fruFieldTypeLength + (unsigned)tlv->length;
+ });
+
+ frus.push_back(fru);
+ }
+
+ return frus;
+}
} // namespace pdr_utils
} // namespace responder
} // namespace pldm