blob: 1f80a1a991f042afcf3a86db954b182039a25f50 [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
Ed Tanous4aee3fc2022-09-20 15:59:16 -070018#include <boost/container/flat_map.hpp>
Agnieszka Szlendakd2220cc2020-04-17 15:00:12 +020019#include <ipmi_to_redfish_hooks.hpp>
20
21namespace intel_oem::ipmi::sel::redfish_hooks::me
22{
23enum class EventSensor
24{
25 MeFirmwareHealth = 23
26};
27
28enum class HealthEventType
29{
30 FirmwareStatus = 0x00,
31 SmbusLinkFailure = 0x01
32};
33
34bool messageHook(const SELData& selData, const std::string& ipmiRaw);
35
36namespace utils
37{
38// Maps event byte to human-readable message
39using MessageMap = boost::container::flat_map<uint8_t, std::string>;
40// Function which performs custom decoding for complex structures
41using 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 */
53static 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
97static 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
105template <int idx>
106static 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
143template <int idx>
144static 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
150template <int idx>
151static 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
157static 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
Ed Tanous4aee3fc2022-09-20 15:59:16 -0700186} // namespace intel_oem::ipmi::sel::redfish_hooks::me