blob: e7f6d42bcc6368bf676a1e3752c7c1304d4a9aae [file] [log] [blame]
George Liue53193f2020-02-24 09:23:26 +08001#include "pdr.hpp"
2
Andrew Jeffery4668f5c2024-01-15 14:59:17 +10303#include <libpldm/fru.h>
George Liuc453e162022-12-21 17:16:23 +08004#include <libpldm/platform.h>
Manojkiran Eda3ca40452021-10-04 22:51:37 +05305
Riya Dixit49cfb132023-03-02 04:26:53 -06006#include <phosphor-logging/lg2.hpp>
7
Tom Josephb4268602020-04-17 17:20:45 +05308#include <climits>
9
Riya Dixit49cfb132023-03-02 04:26:53 -060010PHOSPHOR_LOG2_USING;
11
Brad Bishop5079ac42021-08-19 18:35:06 -040012using namespace pldm::pdr;
13
George Liue53193f2020-02-24 09:23:26 +080014namespace pldm
15{
George Liue53193f2020-02-24 09:23:26 +080016namespace responder
17{
George Liue53193f2020-02-24 09:23:26 +080018namespace pdr_utils
19{
George Liu682ee182020-12-25 15:24:33 +080020// 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)
24static constexpr uint8_t fruRecordDataFormatLength = 7;
25
26// // 2: 1byte FRU Field Type, 1byte FRU Field Length
27static constexpr uint8_t fruFieldTypeLength = 2;
28
Deepak Kodihallic682fe22020-03-04 00:42:54 -060029pldm_pdr* Repo::getPdr() const
George Liue53193f2020-02-24 09:23:26 +080030{
31 return repo;
32}
33
34RecordHandle Repo::addRecord(const PdrEntry& pdrEntry)
35{
Andrew Jeffery64f37fe2023-07-03 15:41:13 +093036 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;
George Liue53193f2020-02-24 09:23:26 +080045}
46
47const pldm_pdr_record* Repo::getFirstRecord(PdrEntry& pdrEntry)
48{
49 constexpr uint32_t firstNum = 0;
50 uint8_t* pdrData = nullptr;
Patrick Williams6da4f912023-05-10 07:50:53 -050051 auto record = pldm_pdr_find_record(getPdr(), firstNum, &pdrData,
52 &pdrEntry.size,
53 &pdrEntry.handle.nextRecordHandle);
George Liue53193f2020-02-24 09:23:26 +080054 if (record)
55 {
56 pdrEntry.data = pdrData;
57 }
58
59 return record;
60}
61
62const pldm_pdr_record* Repo::getNextRecord(const pldm_pdr_record* currRecord,
63 PdrEntry& pdrEntry)
64{
65 uint8_t* pdrData = nullptr;
Patrick Williams6da4f912023-05-10 07:50:53 -050066 auto record = pldm_pdr_get_next_record(getPdr(), currRecord, &pdrData,
67 &pdrEntry.size,
68 &pdrEntry.handle.nextRecordHandle);
George Liue53193f2020-02-24 09:23:26 +080069 if (record)
70 {
71 pdrEntry.data = pdrData;
72 }
73
74 return record;
75}
76
Deepak Kodihallic682fe22020-03-04 00:42:54 -060077uint32_t Repo::getRecordHandle(const pldm_pdr_record* record) const
George Liue53193f2020-02-24 09:23:26 +080078{
79 return pldm_pdr_get_record_handle(getPdr(), record);
80}
81
82uint32_t Repo::getRecordCount()
83{
84 return pldm_pdr_get_record_count(getPdr());
85}
86
87bool Repo::empty()
88{
89 return !getRecordCount();
90}
91
George Liu1ec85d42020-02-12 16:05:32 +080092StatestoDbusVal 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 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600100 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());
George Liu1ec85d42020-02-12 16:05:32 +0800103 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 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600150 error("Unknown D-Bus property type, TYPE={OTHER_TYPE}",
151 "OTHER_TYPE", type.c_str());
George Liu1ec85d42020-02-12 16:05:32 +0800152 return {};
153 }
154
155 valueMap.emplace(pv[pos], value);
156 }
157
158 return valueMap;
159}
160
Tom Josephb4268602020-04-17 17:20:45 +0530161std::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;
Sagar Srinivase3607a32024-02-16 03:50:53 -0600169 std::vector<StateSetId> stateSetIds{};
Tom Josephb4268602020-04-17 17:20:45 +0530170
171 while (compositeSensorCount--)
172 {
173 auto state =
174 reinterpret_cast<const state_sensor_possible_states*>(statesPtr);
175 PossibleStates possibleStates{};
176 uint8_t possibleStatesPos{};
Patrick Williamsa6756622023-10-20 11:19:15 -0500177 auto updateStates = [&possibleStates,
178 &possibleStatesPos](const bitfield8_t& val) {
Tom Josephb4268602020-04-17 17:20:45 +0530179 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));
Sagar Srinivase3607a32024-02-16 03:50:53 -0600193 stateSetIds.emplace_back(state->state_set_id);
194
Tom Josephb4268602020-04-17 17:20:45 +0530195 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));
Sagar Srinivase3607a32024-02-16 03:50:53 -0600206 auto sensorInfo = std::make_tuple(std::move(entityInfo), std::move(sensors),
207 std::move(stateSetIds));
Tom Josephb4268602020-04-17 17:20:45 +0530208 return std::make_tuple(pdr->terminus_handle, pdr->sensor_id,
209 std::move(sensorInfo));
210}
211
George Liu682ee182020-12-25 15:24:33 +0800212std::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}
Archana Kakani6ece21fb2023-10-10 08:21:52 -0500264
265size_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
George Liue53193f2020-02-24 09:23:26 +0800286} // namespace pdr_utils
287} // namespace responder
288} // namespace pldm