| /* |
| // Copyright (c) 2019 Intel Corporation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| */ |
| |
| #pragma once |
| #include <boost/container/flat_map.hpp> |
| #include <ipmi_to_redfish_hooks.hpp> |
| |
| namespace intel_oem::ipmi::sel::redfish_hooks::me |
| { |
| enum class EventSensor |
| { |
| MeFirmwareHealth = 23 |
| }; |
| |
| enum class HealthEventType |
| { |
| FirmwareStatus = 0x00, |
| SmbusLinkFailure = 0x01 |
| }; |
| |
| bool messageHook(const SELData& selData, const std::string& ipmiRaw); |
| |
| namespace utils |
| { |
| // Maps event byte to human-readable message |
| using MessageMap = boost::container::flat_map<uint8_t, std::string>; |
| // Function which performs custom decoding for complex structures |
| using ParserFunc = std::function<bool(const SELData& selData, std::string&, |
| std::vector<std::string>&)>; |
| /** |
| * @brief Generic function for parsing IPMI Platform Events |
| * |
| * @param[in] map - maps EventData2 byte of IPMI Platform Event to decoder |
| * @param[in] selData - IPMI Platform Event |
| * @param[out] eventId - resulting Redfish Event ID |
| * @param[out] args - resulting Redfish Event Parameters |
| * |
| * @returns If matching event was found |
| */ |
| static inline bool genericMessageHook( |
| const boost::container::flat_map< |
| uint8_t, |
| std::pair<std::string, |
| std::optional<std::variant<ParserFunc, MessageMap>>>>& map, |
| const SELData& selData, std::string& eventId, |
| std::vector<std::string>& args) |
| { |
| const auto match = map.find(selData.eventData2); |
| if (match == map.end()) |
| { |
| return false; |
| } |
| |
| eventId = match->second.first; |
| |
| auto details = match->second.second; |
| if (details) |
| { |
| if (std::holds_alternative<MessageMap>(*details)) |
| { |
| const auto& detailsMap = std::get<MessageMap>(*details); |
| const auto translation = detailsMap.find(selData.eventData3); |
| if (translation == detailsMap.end()) |
| { |
| return false; |
| } |
| |
| args.push_back(translation->second); |
| } |
| else if (std::holds_alternative<ParserFunc>(*details)) |
| { |
| const auto& parser = std::get<ParserFunc>(*details); |
| return parser(selData, eventId, args); |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| static inline std::string toHex(uint8_t byte) |
| { |
| std::stringstream ss; |
| ss << "0x" << std::hex << std::uppercase << std::setfill('0') |
| << std::setw(2) << static_cast<int>(byte); |
| return ss.str(); |
| } |
| |
| template <int idx> |
| static inline bool |
| logByte(const SELData& selData, std::string& unused, |
| std::vector<std::string>& args, |
| std::function<std::string(uint8_t)> conversion = nullptr) |
| { |
| uint8_t byte; |
| switch (idx) |
| { |
| case 0: |
| byte = selData.offset; |
| break; |
| |
| case 1: |
| byte = selData.eventData2; |
| break; |
| |
| case 2: |
| byte = selData.eventData3; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| |
| if (conversion) |
| { |
| args.push_back(conversion(byte)); |
| } |
| else |
| { |
| args.push_back(std::to_string(byte)); |
| } |
| |
| return true; |
| } |
| |
| template <int idx> |
| static inline bool logByteDec(const SELData& selData, std::string& unused, |
| std::vector<std::string>& args) |
| { |
| return logByte<idx>(selData, unused, args); |
| } |
| |
| template <int idx> |
| static inline bool logByteHex(const SELData& selData, std::string& unused, |
| std::vector<std::string>& args) |
| { |
| return logByte<idx>(selData, unused, args, toHex); |
| } |
| |
| static inline void storeRedfishEvent(const std::string& ipmiRaw, |
| const std::string& eventId, |
| const std::vector<std::string>& args) |
| { |
| static constexpr std::string_view openBMCMessageRegistryVer = "0.1"; |
| std::string messageID = |
| "OpenBMC." + std::string(openBMCMessageRegistryVer) + "." + eventId; |
| |
| // Log the Redfish message to the journal with the appropriate metadata |
| std::string journalMsg = "ME Event: " + ipmiRaw; |
| if (args.empty()) |
| { |
| phosphor::logging::log<phosphor::logging::level::INFO>( |
| journalMsg.c_str(), |
| phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", |
| messageID.c_str())); |
| } |
| else |
| { |
| std::string argsStr = boost::algorithm::join(args, ","); |
| phosphor::logging::log<phosphor::logging::level::INFO>( |
| journalMsg.c_str(), |
| phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", |
| messageID.c_str()), |
| phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s", |
| argsStr.c_str())); |
| } |
| } |
| } // namespace utils |
| } // namespace intel_oem::ipmi::sel::redfish_hooks::me |