1 #include "event_parser.hpp"
2
3 #include <phosphor-logging/lg2.hpp>
4 #include <xyz/openbmc_project/Common/error.hpp>
5
6 #include <filesystem>
7 #include <fstream>
8 #include <set>
9
10 PHOSPHOR_LOG2_USING;
11
12 namespace pldm::responder::events
13 {
14 namespace fs = std::filesystem;
15 using InternalFailure =
16 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
17
18 const Json emptyJson{};
19 const std::vector<Json> emptyJsonList{};
20
21 const std::set<std::string_view> supportedDbusPropertyTypes = {
22 "bool", "uint8_t", "int16_t", "uint16_t", "int32_t",
23 "uint32_t", "int64_t", "uint64_t", "double", "string"};
24
StateSensorHandler(const std::string & dirPath)25 StateSensorHandler::StateSensorHandler(const std::string& dirPath)
26 {
27 fs::path dir(dirPath);
28 if (!fs::exists(dir) || fs::is_empty(dir))
29 {
30 error("Event config directory at '{PATH}' does not exist or empty",
31 "PATH", dirPath);
32 return;
33 }
34
35 for (auto& file : fs::directory_iterator(dirPath))
36 {
37 std::ifstream jsonFile(file.path());
38
39 auto data = Json::parse(jsonFile, nullptr, false);
40 if (data.is_discarded())
41 {
42 error("Failed to parse event state sensor JSON file at '{PATH}'",
43 "PATH", file.path());
44 continue;
45 }
46
47 auto entries = data.value("entries", emptyJsonList);
48 for (const auto& entry : entries)
49 {
50 StateSensorEntry stateSensorEntry{};
51 stateSensorEntry.containerId =
52 static_cast<uint16_t>(entry.value("containerID", 0xFFFF));
53 stateSensorEntry.entityType =
54 static_cast<uint16_t>(entry.value("entityType", 0));
55 stateSensorEntry.entityInstance =
56 static_cast<uint16_t>(entry.value("entityInstance", 0));
57 stateSensorEntry.sensorOffset =
58 static_cast<uint8_t>(entry.value("sensorOffset", 0));
59 stateSensorEntry.stateSetid =
60 static_cast<uint16_t>(entry.value("stateSetId", 0));
61
62 // container id is not found in the json
63 stateSensorEntry.skipContainerId =
64 (stateSensorEntry.containerId == 0xFFFF) ? true : false;
65
66 pldm::utils::DBusMapping dbusInfo{};
67
68 auto dbus = entry.value("dbus", emptyJson);
69 dbusInfo.objectPath = dbus.value("object_path", "");
70 dbusInfo.interface = dbus.value("interface", "");
71 dbusInfo.propertyName = dbus.value("property_name", "");
72 dbusInfo.propertyType = dbus.value("property_type", "");
73 if (dbusInfo.objectPath.empty() || dbusInfo.interface.empty() ||
74 dbusInfo.propertyName.empty() ||
75 !supportedDbusPropertyTypes.contains(dbusInfo.propertyType))
76 {
77 error(
78 "Invalid dbus config at '{PATH}', interface '{DBUS_INTERFACE}', property name '{PROPERTY_NAME}' and property type '{PROPERTY_TYPE}'",
79 "PATH", dbusInfo.objectPath, "DBUS_INTERFACE",
80 dbusInfo.interface, "PROPERTY_NAME", dbusInfo.propertyName,
81 "PROPERTY_TYPE", dbusInfo.propertyType);
82 continue;
83 }
84
85 auto eventStates = entry.value("event_states", emptyJsonList);
86 auto propertyValues = dbus.value("property_values", emptyJsonList);
87 if ((eventStates.size() == 0) || (propertyValues.size() == 0) ||
88 (eventStates.size() != propertyValues.size()))
89 {
90 error(
91 "Invalid event state JSON config size '{EVENT_STATE_SIZE}' and property value size '{PROPERTY_VALUE_SIZE}'",
92 "EVENT_STATE_SIZE", eventStates.size(),
93 "PROPERTY_VALUE_SIZE", propertyValues.size());
94 continue;
95 }
96
97 auto eventStateMap = mapStateToDBusVal(eventStates, propertyValues,
98 dbusInfo.propertyType);
99 eventMap.emplace(
100 stateSensorEntry,
101 std::make_tuple(std::move(dbusInfo), std::move(eventStateMap)));
102 }
103 }
104 }
105
mapStateToDBusVal(const Json & eventStates,const Json & propertyValues,std::string_view type)106 StateToDBusValue StateSensorHandler::mapStateToDBusVal(
107 const Json& eventStates, const Json& propertyValues, std::string_view type)
108 {
109 StateToDBusValue eventStateMap{};
110 auto stateIt = eventStates.begin();
111 auto propIt = propertyValues.begin();
112
113 for (; stateIt != eventStates.end(); ++stateIt, ++propIt)
114 {
115 auto propValue = utils::jsonEntryToDbusVal(type, propIt.value());
116 eventStateMap.emplace((*stateIt).get<uint8_t>(), std::move(propValue));
117 }
118
119 return eventStateMap;
120 }
121
eventAction(const StateSensorEntry & entry,pdr::EventState state)122 int StateSensorHandler::eventAction(const StateSensorEntry& entry,
123 pdr::EventState state)
124 {
125 try
126 {
127 const auto& [dbusMapping, eventStateMap] = eventMap.at(entry);
128 utils::PropertyValue propValue{};
129 try
130 {
131 propValue = eventStateMap.at(state);
132 }
133 catch (const std::out_of_range& e)
134 {
135 error("Invalid event state '{EVENT_STATE}', error - {ERROR}",
136 "EVENT_STATE", state, "ERROR", e);
137 return PLDM_ERROR_INVALID_DATA;
138 }
139
140 try
141 {
142 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, propValue);
143 }
144 catch (const std::exception& e)
145 {
146 error(
147 "Failed to set property '{PROPERTY}' on interface '{INTERFACE}' at path '{PATH}', error - {ERROR}",
148 "PROPERTY", dbusMapping.propertyName, "INTERFACE",
149 dbusMapping.interface, "PATH", dbusMapping.objectPath, "ERROR",
150 e);
151 return PLDM_ERROR;
152 }
153 }
154 catch (const std::out_of_range&)
155 {
156 // There is no BMC action for this PLDM event
157 return PLDM_SUCCESS;
158 }
159 return PLDM_SUCCESS;
160 }
161
162 } // namespace pldm::responder::events
163