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 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 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 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