1 /* 2 // Copyright (c) 2019 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #pragma once 18 #include <boost/container/flat_map.hpp> 19 #include <ipmi_to_redfish_hooks.hpp> 20 21 namespace intel_oem::ipmi::sel::redfish_hooks::me 22 { 23 enum class EventSensor 24 { 25 MeFirmwareHealth = 23 26 }; 27 28 enum class HealthEventType 29 { 30 FirmwareStatus = 0x00, 31 SmbusLinkFailure = 0x01 32 }; 33 34 bool messageHook(const SELData& selData, const std::string& ipmiRaw); 35 36 namespace utils 37 { 38 // Maps event byte to human-readable message 39 using MessageMap = boost::container::flat_map<uint8_t, std::string>; 40 // Function which performs custom decoding for complex structures 41 using ParserFunc = std::function<bool(const SELData& selData, std::string&, 42 std::vector<std::string>&)>; 43 /** 44 * @brief Generic function for parsing IPMI Platform Events 45 * 46 * @param[in] map - maps EventData2 byte of IPMI Platform Event to decoder 47 * @param[in] selData - IPMI Platform Event 48 * @param[out] eventId - resulting Redfish Event ID 49 * @param[out] args - resulting Redfish Event Parameters 50 * 51 * @returns If matching event was found 52 */ 53 static inline bool genericMessageHook( 54 const boost::container::flat_map< 55 uint8_t, 56 std::pair<std::string, 57 std::optional<std::variant<ParserFunc, MessageMap>>>>& map, 58 const SELData& selData, std::string& eventId, 59 std::vector<std::string>& args) 60 { 61 const auto match = map.find(selData.eventData2); 62 if (match == map.end()) 63 { 64 return false; 65 } 66 67 eventId = match->second.first; 68 69 auto details = match->second.second; 70 if (details) 71 { 72 if (std::holds_alternative<MessageMap>(*details)) 73 { 74 const auto& detailsMap = std::get<MessageMap>(*details); 75 const auto translation = detailsMap.find(selData.eventData3); 76 if (translation == detailsMap.end()) 77 { 78 return false; 79 } 80 81 args.push_back(translation->second); 82 } 83 else if (std::holds_alternative<ParserFunc>(*details)) 84 { 85 const auto& parser = std::get<ParserFunc>(*details); 86 return parser(selData, eventId, args); 87 } 88 else 89 { 90 return false; 91 } 92 } 93 94 return true; 95 } 96 97 static inline std::string toHex(uint8_t byte) 98 { 99 std::stringstream ss; 100 ss << "0x" << std::hex << std::uppercase << std::setfill('0') 101 << std::setw(2) << static_cast<int>(byte); 102 return ss.str(); 103 } 104 105 template <int idx> 106 static inline bool 107 logByte(const SELData& selData, std::string& /* unused */, 108 std::vector<std::string>& args, 109 std::function<std::string(uint8_t)> conversion = nullptr) 110 { 111 uint8_t byte; 112 switch (idx) 113 { 114 case 0: 115 byte = selData.offset; 116 break; 117 118 case 1: 119 byte = selData.eventData2; 120 break; 121 122 case 2: 123 byte = selData.eventData3; 124 break; 125 126 default: 127 return false; 128 break; 129 } 130 131 if (conversion) 132 { 133 args.push_back(conversion(byte)); 134 } 135 else 136 { 137 args.push_back(std::to_string(byte)); 138 } 139 140 return true; 141 } 142 143 template <int idx> 144 static inline bool logByteDec(const SELData& selData, std::string& unused, 145 std::vector<std::string>& args) 146 { 147 return logByte<idx>(selData, unused, args); 148 } 149 150 template <int idx> 151 static inline bool logByteHex(const SELData& selData, std::string& unused, 152 std::vector<std::string>& args) 153 { 154 return logByte<idx>(selData, unused, args, toHex); 155 } 156 157 static inline void storeRedfishEvent(const std::string& ipmiRaw, 158 const std::string& eventId, 159 const std::vector<std::string>& args) 160 { 161 static constexpr std::string_view openBMCMessageRegistryVer = "0.1"; 162 std::string messageID = 163 "OpenBMC." + std::string(openBMCMessageRegistryVer) + "." + eventId; 164 165 // Log the Redfish message to the journal with the appropriate metadata 166 std::string journalMsg = "ME Event: " + ipmiRaw; 167 if (args.empty()) 168 { 169 phosphor::logging::log<phosphor::logging::level::INFO>( 170 journalMsg.c_str(), 171 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", 172 messageID.c_str())); 173 } 174 else 175 { 176 std::string argsStr = boost::algorithm::join(args, ","); 177 phosphor::logging::log<phosphor::logging::level::INFO>( 178 journalMsg.c_str(), 179 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", 180 messageID.c_str()), 181 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s", 182 argsStr.c_str())); 183 } 184 } 185 } // namespace utils 186 } // namespace intel_oem::ipmi::sel::redfish_hooks::me 187