blob: acaedd746bde618a9013a17108f66017f2e09c57 [file] [log] [blame]
George Liu682ee182020-12-25 15:24:33 +08001#include "libpldm/fru.h"
2
George Liue53193f2020-02-24 09:23:26 +08003#include "pdr.hpp"
4
George Liuc453e162022-12-21 17:16:23 +08005#include <libpldm/platform.h>
Manojkiran Eda3ca40452021-10-04 22:51:37 +05306
Riya Dixit49cfb132023-03-02 04:26:53 -06007#include <phosphor-logging/lg2.hpp>
8
Tom Josephb4268602020-04-17 17:20:45 +05309#include <climits>
10
Riya Dixit49cfb132023-03-02 04:26:53 -060011PHOSPHOR_LOG2_USING;
12
Brad Bishop5079ac42021-08-19 18:35:06 -040013using namespace pldm::pdr;
14
George Liue53193f2020-02-24 09:23:26 +080015namespace pldm
16{
George Liue53193f2020-02-24 09:23:26 +080017namespace responder
18{
George Liue53193f2020-02-24 09:23:26 +080019namespace pdr_utils
20{
George Liu682ee182020-12-25 15:24:33 +080021// Refer: DSP0257_1.0.0 Table 2
22// 7: uint16_t(FRU Record Set Identifier), uint8_t(FRU Record Type),
23// uint8_t(Number of FRU fields), uint8_t(Encoding Type for FRU fields),
24// uint8_t(FRU Field Type), uint8_t(FRU Field Length)
25static constexpr uint8_t fruRecordDataFormatLength = 7;
26
27// // 2: 1byte FRU Field Type, 1byte FRU Field Length
28static constexpr uint8_t fruFieldTypeLength = 2;
29
Deepak Kodihallic682fe22020-03-04 00:42:54 -060030pldm_pdr* Repo::getPdr() const
George Liue53193f2020-02-24 09:23:26 +080031{
32 return repo;
33}
34
35RecordHandle Repo::addRecord(const PdrEntry& pdrEntry)
36{
Andrew Jeffery64f37fe2023-07-03 15:41:13 +093037 uint32_t handle = pdrEntry.handle.recordHandle;
38 int rc = pldm_pdr_add_check(repo, pdrEntry.data, pdrEntry.size, false,
39 TERMINUS_HANDLE, &handle);
40 if (rc)
41 {
42 // pldm_pdr_add() assert()ed on failure to add PDR
43 throw std::runtime_error("Failed to add PDR");
44 }
45 return handle;
George Liue53193f2020-02-24 09:23:26 +080046}
47
48const pldm_pdr_record* Repo::getFirstRecord(PdrEntry& pdrEntry)
49{
50 constexpr uint32_t firstNum = 0;
51 uint8_t* pdrData = nullptr;
Patrick Williams6da4f912023-05-10 07:50:53 -050052 auto record = pldm_pdr_find_record(getPdr(), firstNum, &pdrData,
53 &pdrEntry.size,
54 &pdrEntry.handle.nextRecordHandle);
George Liue53193f2020-02-24 09:23:26 +080055 if (record)
56 {
57 pdrEntry.data = pdrData;
58 }
59
60 return record;
61}
62
63const pldm_pdr_record* Repo::getNextRecord(const pldm_pdr_record* currRecord,
64 PdrEntry& pdrEntry)
65{
66 uint8_t* pdrData = nullptr;
Patrick Williams6da4f912023-05-10 07:50:53 -050067 auto record = pldm_pdr_get_next_record(getPdr(), currRecord, &pdrData,
68 &pdrEntry.size,
69 &pdrEntry.handle.nextRecordHandle);
George Liue53193f2020-02-24 09:23:26 +080070 if (record)
71 {
72 pdrEntry.data = pdrData;
73 }
74
75 return record;
76}
77
Deepak Kodihallic682fe22020-03-04 00:42:54 -060078uint32_t Repo::getRecordHandle(const pldm_pdr_record* record) const
George Liue53193f2020-02-24 09:23:26 +080079{
80 return pldm_pdr_get_record_handle(getPdr(), record);
81}
82
83uint32_t Repo::getRecordCount()
84{
85 return pldm_pdr_get_record_count(getPdr());
86}
87
88bool Repo::empty()
89{
90 return !getRecordCount();
91}
92
George Liu1ec85d42020-02-12 16:05:32 +080093StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues,
94 const PossibleValues& pv)
95{
96 size_t pos = 0;
97 pldm::utils::PropertyValue value;
98 StatestoDbusVal valueMap;
99 if (dBusValues.size() != pv.size())
100 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600101 error(
102 "dBusValues size is not equal to pv size, dBusValues Size: {DBUS_VAL_SIZE}, pv Size: {PV_SIZE}",
103 "DBUS_VAL_SIZE", dBusValues.size(), "PV_SIZE", pv.size());
George Liu1ec85d42020-02-12 16:05:32 +0800104 return {};
105 }
106
107 for (auto it = dBusValues.begin(); it != dBusValues.end(); ++it, ++pos)
108 {
109 if (type == "uint8_t")
110 {
111 value = static_cast<uint8_t>(it.value());
112 }
113 else if (type == "uint16_t")
114 {
115 value = static_cast<uint16_t>(it.value());
116 }
117 else if (type == "uint32_t")
118 {
119 value = static_cast<uint32_t>(it.value());
120 }
121 else if (type == "uint64_t")
122 {
123 value = static_cast<uint64_t>(it.value());
124 }
125 else if (type == "int16_t")
126 {
127 value = static_cast<int16_t>(it.value());
128 }
129 else if (type == "int32_t")
130 {
131 value = static_cast<int32_t>(it.value());
132 }
133 else if (type == "int64_t")
134 {
135 value = static_cast<int64_t>(it.value());
136 }
137 else if (type == "bool")
138 {
139 value = static_cast<bool>(it.value());
140 }
141 else if (type == "double")
142 {
143 value = static_cast<double>(it.value());
144 }
145 else if (type == "string")
146 {
147 value = static_cast<std::string>(it.value());
148 }
149 else
150 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600151 error("Unknown D-Bus property type, TYPE={OTHER_TYPE}",
152 "OTHER_TYPE", type.c_str());
George Liu1ec85d42020-02-12 16:05:32 +0800153 return {};
154 }
155
156 valueMap.emplace(pv[pos], value);
157 }
158
159 return valueMap;
160}
161
Tom Josephb4268602020-04-17 17:20:45 +0530162std::tuple<TerminusHandle, SensorID, SensorInfo>
163 parseStateSensorPDR(const std::vector<uint8_t>& stateSensorPdr)
164{
165 auto pdr =
166 reinterpret_cast<const pldm_state_sensor_pdr*>(stateSensorPdr.data());
167 CompositeSensorStates sensors{};
168 auto statesPtr = pdr->possible_states;
169 auto compositeSensorCount = pdr->composite_sensor_count;
170
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));
193 if (compositeSensorCount)
194 {
195 statesPtr += sizeof(state_sensor_possible_states) +
196 state->possible_states_size - 1;
197 }
198 }
199
200 auto entityInfo =
201 std::make_tuple(static_cast<ContainerID>(pdr->container_id),
202 static_cast<EntityType>(pdr->entity_type),
203 static_cast<EntityInstance>(pdr->entity_instance));
Patrick Williams6da4f912023-05-10 07:50:53 -0500204 auto sensorInfo = std::make_tuple(std::move(entityInfo),
205 std::move(sensors));
Tom Josephb4268602020-04-17 17:20:45 +0530206 return std::make_tuple(pdr->terminus_handle, pdr->sensor_id,
207 std::move(sensorInfo));
208}
209
George Liu682ee182020-12-25 15:24:33 +0800210std::vector<FruRecordDataFormat> parseFruRecordTable(const uint8_t* fruData,
211 size_t fruLen)
212{
213 // Refer: DSP0257_1.0.0 Table 2
214 // 7: uint16_t(FRU Record Set Identifier), uint8_t(FRU Record Type),
215 // uint8_t(Number of FRU fields), uint8_t(Encoding Type for FRU fields),
216 // uint8_t(FRU Field Type), uint8_t(FRU Field Length)
217 if (fruLen < fruRecordDataFormatLength)
218 {
219 lg2::error("Invalid fru len: {FRULEN}", "FRULEN", fruLen);
220 return {};
221 }
222
223 std::vector<FruRecordDataFormat> frus;
224
225 size_t index = 0;
226 while (index < fruLen)
227 {
228 FruRecordDataFormat fru;
229
230 auto record = reinterpret_cast<const pldm_fru_record_data_format*>(
231 fruData + index);
232 fru.fruRSI = (int)le16toh(record->record_set_id);
233 fru.fruRecType = record->record_type;
234 fru.fruNum = record->num_fru_fields;
235 fru.fruEncodeType = record->encoding_type;
236
237 index += 5;
238
239 std::ranges::for_each(std::views::iota(0, (int)record->num_fru_fields),
240 [fruData, &fru, &index](int) {
241 auto tlv =
242 reinterpret_cast<const pldm_fru_record_tlv*>(fruData + index);
243 FruTLV frutlv;
244 frutlv.fruFieldType = tlv->type;
245 frutlv.fruFieldLen = tlv->length;
246 frutlv.fruFieldValue.resize(tlv->length);
247 for (const auto& i : std::views::iota(0, (int)tlv->length))
248 {
249 memcpy(frutlv.fruFieldValue.data() + i, tlv->value + i, 1);
250 }
251 fru.fruTLV.push_back(frutlv);
252
253 // 2: 1byte FRU Field Type, 1byte FRU Field Length
254 index += fruFieldTypeLength + (unsigned)tlv->length;
255 });
256
257 frus.push_back(fru);
258 }
259
260 return frus;
261}
George Liue53193f2020-02-24 09:23:26 +0800262} // namespace pdr_utils
263} // namespace responder
264} // namespace pldm