#include "pdr.hpp" #include #include #include #include PHOSPHOR_LOG2_USING; using namespace pldm::pdr; namespace pldm { namespace responder { 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; } RecordHandle Repo::addRecord(const PdrEntry& pdrEntry) { uint32_t handle = pdrEntry.handle.recordHandle; int rc = pldm_pdr_add_check(repo, pdrEntry.data, pdrEntry.size, false, TERMINUS_HANDLE, &handle); if (rc) { // pldm_pdr_add() assert()ed on failure to add PDR throw std::runtime_error("Failed to add PDR"); } return handle; } const pldm_pdr_record* Repo::getFirstRecord(PdrEntry& pdrEntry) { constexpr uint32_t firstNum = 0; uint8_t* pdrData = nullptr; auto record = pldm_pdr_find_record(getPdr(), firstNum, &pdrData, &pdrEntry.size, &pdrEntry.handle.nextRecordHandle); if (record) { pdrEntry.data = pdrData; } return record; } const pldm_pdr_record* Repo::getNextRecord(const pldm_pdr_record* currRecord, PdrEntry& pdrEntry) { uint8_t* pdrData = nullptr; auto record = pldm_pdr_get_next_record(getPdr(), currRecord, &pdrData, &pdrEntry.size, &pdrEntry.handle.nextRecordHandle); if (record) { pdrEntry.data = pdrData; } return record; } uint32_t Repo::getRecordHandle(const pldm_pdr_record* record) const { return pldm_pdr_get_record_handle(getPdr(), record); } uint32_t Repo::getRecordCount() { return pldm_pdr_get_record_count(getPdr()); } bool Repo::empty() { return !getRecordCount(); } StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues, const PossibleValues& pv) { size_t pos = 0; pldm::utils::PropertyValue value; StatestoDbusVal valueMap; if (dBusValues.size() != pv.size()) { error( "DBusValues size '{DBUS_VALUE_SIZE}' is not equal to pv size'{PROPERTY_VALUE_SIZE}'.", "DBUS_VALUE_SIZE", dBusValues.size(), "PROPERTY_VALUE_SIZE", pv.size()); return {}; } for (auto it = dBusValues.begin(); it != dBusValues.end(); ++it, ++pos) { if (type == "uint8_t") { value = static_cast(it.value()); } else if (type == "uint16_t") { value = static_cast(it.value()); } else if (type == "uint32_t") { value = static_cast(it.value()); } else if (type == "uint64_t") { value = static_cast(it.value()); } else if (type == "int16_t") { value = static_cast(it.value()); } else if (type == "int32_t") { value = static_cast(it.value()); } else if (type == "int64_t") { value = static_cast(it.value()); } else if (type == "bool") { value = static_cast(it.value()); } else if (type == "double") { value = static_cast(it.value()); } else if (type == "string") { value = static_cast(it.value()); } else { error("Unknown D-Bus property type '{TYPE}'", "TYPE", type); return {}; } valueMap.emplace(pv[pos], value); } return valueMap; } std::tuple parseStateSensorPDR(const std::vector& stateSensorPdr) { auto pdr = reinterpret_cast(stateSensorPdr.data()); CompositeSensorStates sensors{}; auto statesPtr = pdr->possible_states; auto compositeSensorCount = pdr->composite_sensor_count; std::vector stateSetIds{}; while (compositeSensorCount--) { auto state = reinterpret_cast(statesPtr); PossibleStates possibleStates{}; uint8_t possibleStatesPos{}; auto updateStates = [&possibleStates, &possibleStatesPos](const bitfield8_t& val) { for (int i = 0; i < CHAR_BIT; i++) { if (val.byte & (1 << i)) { possibleStates.insert(possibleStatesPos * CHAR_BIT + i); } } possibleStatesPos++; }; std::for_each(&state->states[0], &state->states[state->possible_states_size], updateStates); sensors.emplace_back(std::move(possibleStates)); stateSetIds.emplace_back(state->state_set_id); if (compositeSensorCount) { statesPtr += sizeof(state_sensor_possible_states) + state->possible_states_size - 1; } } auto entityInfo = std::make_tuple(static_cast(pdr->container_id), static_cast(pdr->entity_type), static_cast(pdr->entity_instance)); auto sensorInfo = std::make_tuple(std::move(entityInfo), std::move(sensors), std::move(stateSetIds)); return std::make_tuple(pdr->terminus_handle, pdr->sensor_id, std::move(sensorInfo)); } std::vector 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) { error("Invalid FRU length '{LENGTH}' while parsing FRU record table", "LENGTH", fruLen); return {}; } std::vector frus; size_t index = 0; while (index < fruLen) { FruRecordDataFormat fru; auto record = reinterpret_cast( 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(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; } size_t getEffecterDataSize(uint8_t effecterDataSize) { switch (effecterDataSize) { case PLDM_EFFECTER_DATA_SIZE_UINT8: return sizeof(uint8_t); case PLDM_EFFECTER_DATA_SIZE_SINT8: return sizeof(int8_t); case PLDM_EFFECTER_DATA_SIZE_UINT16: return sizeof(uint16_t); case PLDM_EFFECTER_DATA_SIZE_SINT16: return sizeof(int16_t); case PLDM_EFFECTER_DATA_SIZE_UINT32: return sizeof(uint32_t); case PLDM_EFFECTER_DATA_SIZE_SINT32: return sizeof(int32_t); default: return 0; } } } // namespace pdr_utils } // namespace responder } // namespace pldm