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