blob: 27fda0335c8d3fd6d39df1c438115a831ea2a159 [file] [log] [blame]
George Liu83409572019-12-24 18:42:54 +08001#include "utils.hpp"
2
3#include <array>
4#include <ctime>
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05005#include <fstream>
George Liu83409572019-12-24 18:42:54 +08006#include <iostream>
7#include <map>
George Liu83409572019-12-24 18:42:54 +08008#include <stdexcept>
9#include <string>
10#include <vector>
11#include <xyz/openbmc_project/Common/error.hpp>
12
Pavithra Barithaya0f74c982020-04-27 02:17:10 -050013#include "libpldm/pdr.h"
14#include "libpldm/pldm_types.h"
15
George Liu83409572019-12-24 18:42:54 +080016namespace pldm
17{
18namespace utils
19{
20
21constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
22constexpr auto mapperPath = "/xyz/openbmc_project/object_mapper";
23constexpr auto mapperInterface = "xyz.openbmc_project.ObjectMapper";
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050024constexpr auto eidPath = "/usr/share/pldm/host_eid";
25
Pavithra Barithaya0f74c982020-04-27 02:17:10 -050026std::vector<std::vector<uint8_t>> findStateEffecterPDR(uint8_t /*tid*/,
27 uint16_t entityID,
28 uint16_t stateSetId,
29 const pldm_pdr* repo)
30{
31 uint8_t* outData = nullptr;
32 uint32_t size{};
33 const pldm_pdr_record* record{};
34 std::vector<std::vector<uint8_t>> pdrs;
35 try
36 {
37 do
38 {
39 record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_EFFECTER_PDR,
40 record, &outData, &size);
41 if (record)
42 {
43 auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(outData);
44 auto compositeEffecterCount = pdr->composite_effecter_count;
45
46 for (auto effecters = 0x00; effecters < compositeEffecterCount;
47 effecters++)
48 {
49 auto possibleStates =
50 reinterpret_cast<state_effecter_possible_states*>(
51 pdr->possible_states);
52 auto setId = possibleStates->state_set_id;
53 auto possibleStateSize =
54 possibleStates->possible_states_size;
55
56 if (pdr->entity_type == entityID && setId == stateSetId)
57 {
58 std::vector<uint8_t> effecter_pdr(&outData[0],
59 &outData[size]);
60 pdrs.emplace_back(std::move(effecter_pdr));
61 break;
62 }
63 possibleStates += possibleStateSize + sizeof(setId) +
64 sizeof(possibleStateSize);
65 }
66 }
67
68 } while (record);
69 }
70 catch (const std::exception& e)
71 {
72 std::cerr << " Failed to obtain a record. ERROR =" << e.what()
73 << std::endl;
74 }
75
76 return pdrs;
77}
78
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050079uint8_t readHostEID()
80{
81 uint8_t eid{};
82 std::ifstream eidFile{eidPath};
83 if (!eidFile.good())
84 {
85 std::cerr << "Could not open host EID file"
86 << "\n";
87 }
88 else
89 {
90 std::string eidStr;
91 eidFile >> eidStr;
92 if (!eidStr.empty())
93 {
94 eid = atoi(eidStr.c_str());
95 }
96 else
97 {
98 std::cerr << "Host EID file was empty"
99 << "\n";
100 }
101 }
102
103 return eid;
104}
George Liu83409572019-12-24 18:42:54 +0800105
106uint8_t getNumPadBytes(uint32_t data)
107{
108 uint8_t pad;
109 pad = ((data % 4) ? (4 - data % 4) : 0);
110 return pad;
111} // end getNumPadBytes
112
113bool uintToDate(uint64_t data, uint16_t* year, uint8_t* month, uint8_t* day,
114 uint8_t* hour, uint8_t* min, uint8_t* sec)
115{
116 constexpr uint64_t max_data = 29991231115959;
117 constexpr uint64_t min_data = 19700101000000;
118 if (data < min_data || data > max_data)
119 {
120 return false;
121 }
122
123 *year = data / 10000000000;
124 data = data % 10000000000;
125 *month = data / 100000000;
126 data = data % 100000000;
127 *day = data / 1000000;
128 data = data % 1000000;
129 *hour = data / 10000;
130 data = data % 10000;
131 *min = data / 100;
132 *sec = data % 100;
133
134 return true;
135}
136
George Liuba4c1fb2020-02-05 14:13:30 +0800137std::optional<std::vector<set_effecter_state_field>>
138 parseEffecterData(const std::vector<uint8_t>& effecterData,
139 uint8_t effecterCount)
George Liu83409572019-12-24 18:42:54 +0800140{
George Liuba4c1fb2020-02-05 14:13:30 +0800141 std::vector<set_effecter_state_field> stateField;
142
143 if (effecterData.size() != effecterCount * 2)
George Liu83409572019-12-24 18:42:54 +0800144 {
George Liuba4c1fb2020-02-05 14:13:30 +0800145 return std::nullopt;
George Liu83409572019-12-24 18:42:54 +0800146 }
147
George Liuba4c1fb2020-02-05 14:13:30 +0800148 for (uint8_t i = 0; i < effecterCount; ++i)
George Liu83409572019-12-24 18:42:54 +0800149 {
George Liuba4c1fb2020-02-05 14:13:30 +0800150 uint8_t set_request = effecterData[i * 2] == PLDM_REQUEST_SET
151 ? PLDM_REQUEST_SET
152 : PLDM_NO_CHANGE;
153 set_effecter_state_field filed{set_request, effecterData[i * 2 + 1]};
154 stateField.emplace_back(std::move(filed));
George Liu83409572019-12-24 18:42:54 +0800155 }
156
George Liuba4c1fb2020-02-05 14:13:30 +0800157 return std::make_optional(std::move(stateField));
George Liu83409572019-12-24 18:42:54 +0800158}
159
George Liu0e02c322020-01-01 09:41:51 +0800160std::string DBusHandler::getService(const char* path,
161 const char* interface) const
George Liu83409572019-12-24 18:42:54 +0800162{
163 using DbusInterfaceList = std::vector<std::string>;
164 std::map<std::string, std::vector<std::string>> mapperResponse;
George Liu0e02c322020-01-01 09:41:51 +0800165 auto& bus = DBusHandler::getBus();
George Liu83409572019-12-24 18:42:54 +0800166
George Liu0e02c322020-01-01 09:41:51 +0800167 auto mapper = bus.new_method_call(mapperBusName, mapperPath,
168 mapperInterface, "GetObject");
169 mapper.append(path, DbusInterfaceList({interface}));
George Liu83409572019-12-24 18:42:54 +0800170
George Liu0e02c322020-01-01 09:41:51 +0800171 auto mapperResponseMsg = bus.call(mapper);
172 mapperResponseMsg.read(mapperResponse);
George Liu83409572019-12-24 18:42:54 +0800173 return mapperResponse.begin()->first;
174}
175
176void reportError(const char* errorMsg)
177{
178 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
179 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
180
George Liu0e02c322020-01-01 09:41:51 +0800181 auto& bus = pldm::utils::DBusHandler::getBus();
George Liu83409572019-12-24 18:42:54 +0800182
183 try
184 {
George Liu0e02c322020-01-01 09:41:51 +0800185 auto service = DBusHandler().getService(logObjPath, logInterface);
George Liu83409572019-12-24 18:42:54 +0800186 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
187 auto severity =
188 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
189 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
190 Error);
191 auto method = bus.new_method_call(service.c_str(), logObjPath,
192 logInterface, "Create");
193 std::map<std::string, std::string> addlData{};
194 method.append(errorMsg, severity, addlData);
195 bus.call_noreply(method);
196 }
197 catch (const std::exception& e)
198 {
199 std::cerr << "failed to make a d-bus call to create error log, ERROR="
200 << e.what() << "\n";
201 }
202}
203
George Liu1e44c732020-02-28 20:20:06 +0800204void DBusHandler::setDbusProperty(const DBusMapping& dBusMap,
205 const PropertyValue& value) const
206{
207 auto setDbusValue = [&dBusMap, this](const auto& variant) {
208 auto& bus = getBus();
209 auto service =
210 getService(dBusMap.objectPath.c_str(), dBusMap.interface.c_str());
211 auto method = bus.new_method_call(
212 service.c_str(), dBusMap.objectPath.c_str(), dbusProperties, "Set");
213 method.append(dBusMap.interface.c_str(), dBusMap.propertyName.c_str(),
214 variant);
215 bus.call_noreply(method);
216 };
217
218 if (dBusMap.propertyType == "uint8_t")
219 {
220 std::variant<uint8_t> v = std::get<uint8_t>(value);
221 setDbusValue(v);
222 }
Deepak Kodihallifd279e12020-02-02 05:20:43 -0600223 else if (dBusMap.propertyType == "bool")
224 {
225 std::variant<bool> v = std::get<bool>(value);
226 setDbusValue(v);
227 }
George Liu1e44c732020-02-28 20:20:06 +0800228 else if (dBusMap.propertyType == "int16_t")
229 {
230 std::variant<int16_t> v = std::get<int16_t>(value);
231 setDbusValue(v);
232 }
233 else if (dBusMap.propertyType == "uint16_t")
234 {
235 std::variant<uint16_t> v = std::get<uint16_t>(value);
236 setDbusValue(v);
237 }
238 else if (dBusMap.propertyType == "int32_t")
239 {
240 std::variant<int32_t> v = std::get<int32_t>(value);
241 setDbusValue(v);
242 }
243 else if (dBusMap.propertyType == "uint32_t")
244 {
245 std::variant<uint32_t> v = std::get<uint32_t>(value);
246 setDbusValue(v);
247 }
248 else if (dBusMap.propertyType == "int64_t")
249 {
250 std::variant<int64_t> v = std::get<int64_t>(value);
251 setDbusValue(v);
252 }
253 else if (dBusMap.propertyType == "uint64_t")
254 {
255 std::variant<uint64_t> v = std::get<uint64_t>(value);
256 setDbusValue(v);
257 }
258 else if (dBusMap.propertyType == "double")
259 {
260 std::variant<double> v = std::get<double>(value);
261 setDbusValue(v);
262 }
263 else if (dBusMap.propertyType == "string")
264 {
265 std::variant<std::string> v = std::get<std::string>(value);
266 setDbusValue(v);
267 }
268 else
269 {
270 throw std::invalid_argument("UnSpported Dbus Type");
271 }
272}
273
John Wang9e242422020-03-05 08:37:50 +0800274PropertyValue DBusHandler::getDbusPropertyVariant(
275 const char* objPath, const char* dbusProp, const char* dbusInterface) const
276{
277 auto& bus = DBusHandler::getBus();
278 auto service = getService(objPath, dbusInterface);
279 auto method =
280 bus.new_method_call(service.c_str(), objPath, dbusProperties, "Get");
281 method.append(dbusInterface, dbusProp);
282 PropertyValue value{};
283 auto reply = bus.call(method);
284 reply.read(value);
285 return value;
286}
287
TOM JOSEPHd4d97a52020-03-23 14:36:34 +0530288PropertyValue jsonEntryToDbusVal(std::string_view type,
289 const nlohmann::json& value)
290{
291 PropertyValue propValue{};
292 if (type == "uint8_t")
293 {
294 propValue = static_cast<uint8_t>(value);
295 }
296 else if (type == "uint16_t")
297 {
298 propValue = static_cast<uint16_t>(value);
299 }
300 else if (type == "uint32_t")
301 {
302 propValue = static_cast<uint32_t>(value);
303 }
304 else if (type == "uint64_t")
305 {
306 propValue = static_cast<uint64_t>(value);
307 }
308 else if (type == "int16_t")
309 {
310 propValue = static_cast<int16_t>(value);
311 }
312 else if (type == "int32_t")
313 {
314 propValue = static_cast<int32_t>(value);
315 }
316 else if (type == "int64_t")
317 {
318 propValue = static_cast<int64_t>(value);
319 }
320 else if (type == "bool")
321 {
322 propValue = static_cast<bool>(value);
323 }
324 else if (type == "double")
325 {
326 propValue = static_cast<double>(value);
327 }
328 else if (type == "string")
329 {
330 propValue = static_cast<std::string>(value);
331 }
332 else
333 {
334 std::cerr << "Unknown D-Bus property type, TYPE=" << type << "\n";
335 }
336
337 return propValue;
338}
339
George Liu83409572019-12-24 18:42:54 +0800340} // namespace utils
341} // namespace pldm