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 <ipmi_to_redfish_hooks.hpp> 19 20 namespace intel_oem::ipmi::sel::redfish_hooks::me 21 { 22 enum class EventSensor 23 { 24 MeFirmwareHealth = 23 25 }; 26 27 enum class HealthEventType 28 { 29 FirmwareStatus = 0x00, 30 SmbusLinkFailure = 0x01 31 }; 32 33 bool messageHook(const SELData& selData, const std::string& ipmiRaw); 34 35 namespace utils 36 { 37 // Maps event byte to human-readable message 38 using MessageMap = boost::container::flat_map<uint8_t, std::string>; 39 // Function which performs custom decoding for complex structures 40 using ParserFunc = std::function<bool(const SELData& selData, std::string&, 41 std::vector<std::string>&)>; 42 /** 43 * @brief Generic function for parsing IPMI Platform Events 44 * 45 * @param[in] map - maps EventData2 byte of IPMI Platform Event to decoder 46 * @param[in] selData - IPMI Platform Event 47 * @param[out] eventId - resulting Redfish Event ID 48 * @param[out] args - resulting Redfish Event Parameters 49 * 50 * @returns If matching event was found 51 */ 52 static inline bool genericMessageHook( 53 const boost::container::flat_map< 54 uint8_t, 55 std::pair<std::string, 56 std::optional<std::variant<ParserFunc, MessageMap>>>>& map, 57 const SELData& selData, std::string& eventId, 58 std::vector<std::string>& args) 59 { 60 const auto match = map.find(selData.eventData2); 61 if (match == map.end()) 62 { 63 return false; 64 } 65 66 eventId = match->second.first; 67 68 auto details = match->second.second; 69 if (details) 70 { 71 if (std::holds_alternative<MessageMap>(*details)) 72 { 73 const auto& detailsMap = std::get<MessageMap>(*details); 74 const auto translation = detailsMap.find(selData.eventData3); 75 if (translation == detailsMap.end()) 76 { 77 return false; 78 } 79 80 args.push_back(translation->second); 81 } 82 else if (std::holds_alternative<ParserFunc>(*details)) 83 { 84 const auto& parser = std::get<ParserFunc>(*details); 85 return parser(selData, eventId, args); 86 } 87 else 88 { 89 return false; 90 } 91 } 92 93 return true; 94 } 95 96 static inline std::string toHex(uint8_t byte) 97 { 98 std::stringstream ss; 99 ss << "0x" << std::hex << std::uppercase << std::setfill('0') 100 << std::setw(2) << static_cast<int>(byte); 101 return ss.str(); 102 } 103 104 template <int idx> 105 static inline bool 106 logByte(const SELData& selData, std::string& unused, 107 std::vector<std::string>& args, 108 std::function<std::string(uint8_t)> conversion = nullptr) 109 { 110 uint8_t byte; 111 switch (idx) 112 { 113 case 0: 114 byte = selData.offset; 115 break; 116 117 case 1: 118 byte = selData.eventData2; 119 break; 120 121 case 2: 122 byte = selData.eventData3; 123 break; 124 125 default: 126 return false; 127 break; 128 } 129 130 if (conversion) 131 { 132 args.push_back(conversion(byte)); 133 } 134 else 135 { 136 args.push_back(std::to_string(byte)); 137 } 138 139 return true; 140 } 141 142 template <int idx> 143 static inline bool logByteDec(const SELData& selData, std::string& unused, 144 std::vector<std::string>& args) 145 { 146 return logByte<idx>(selData, unused, args); 147 } 148 149 template <int idx> 150 static inline bool logByteHex(const SELData& selData, std::string& unused, 151 std::vector<std::string>& args) 152 { 153 return logByte<idx>(selData, unused, args, toHex); 154 } 155 156 static inline void storeRedfishEvent(const std::string& ipmiRaw, 157 const std::string& eventId, 158 const std::vector<std::string>& args) 159 { 160 static constexpr std::string_view openBMCMessageRegistryVer = "0.1"; 161 std::string messageID = 162 "OpenBMC." + std::string(openBMCMessageRegistryVer) + "." + eventId; 163 164 // Log the Redfish message to the journal with the appropriate metadata 165 std::string journalMsg = "ME Event: " + ipmiRaw; 166 if (args.empty()) 167 { 168 phosphor::logging::log<phosphor::logging::level::INFO>( 169 journalMsg.c_str(), 170 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", 171 messageID.c_str())); 172 } 173 else 174 { 175 std::string argsStr = boost::algorithm::join(args, ","); 176 phosphor::logging::log<phosphor::logging::level::INFO>( 177 journalMsg.c_str(), 178 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", 179 messageID.c_str()), 180 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s", 181 argsStr.c_str())); 182 } 183 } 184 } // namespace utils 185 } // namespace intel_oem::ipmi::sel::redfish_hooks::me