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 170 while (compositeSensorCount--) 171 { 172 auto state = 173 reinterpret_cast<const state_sensor_possible_states*>(statesPtr); 174 PossibleStates possibleStates{}; 175 uint8_t possibleStatesPos{}; 176 auto updateStates = [&possibleStates, 177 &possibleStatesPos](const bitfield8_t& val) { 178 for (int i = 0; i < CHAR_BIT; i++) 179 { 180 if (val.byte & (1 << i)) 181 { 182 possibleStates.insert(possibleStatesPos * CHAR_BIT + i); 183 } 184 } 185 possibleStatesPos++; 186 }; 187 std::for_each(&state->states[0], 188 &state->states[state->possible_states_size], 189 updateStates); 190 191 sensors.emplace_back(std::move(possibleStates)); 192 if (compositeSensorCount) 193 { 194 statesPtr += sizeof(state_sensor_possible_states) + 195 state->possible_states_size - 1; 196 } 197 } 198 199 auto entityInfo = 200 std::make_tuple(static_cast<ContainerID>(pdr->container_id), 201 static_cast<EntityType>(pdr->entity_type), 202 static_cast<EntityInstance>(pdr->entity_instance)); 203 auto sensorInfo = std::make_tuple(std::move(entityInfo), 204 std::move(sensors)); 205 return std::make_tuple(pdr->terminus_handle, pdr->sensor_id, 206 std::move(sensorInfo)); 207 } 208 209 std::vector<FruRecordDataFormat> parseFruRecordTable(const uint8_t* fruData, 210 size_t fruLen) 211 { 212 // Refer: DSP0257_1.0.0 Table 2 213 // 7: uint16_t(FRU Record Set Identifier), uint8_t(FRU Record Type), 214 // uint8_t(Number of FRU fields), uint8_t(Encoding Type for FRU fields), 215 // uint8_t(FRU Field Type), uint8_t(FRU Field Length) 216 if (fruLen < fruRecordDataFormatLength) 217 { 218 lg2::error("Invalid fru len: {FRULEN}", "FRULEN", fruLen); 219 return {}; 220 } 221 222 std::vector<FruRecordDataFormat> frus; 223 224 size_t index = 0; 225 while (index < fruLen) 226 { 227 FruRecordDataFormat fru; 228 229 auto record = reinterpret_cast<const pldm_fru_record_data_format*>( 230 fruData + index); 231 fru.fruRSI = (int)le16toh(record->record_set_id); 232 fru.fruRecType = record->record_type; 233 fru.fruNum = record->num_fru_fields; 234 fru.fruEncodeType = record->encoding_type; 235 236 index += 5; 237 238 std::ranges::for_each(std::views::iota(0, (int)record->num_fru_fields), 239 [fruData, &fru, &index](int) { 240 auto tlv = 241 reinterpret_cast<const pldm_fru_record_tlv*>(fruData + index); 242 FruTLV frutlv; 243 frutlv.fruFieldType = tlv->type; 244 frutlv.fruFieldLen = tlv->length; 245 frutlv.fruFieldValue.resize(tlv->length); 246 for (const auto& i : std::views::iota(0, (int)tlv->length)) 247 { 248 memcpy(frutlv.fruFieldValue.data() + i, tlv->value + i, 1); 249 } 250 fru.fruTLV.push_back(frutlv); 251 252 // 2: 1byte FRU Field Type, 1byte FRU Field Length 253 index += fruFieldTypeLength + (unsigned)tlv->length; 254 }); 255 256 frus.push_back(fru); 257 } 258 259 return frus; 260 } 261 262 size_t getEffecterDataSize(uint8_t effecterDataSize) 263 { 264 switch (effecterDataSize) 265 { 266 case PLDM_EFFECTER_DATA_SIZE_UINT8: 267 return sizeof(uint8_t); 268 case PLDM_EFFECTER_DATA_SIZE_SINT8: 269 return sizeof(int8_t); 270 case PLDM_EFFECTER_DATA_SIZE_UINT16: 271 return sizeof(uint16_t); 272 case PLDM_EFFECTER_DATA_SIZE_SINT16: 273 return sizeof(int16_t); 274 case PLDM_EFFECTER_DATA_SIZE_UINT32: 275 return sizeof(uint32_t); 276 case PLDM_EFFECTER_DATA_SIZE_SINT32: 277 return sizeof(int32_t); 278 default: 279 return 0; 280 } 281 } 282 283 } // namespace pdr_utils 284 } // namespace responder 285 } // namespace pldm 286