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