1 #include "pdr.hpp" 2 3 #include <libpldm/fru.h> 4 #include <libpldm/platform.h> 5 6 #include <phosphor-logging/lg2.hpp> 7 8 #include <climits> 9 10 PHOSPHOR_LOG2_USING; 11 12 using namespace pldm::pdr; 13 14 namespace pldm 15 { 16 namespace responder 17 { 18 namespace pdr_utils 19 { 20 // Refer: DSP0257_1.0.0 Table 2 21 // 7: uint16_t(FRU Record Set Identifier), uint8_t(FRU Record Type), 22 // uint8_t(Number of FRU fields), uint8_t(Encoding Type for FRU fields), 23 // uint8_t(FRU Field Type), uint8_t(FRU Field Length) 24 static constexpr uint8_t fruRecordDataFormatLength = 7; 25 26 // // 2: 1byte FRU Field Type, 1byte FRU Field Length 27 static constexpr uint8_t fruFieldTypeLength = 2; 28 29 pldm_pdr* Repo::getPdr() const 30 { 31 return repo; 32 } 33 34 RecordHandle Repo::addRecord(const PdrEntry& pdrEntry) 35 { 36 uint32_t handle = pdrEntry.handle.recordHandle; 37 int rc = pldm_pdr_add_check(repo, pdrEntry.data, pdrEntry.size, false, 38 TERMINUS_HANDLE, &handle); 39 if (rc) 40 { 41 // pldm_pdr_add() assert()ed on failure to add PDR 42 throw std::runtime_error("Failed to add PDR"); 43 } 44 return handle; 45 } 46 47 const pldm_pdr_record* Repo::getFirstRecord(PdrEntry& pdrEntry) 48 { 49 constexpr uint32_t firstNum = 0; 50 uint8_t* pdrData = nullptr; 51 auto record = pldm_pdr_find_record(getPdr(), firstNum, &pdrData, 52 &pdrEntry.size, 53 &pdrEntry.handle.nextRecordHandle); 54 if (record) 55 { 56 pdrEntry.data = pdrData; 57 } 58 59 return record; 60 } 61 62 const pldm_pdr_record* Repo::getNextRecord(const pldm_pdr_record* currRecord, 63 PdrEntry& pdrEntry) 64 { 65 uint8_t* pdrData = nullptr; 66 auto record = pldm_pdr_get_next_record(getPdr(), currRecord, &pdrData, 67 &pdrEntry.size, 68 &pdrEntry.handle.nextRecordHandle); 69 if (record) 70 { 71 pdrEntry.data = pdrData; 72 } 73 74 return record; 75 } 76 77 uint32_t Repo::getRecordHandle(const pldm_pdr_record* record) const 78 { 79 return pldm_pdr_get_record_handle(getPdr(), record); 80 } 81 82 uint32_t Repo::getRecordCount() 83 { 84 return pldm_pdr_get_record_count(getPdr()); 85 } 86 87 bool Repo::empty() 88 { 89 return !getRecordCount(); 90 } 91 92 StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues, 93 const PossibleValues& pv) 94 { 95 size_t pos = 0; 96 pldm::utils::PropertyValue value; 97 StatestoDbusVal valueMap; 98 if (dBusValues.size() != pv.size()) 99 { 100 error( 101 "dBusValues size is not equal to pv size, dBusValues Size: {DBUS_VAL_SIZE}, pv Size: {PV_SIZE}", 102 "DBUS_VAL_SIZE", dBusValues.size(), "PV_SIZE", pv.size()); 103 return {}; 104 } 105 106 for (auto it = dBusValues.begin(); it != dBusValues.end(); ++it, ++pos) 107 { 108 if (type == "uint8_t") 109 { 110 value = static_cast<uint8_t>(it.value()); 111 } 112 else if (type == "uint16_t") 113 { 114 value = static_cast<uint16_t>(it.value()); 115 } 116 else if (type == "uint32_t") 117 { 118 value = static_cast<uint32_t>(it.value()); 119 } 120 else if (type == "uint64_t") 121 { 122 value = static_cast<uint64_t>(it.value()); 123 } 124 else if (type == "int16_t") 125 { 126 value = static_cast<int16_t>(it.value()); 127 } 128 else if (type == "int32_t") 129 { 130 value = static_cast<int32_t>(it.value()); 131 } 132 else if (type == "int64_t") 133 { 134 value = static_cast<int64_t>(it.value()); 135 } 136 else if (type == "bool") 137 { 138 value = static_cast<bool>(it.value()); 139 } 140 else if (type == "double") 141 { 142 value = static_cast<double>(it.value()); 143 } 144 else if (type == "string") 145 { 146 value = static_cast<std::string>(it.value()); 147 } 148 else 149 { 150 error("Unknown D-Bus property type, TYPE={OTHER_TYPE}", 151 "OTHER_TYPE", type.c_str()); 152 return {}; 153 } 154 155 valueMap.emplace(pv[pos], value); 156 } 157 158 return valueMap; 159 } 160 161 std::tuple<TerminusHandle, SensorID, SensorInfo> 162 parseStateSensorPDR(const std::vector<uint8_t>& stateSensorPdr) 163 { 164 auto pdr = 165 reinterpret_cast<const pldm_state_sensor_pdr*>(stateSensorPdr.data()); 166 CompositeSensorStates sensors{}; 167 auto statesPtr = pdr->possible_states; 168 auto compositeSensorCount = pdr->composite_sensor_count; 169 std::vector<StateSetId> stateSetIds{}; 170 171 while (compositeSensorCount--) 172 { 173 auto state = 174 reinterpret_cast<const state_sensor_possible_states*>(statesPtr); 175 PossibleStates possibleStates{}; 176 uint8_t possibleStatesPos{}; 177 auto updateStates = [&possibleStates, 178 &possibleStatesPos](const bitfield8_t& val) { 179 for (int i = 0; i < CHAR_BIT; i++) 180 { 181 if (val.byte & (1 << i)) 182 { 183 possibleStates.insert(possibleStatesPos * CHAR_BIT + i); 184 } 185 } 186 possibleStatesPos++; 187 }; 188 std::for_each(&state->states[0], 189 &state->states[state->possible_states_size], 190 updateStates); 191 192 sensors.emplace_back(std::move(possibleStates)); 193 stateSetIds.emplace_back(state->state_set_id); 194 195 if (compositeSensorCount) 196 { 197 statesPtr += sizeof(state_sensor_possible_states) + 198 state->possible_states_size - 1; 199 } 200 } 201 202 auto entityInfo = 203 std::make_tuple(static_cast<ContainerID>(pdr->container_id), 204 static_cast<EntityType>(pdr->entity_type), 205 static_cast<EntityInstance>(pdr->entity_instance)); 206 auto sensorInfo = std::make_tuple(std::move(entityInfo), std::move(sensors), 207 std::move(stateSetIds)); 208 return std::make_tuple(pdr->terminus_handle, pdr->sensor_id, 209 std::move(sensorInfo)); 210 } 211 212 std::vector<FruRecordDataFormat> parseFruRecordTable(const uint8_t* fruData, 213 size_t fruLen) 214 { 215 // Refer: DSP0257_1.0.0 Table 2 216 // 7: uint16_t(FRU Record Set Identifier), uint8_t(FRU Record Type), 217 // uint8_t(Number of FRU fields), uint8_t(Encoding Type for FRU fields), 218 // uint8_t(FRU Field Type), uint8_t(FRU Field Length) 219 if (fruLen < fruRecordDataFormatLength) 220 { 221 lg2::error("Invalid fru len: {FRULEN}", "FRULEN", fruLen); 222 return {}; 223 } 224 225 std::vector<FruRecordDataFormat> frus; 226 227 size_t index = 0; 228 while (index < fruLen) 229 { 230 FruRecordDataFormat fru; 231 232 auto record = reinterpret_cast<const pldm_fru_record_data_format*>( 233 fruData + index); 234 fru.fruRSI = (int)le16toh(record->record_set_id); 235 fru.fruRecType = record->record_type; 236 fru.fruNum = record->num_fru_fields; 237 fru.fruEncodeType = record->encoding_type; 238 239 index += 5; 240 241 std::ranges::for_each(std::views::iota(0, (int)record->num_fru_fields), 242 [fruData, &fru, &index](int) { 243 auto tlv = 244 reinterpret_cast<const pldm_fru_record_tlv*>(fruData + index); 245 FruTLV frutlv; 246 frutlv.fruFieldType = tlv->type; 247 frutlv.fruFieldLen = tlv->length; 248 frutlv.fruFieldValue.resize(tlv->length); 249 for (const auto& i : std::views::iota(0, (int)tlv->length)) 250 { 251 memcpy(frutlv.fruFieldValue.data() + i, tlv->value + i, 1); 252 } 253 fru.fruTLV.push_back(frutlv); 254 255 // 2: 1byte FRU Field Type, 1byte FRU Field Length 256 index += fruFieldTypeLength + (unsigned)tlv->length; 257 }); 258 259 frus.push_back(fru); 260 } 261 262 return frus; 263 } 264 265 size_t getEffecterDataSize(uint8_t effecterDataSize) 266 { 267 switch (effecterDataSize) 268 { 269 case PLDM_EFFECTER_DATA_SIZE_UINT8: 270 return sizeof(uint8_t); 271 case PLDM_EFFECTER_DATA_SIZE_SINT8: 272 return sizeof(int8_t); 273 case PLDM_EFFECTER_DATA_SIZE_UINT16: 274 return sizeof(uint16_t); 275 case PLDM_EFFECTER_DATA_SIZE_SINT16: 276 return sizeof(int16_t); 277 case PLDM_EFFECTER_DATA_SIZE_UINT32: 278 return sizeof(uint32_t); 279 case PLDM_EFFECTER_DATA_SIZE_SINT32: 280 return sizeof(int32_t); 281 default: 282 return 0; 283 } 284 } 285 286 } // namespace pdr_utils 287 } // namespace responder 288 } // namespace pldm 289