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