blob: 1dac2e59b51a3cb97269ddbe22b118a69e99ab9e [file] [log] [blame]
George Liu83409572019-12-24 18:42:54 +08001#include "utils.hpp"
2
George Liu6492f522020-06-16 10:34:05 +08003#include "libpldm/pdr.h"
4#include "libpldm/pldm_types.h"
5
6#include <xyz/openbmc_project/Common/error.hpp>
7
George Liu83409572019-12-24 18:42:54 +08008#include <array>
9#include <ctime>
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050010#include <fstream>
George Liu83409572019-12-24 18:42:54 +080011#include <iostream>
12#include <map>
George Liu83409572019-12-24 18:42:54 +080013#include <stdexcept>
14#include <string>
15#include <vector>
Pavithra Barithaya0f74c982020-04-27 02:17:10 -050016
George Liu83409572019-12-24 18:42:54 +080017namespace pldm
18{
19namespace utils
20{
21
22constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
23constexpr auto mapperPath = "/xyz/openbmc_project/object_mapper";
24constexpr auto mapperInterface = "xyz.openbmc_project.ObjectMapper";
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050025constexpr auto eidPath = "/usr/share/pldm/host_eid";
26
Pavithra Barithaya0f74c982020-04-27 02:17:10 -050027std::vector<std::vector<uint8_t>> findStateEffecterPDR(uint8_t /*tid*/,
28 uint16_t entityID,
29 uint16_t stateSetId,
30 const pldm_pdr* repo)
31{
32 uint8_t* outData = nullptr;
33 uint32_t size{};
34 const pldm_pdr_record* record{};
35 std::vector<std::vector<uint8_t>> pdrs;
36 try
37 {
38 do
39 {
40 record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_EFFECTER_PDR,
41 record, &outData, &size);
42 if (record)
43 {
44 auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(outData);
45 auto compositeEffecterCount = pdr->composite_effecter_count;
Chicago Duana7aacc32020-06-10 18:03:38 +080046 auto possible_states_start = pdr->possible_states;
Pavithra Barithaya0f74c982020-04-27 02:17:10 -050047
48 for (auto effecters = 0x00; effecters < compositeEffecterCount;
49 effecters++)
50 {
51 auto possibleStates =
52 reinterpret_cast<state_effecter_possible_states*>(
Chicago Duana7aacc32020-06-10 18:03:38 +080053 possible_states_start);
Pavithra Barithaya0f74c982020-04-27 02:17:10 -050054 auto setId = possibleStates->state_set_id;
55 auto possibleStateSize =
56 possibleStates->possible_states_size;
57
58 if (pdr->entity_type == entityID && setId == stateSetId)
59 {
60 std::vector<uint8_t> effecter_pdr(&outData[0],
61 &outData[size]);
62 pdrs.emplace_back(std::move(effecter_pdr));
63 break;
64 }
Chicago Duana7aacc32020-06-10 18:03:38 +080065 possible_states_start += possibleStateSize + sizeof(setId) +
66 sizeof(possibleStateSize);
Pavithra Barithaya0f74c982020-04-27 02:17:10 -050067 }
68 }
69
70 } while (record);
71 }
72 catch (const std::exception& e)
73 {
74 std::cerr << " Failed to obtain a record. ERROR =" << e.what()
75 << std::endl;
76 }
77
78 return pdrs;
79}
80
Chicago Duan738e4d82020-05-28 16:39:19 +080081std::vector<std::vector<uint8_t>> findStateSensorPDR(uint8_t /*tid*/,
82 uint16_t entityID,
83 uint16_t stateSetId,
84 const pldm_pdr* repo)
85{
86 uint8_t* outData = nullptr;
87 uint32_t size{};
88 const pldm_pdr_record* record{};
89 std::vector<std::vector<uint8_t>> pdrs;
90 try
91 {
92 do
93 {
94 record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_SENSOR_PDR,
95 record, &outData, &size);
96 if (record)
97 {
98 auto pdr = reinterpret_cast<pldm_state_sensor_pdr*>(outData);
99 auto compositeSensorCount = pdr->composite_sensor_count;
Chicago Duana7aacc32020-06-10 18:03:38 +0800100 auto possible_states_start = pdr->possible_states;
Chicago Duan738e4d82020-05-28 16:39:19 +0800101
102 for (auto sensors = 0x00; sensors < compositeSensorCount;
103 sensors++)
104 {
105 auto possibleStates =
106 reinterpret_cast<state_sensor_possible_states*>(
Chicago Duana7aacc32020-06-10 18:03:38 +0800107 possible_states_start);
Chicago Duan738e4d82020-05-28 16:39:19 +0800108 auto setId = possibleStates->state_set_id;
109 auto possibleStateSize =
110 possibleStates->possible_states_size;
111
112 if (pdr->entity_type == entityID && setId == stateSetId)
113 {
114 std::vector<uint8_t> sensor_pdr(&outData[0],
115 &outData[size]);
116 pdrs.emplace_back(std::move(sensor_pdr));
117 break;
118 }
Chicago Duana7aacc32020-06-10 18:03:38 +0800119 possible_states_start += possibleStateSize + sizeof(setId) +
120 sizeof(possibleStateSize);
Chicago Duan738e4d82020-05-28 16:39:19 +0800121 }
122 }
123
124 } while (record);
125 }
126 catch (const std::exception& e)
127 {
128 std::cerr << " Failed to obtain a record. ERROR =" << e.what()
129 << std::endl;
130 }
131
132 return pdrs;
133}
134
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500135uint8_t readHostEID()
136{
137 uint8_t eid{};
138 std::ifstream eidFile{eidPath};
139 if (!eidFile.good())
140 {
141 std::cerr << "Could not open host EID file"
142 << "\n";
143 }
144 else
145 {
146 std::string eidStr;
147 eidFile >> eidStr;
148 if (!eidStr.empty())
149 {
150 eid = atoi(eidStr.c_str());
151 }
152 else
153 {
154 std::cerr << "Host EID file was empty"
155 << "\n";
156 }
157 }
158
159 return eid;
160}
George Liu83409572019-12-24 18:42:54 +0800161
162uint8_t getNumPadBytes(uint32_t data)
163{
164 uint8_t pad;
165 pad = ((data % 4) ? (4 - data % 4) : 0);
166 return pad;
167} // end getNumPadBytes
168
169bool uintToDate(uint64_t data, uint16_t* year, uint8_t* month, uint8_t* day,
170 uint8_t* hour, uint8_t* min, uint8_t* sec)
171{
172 constexpr uint64_t max_data = 29991231115959;
173 constexpr uint64_t min_data = 19700101000000;
174 if (data < min_data || data > max_data)
175 {
176 return false;
177 }
178
179 *year = data / 10000000000;
180 data = data % 10000000000;
181 *month = data / 100000000;
182 data = data % 100000000;
183 *day = data / 1000000;
184 data = data % 1000000;
185 *hour = data / 10000;
186 data = data % 10000;
187 *min = data / 100;
188 *sec = data % 100;
189
190 return true;
191}
192
George Liuba4c1fb2020-02-05 14:13:30 +0800193std::optional<std::vector<set_effecter_state_field>>
194 parseEffecterData(const std::vector<uint8_t>& effecterData,
195 uint8_t effecterCount)
George Liu83409572019-12-24 18:42:54 +0800196{
George Liuba4c1fb2020-02-05 14:13:30 +0800197 std::vector<set_effecter_state_field> stateField;
198
199 if (effecterData.size() != effecterCount * 2)
George Liu83409572019-12-24 18:42:54 +0800200 {
George Liuba4c1fb2020-02-05 14:13:30 +0800201 return std::nullopt;
George Liu83409572019-12-24 18:42:54 +0800202 }
203
George Liuba4c1fb2020-02-05 14:13:30 +0800204 for (uint8_t i = 0; i < effecterCount; ++i)
George Liu83409572019-12-24 18:42:54 +0800205 {
George Liuba4c1fb2020-02-05 14:13:30 +0800206 uint8_t set_request = effecterData[i * 2] == PLDM_REQUEST_SET
207 ? PLDM_REQUEST_SET
208 : PLDM_NO_CHANGE;
209 set_effecter_state_field filed{set_request, effecterData[i * 2 + 1]};
210 stateField.emplace_back(std::move(filed));
George Liu83409572019-12-24 18:42:54 +0800211 }
212
George Liuba4c1fb2020-02-05 14:13:30 +0800213 return std::make_optional(std::move(stateField));
George Liu83409572019-12-24 18:42:54 +0800214}
215
George Liu0e02c322020-01-01 09:41:51 +0800216std::string DBusHandler::getService(const char* path,
217 const char* interface) const
George Liu83409572019-12-24 18:42:54 +0800218{
219 using DbusInterfaceList = std::vector<std::string>;
220 std::map<std::string, std::vector<std::string>> mapperResponse;
George Liu0e02c322020-01-01 09:41:51 +0800221 auto& bus = DBusHandler::getBus();
George Liu83409572019-12-24 18:42:54 +0800222
George Liu0e02c322020-01-01 09:41:51 +0800223 auto mapper = bus.new_method_call(mapperBusName, mapperPath,
224 mapperInterface, "GetObject");
225 mapper.append(path, DbusInterfaceList({interface}));
George Liu83409572019-12-24 18:42:54 +0800226
George Liu0e02c322020-01-01 09:41:51 +0800227 auto mapperResponseMsg = bus.call(mapper);
228 mapperResponseMsg.read(mapperResponse);
George Liu83409572019-12-24 18:42:54 +0800229 return mapperResponse.begin()->first;
230}
231
232void reportError(const char* errorMsg)
233{
234 static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
235 static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";
236
George Liu0e02c322020-01-01 09:41:51 +0800237 auto& bus = pldm::utils::DBusHandler::getBus();
George Liu83409572019-12-24 18:42:54 +0800238
239 try
240 {
George Liu0e02c322020-01-01 09:41:51 +0800241 auto service = DBusHandler().getService(logObjPath, logInterface);
George Liu83409572019-12-24 18:42:54 +0800242 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
243 auto severity =
244 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
245 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
246 Error);
247 auto method = bus.new_method_call(service.c_str(), logObjPath,
248 logInterface, "Create");
249 std::map<std::string, std::string> addlData{};
250 method.append(errorMsg, severity, addlData);
251 bus.call_noreply(method);
252 }
253 catch (const std::exception& e)
254 {
255 std::cerr << "failed to make a d-bus call to create error log, ERROR="
256 << e.what() << "\n";
257 }
258}
259
George Liu1e44c732020-02-28 20:20:06 +0800260void DBusHandler::setDbusProperty(const DBusMapping& dBusMap,
261 const PropertyValue& value) const
262{
263 auto setDbusValue = [&dBusMap, this](const auto& variant) {
264 auto& bus = getBus();
265 auto service =
266 getService(dBusMap.objectPath.c_str(), dBusMap.interface.c_str());
267 auto method = bus.new_method_call(
268 service.c_str(), dBusMap.objectPath.c_str(), dbusProperties, "Set");
269 method.append(dBusMap.interface.c_str(), dBusMap.propertyName.c_str(),
270 variant);
271 bus.call_noreply(method);
272 };
273
274 if (dBusMap.propertyType == "uint8_t")
275 {
276 std::variant<uint8_t> v = std::get<uint8_t>(value);
277 setDbusValue(v);
278 }
Deepak Kodihallifd279e12020-02-02 05:20:43 -0600279 else if (dBusMap.propertyType == "bool")
280 {
281 std::variant<bool> v = std::get<bool>(value);
282 setDbusValue(v);
283 }
George Liu1e44c732020-02-28 20:20:06 +0800284 else if (dBusMap.propertyType == "int16_t")
285 {
286 std::variant<int16_t> v = std::get<int16_t>(value);
287 setDbusValue(v);
288 }
289 else if (dBusMap.propertyType == "uint16_t")
290 {
291 std::variant<uint16_t> v = std::get<uint16_t>(value);
292 setDbusValue(v);
293 }
294 else if (dBusMap.propertyType == "int32_t")
295 {
296 std::variant<int32_t> v = std::get<int32_t>(value);
297 setDbusValue(v);
298 }
299 else if (dBusMap.propertyType == "uint32_t")
300 {
301 std::variant<uint32_t> v = std::get<uint32_t>(value);
302 setDbusValue(v);
303 }
304 else if (dBusMap.propertyType == "int64_t")
305 {
306 std::variant<int64_t> v = std::get<int64_t>(value);
307 setDbusValue(v);
308 }
309 else if (dBusMap.propertyType == "uint64_t")
310 {
311 std::variant<uint64_t> v = std::get<uint64_t>(value);
312 setDbusValue(v);
313 }
314 else if (dBusMap.propertyType == "double")
315 {
316 std::variant<double> v = std::get<double>(value);
317 setDbusValue(v);
318 }
319 else if (dBusMap.propertyType == "string")
320 {
321 std::variant<std::string> v = std::get<std::string>(value);
322 setDbusValue(v);
323 }
324 else
325 {
326 throw std::invalid_argument("UnSpported Dbus Type");
327 }
328}
329
John Wang9e242422020-03-05 08:37:50 +0800330PropertyValue DBusHandler::getDbusPropertyVariant(
331 const char* objPath, const char* dbusProp, const char* dbusInterface) const
332{
333 auto& bus = DBusHandler::getBus();
334 auto service = getService(objPath, dbusInterface);
335 auto method =
336 bus.new_method_call(service.c_str(), objPath, dbusProperties, "Get");
337 method.append(dbusInterface, dbusProp);
338 PropertyValue value{};
339 auto reply = bus.call(method);
340 reply.read(value);
341 return value;
342}
343
TOM JOSEPHd4d97a52020-03-23 14:36:34 +0530344PropertyValue jsonEntryToDbusVal(std::string_view type,
345 const nlohmann::json& value)
346{
347 PropertyValue propValue{};
348 if (type == "uint8_t")
349 {
350 propValue = static_cast<uint8_t>(value);
351 }
352 else if (type == "uint16_t")
353 {
354 propValue = static_cast<uint16_t>(value);
355 }
356 else if (type == "uint32_t")
357 {
358 propValue = static_cast<uint32_t>(value);
359 }
360 else if (type == "uint64_t")
361 {
362 propValue = static_cast<uint64_t>(value);
363 }
364 else if (type == "int16_t")
365 {
366 propValue = static_cast<int16_t>(value);
367 }
368 else if (type == "int32_t")
369 {
370 propValue = static_cast<int32_t>(value);
371 }
372 else if (type == "int64_t")
373 {
374 propValue = static_cast<int64_t>(value);
375 }
376 else if (type == "bool")
377 {
378 propValue = static_cast<bool>(value);
379 }
380 else if (type == "double")
381 {
382 propValue = static_cast<double>(value);
383 }
384 else if (type == "string")
385 {
386 propValue = static_cast<std::string>(value);
387 }
388 else
389 {
390 std::cerr << "Unknown D-Bus property type, TYPE=" << type << "\n";
391 }
392
393 return propValue;
394}
395
Tom Joseph250c4752020-04-15 10:32:45 +0530396uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType,
397 uint16_t entityInstance, uint16_t containerId,
398 uint16_t stateSetId)
399{
400 uint8_t* pdrData = nullptr;
401 uint32_t pdrSize{};
402 const pldm_pdr_record* record{};
403 do
404 {
405 record = pldm_pdr_find_record_by_type(pdrRepo, PLDM_STATE_EFFECTER_PDR,
406 record, &pdrData, &pdrSize);
407 if (record)
408 {
409 auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrData);
410 auto compositeEffecterCount = pdr->composite_effecter_count;
411 auto possible_states_start = pdr->possible_states;
412
413 for (auto effecters = 0x00; effecters < compositeEffecterCount;
414 effecters++)
415 {
416 auto possibleStates =
417 reinterpret_cast<state_effecter_possible_states*>(
418 possible_states_start);
419 auto setId = possibleStates->state_set_id;
420 auto possibleStateSize = possibleStates->possible_states_size;
421
422 if (entityType == pdr->entity_type &&
423 entityInstance == pdr->entity_instance &&
424 containerId == pdr->container_id && stateSetId == setId)
425 {
426 return pdr->effecter_id;
427 }
428 possible_states_start += possibleStateSize + sizeof(setId) +
429 sizeof(possibleStateSize);
430 }
431 }
432 } while (record);
433
434 return PLDM_INVALID_EFFECTER_ID;
435}
436
Chicago Duanfe4d88b2020-06-12 16:44:13 +0800437int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId,
438 uint8_t sensorOffset, uint8_t eventState,
439 uint8_t previousEventState)
440{
441 try
442 {
443 auto& bus = DBusHandler::getBus();
444 auto msg = bus.new_signal("/xyz/openbmc_project/pldm",
445 "xyz.openbmc_project.PLDM.Event",
446 "StateSensorEvent");
447 msg.append(tid, sensorId, sensorOffset, eventState, previousEventState);
448
449 msg.signal_send();
450 }
451 catch (std::exception& e)
452 {
453 std::cerr << "Error emitting pldm event signal:"
454 << "ERROR=" << e.what() << "\n";
455 return PLDM_ERROR;
456 }
457
458 return PLDM_SUCCESS;
459}
460
George Liu83409572019-12-24 18:42:54 +0800461} // namespace utils
462} // namespace pldm