1 #include "pdr.hpp"
2 
3 #include <libpldm/platform.h>
4 
5 #include <phosphor-logging/lg2.hpp>
6 
7 #include <climits>
8 
9 PHOSPHOR_LOG2_USING;
10 
11 using namespace pldm::pdr;
12 
13 namespace pldm
14 {
15 namespace responder
16 {
17 namespace pdr_utils
18 {
19 pldm_pdr* Repo::getPdr() const
20 {
21     return repo;
22 }
23 
24 RecordHandle Repo::addRecord(const PdrEntry& pdrEntry)
25 {
26     uint32_t handle = pdrEntry.handle.recordHandle;
27     int rc = pldm_pdr_add_check(repo, pdrEntry.data, pdrEntry.size, false,
28                                 TERMINUS_HANDLE, &handle);
29     if (rc)
30     {
31         // pldm_pdr_add() assert()ed on failure to add PDR
32         throw std::runtime_error("Failed to add PDR");
33     }
34     return handle;
35 }
36 
37 const pldm_pdr_record* Repo::getFirstRecord(PdrEntry& pdrEntry)
38 {
39     constexpr uint32_t firstNum = 0;
40     uint8_t* pdrData = nullptr;
41     auto record = pldm_pdr_find_record(getPdr(), firstNum, &pdrData,
42                                        &pdrEntry.size,
43                                        &pdrEntry.handle.nextRecordHandle);
44     if (record)
45     {
46         pdrEntry.data = pdrData;
47     }
48 
49     return record;
50 }
51 
52 const pldm_pdr_record* Repo::getNextRecord(const pldm_pdr_record* currRecord,
53                                            PdrEntry& pdrEntry)
54 {
55     uint8_t* pdrData = nullptr;
56     auto record = pldm_pdr_get_next_record(getPdr(), currRecord, &pdrData,
57                                            &pdrEntry.size,
58                                            &pdrEntry.handle.nextRecordHandle);
59     if (record)
60     {
61         pdrEntry.data = pdrData;
62     }
63 
64     return record;
65 }
66 
67 uint32_t Repo::getRecordHandle(const pldm_pdr_record* record) const
68 {
69     return pldm_pdr_get_record_handle(getPdr(), record);
70 }
71 
72 uint32_t Repo::getRecordCount()
73 {
74     return pldm_pdr_get_record_count(getPdr());
75 }
76 
77 bool Repo::empty()
78 {
79     return !getRecordCount();
80 }
81 
82 StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues,
83                                 const PossibleValues& pv)
84 {
85     size_t pos = 0;
86     pldm::utils::PropertyValue value;
87     StatestoDbusVal valueMap;
88     if (dBusValues.size() != pv.size())
89     {
90         error(
91             "dBusValues size is not equal to pv size, dBusValues Size: {DBUS_VAL_SIZE}, pv Size: {PV_SIZE}",
92             "DBUS_VAL_SIZE", dBusValues.size(), "PV_SIZE", pv.size());
93         return {};
94     }
95 
96     for (auto it = dBusValues.begin(); it != dBusValues.end(); ++it, ++pos)
97     {
98         if (type == "uint8_t")
99         {
100             value = static_cast<uint8_t>(it.value());
101         }
102         else if (type == "uint16_t")
103         {
104             value = static_cast<uint16_t>(it.value());
105         }
106         else if (type == "uint32_t")
107         {
108             value = static_cast<uint32_t>(it.value());
109         }
110         else if (type == "uint64_t")
111         {
112             value = static_cast<uint64_t>(it.value());
113         }
114         else if (type == "int16_t")
115         {
116             value = static_cast<int16_t>(it.value());
117         }
118         else if (type == "int32_t")
119         {
120             value = static_cast<int32_t>(it.value());
121         }
122         else if (type == "int64_t")
123         {
124             value = static_cast<int64_t>(it.value());
125         }
126         else if (type == "bool")
127         {
128             value = static_cast<bool>(it.value());
129         }
130         else if (type == "double")
131         {
132             value = static_cast<double>(it.value());
133         }
134         else if (type == "string")
135         {
136             value = static_cast<std::string>(it.value());
137         }
138         else
139         {
140             error("Unknown D-Bus property type, TYPE={OTHER_TYPE}",
141                   "OTHER_TYPE", type.c_str());
142             return {};
143         }
144 
145         valueMap.emplace(pv[pos], value);
146     }
147 
148     return valueMap;
149 }
150 
151 std::tuple<TerminusHandle, SensorID, SensorInfo>
152     parseStateSensorPDR(const std::vector<uint8_t>& stateSensorPdr)
153 {
154     auto pdr =
155         reinterpret_cast<const pldm_state_sensor_pdr*>(stateSensorPdr.data());
156     CompositeSensorStates sensors{};
157     auto statesPtr = pdr->possible_states;
158     auto compositeSensorCount = pdr->composite_sensor_count;
159 
160     while (compositeSensorCount--)
161     {
162         auto state =
163             reinterpret_cast<const state_sensor_possible_states*>(statesPtr);
164         PossibleStates possibleStates{};
165         uint8_t possibleStatesPos{};
166         auto updateStates =
167             [&possibleStates, &possibleStatesPos](const bitfield8_t& val) {
168             for (int i = 0; i < CHAR_BIT; i++)
169             {
170                 if (val.byte & (1 << i))
171                 {
172                     possibleStates.insert(possibleStatesPos * CHAR_BIT + i);
173                 }
174             }
175             possibleStatesPos++;
176         };
177         std::for_each(&state->states[0],
178                       &state->states[state->possible_states_size],
179                       updateStates);
180 
181         sensors.emplace_back(std::move(possibleStates));
182         if (compositeSensorCount)
183         {
184             statesPtr += sizeof(state_sensor_possible_states) +
185                          state->possible_states_size - 1;
186         }
187     }
188 
189     auto entityInfo =
190         std::make_tuple(static_cast<ContainerID>(pdr->container_id),
191                         static_cast<EntityType>(pdr->entity_type),
192                         static_cast<EntityInstance>(pdr->entity_instance));
193     auto sensorInfo = std::make_tuple(std::move(entityInfo),
194                                       std::move(sensors));
195     return std::make_tuple(pdr->terminus_handle, pdr->sensor_id,
196                            std::move(sensorInfo));
197 }
198 
199 } // namespace pdr_utils
200 } // namespace responder
201 } // namespace pldm
202