blob: d8250c018db243f94fb57586562a2a7d151be0ce [file] [log] [blame]
Agnieszka Szlendakd2220cc2020-04-17 15:00:12 +02001/*
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
20namespace intel_oem::ipmi::sel::redfish_hooks::me
21{
22enum class EventSensor
23{
24 MeFirmwareHealth = 23
25};
26
27enum class HealthEventType
28{
29 FirmwareStatus = 0x00,
30 SmbusLinkFailure = 0x01
31};
32
33bool messageHook(const SELData& selData, const std::string& ipmiRaw);
34
35namespace utils
36{
37// Maps event byte to human-readable message
38using MessageMap = boost::container::flat_map<uint8_t, std::string>;
39// Function which performs custom decoding for complex structures
40using 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 */
52static 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
96static 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
104template <int idx>
105static 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
142template <int idx>
143static 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
149template <int idx>
150static 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
156static 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