blob: 6b74deab2ed1c8a5c252ab18ae6e40a30d884525 [file] [log] [blame]
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001/*
2// Copyright (c) 2017 2018 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
Patrick Venture31b35d52019-10-20 13:25:16 -070017#include "ipmi_to_redfish_hooks.hpp"
Patrick Venture31b35d52019-10-20 13:25:16 -070018
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070019#include <boost/algorithm/string.hpp>
20#include <boost/container/flat_map.hpp>
James Feistfcd2d3a2020-05-28 10:38:15 -070021#include <ipmid/api.hpp>
22#include <ipmid/utils.hpp>
23#include <phosphor-logging/log.hpp>
24#include <sdbusplus/bus.hpp>
25
26#include <algorithm>
27#include <array>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070028#include <cmath>
Vernon Mauerydcff1502022-09-28 11:12:46 -070029#include <cstdint>
Patrick Venture5c2d26e2019-09-25 17:43:53 -070030#include <cstring>
Patrick Venturefd2a9382019-09-25 17:47:25 -070031#include <memory>
Patrick Venturec4e9de62019-09-25 17:40:54 -070032#include <optional>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070033#include <string>
34
35namespace ipmi
36{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070037void registerSensorFunctions() __attribute__((constructor));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070038
James Feist7aaf3fe2019-06-25 11:52:11 -070039namespace meHealth
40{
James Feistfcd2d3a2020-05-28 10:38:15 -070041constexpr const char* busname = "xyz.openbmc_project.NodeManagerProxy";
42constexpr const char* path = "/xyz/openbmc_project/status/me";
43constexpr const char* interface = "xyz.openbmc_project.SetHealth";
44constexpr const char* method = "SetHealth";
45constexpr const char* critical = "critical";
46constexpr const char* warning = "warning";
47constexpr const char* ok = "ok";
James Feist7aaf3fe2019-06-25 11:52:11 -070048} // namespace meHealth
49
50static void setMeStatus(uint8_t eventData2, uint8_t eventData3, bool disable)
51{
52 constexpr const std::array<uint8_t, 10> critical = {
53 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xD, 0xE};
54 constexpr const std::array<uint8_t, 5> warning = {0x3, 0xA, 0x13, 0x19,
55 0x1A};
56
57 std::string state;
58 if (std::find(critical.begin(), critical.end(), eventData2) !=
59 critical.end())
60 {
61 state = meHealth::critical;
62 }
63 // special case 0x3 as we only care about a few states
64 else if (eventData2 == 0x3)
65 {
66 if (eventData3 <= 0x2)
67 {
68 state = meHealth::warning;
69 }
70 else
71 {
72 return;
73 }
74 }
75 else if (std::find(warning.begin(), warning.end(), eventData2) !=
76 warning.end())
77 {
78 state = meHealth::warning;
79 }
80 else
81 {
82 return;
83 }
84 if (disable)
85 {
86 state = meHealth::ok;
87 }
88
89 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
Patrick Williams1bcced02024-08-16 15:20:24 -040090 auto setHealth =
91 dbus->new_method_call(meHealth::busname, meHealth::path,
92 meHealth::interface, meHealth::method);
James Feist7aaf3fe2019-06-25 11:52:11 -070093 setHealth.append(std::to_string(static_cast<size_t>(eventData2)), state);
94 try
95 {
96 dbus->call(setHealth);
97 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -050098 catch (const sdbusplus::exception_t&)
James Feist7aaf3fe2019-06-25 11:52:11 -070099 {
100 phosphor::logging::log<phosphor::logging::level::ERR>(
101 "Failed to set ME Health");
102 }
103}
104
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000105ipmi::RspType<> ipmiSenPlatformEvent(ipmi::Context::ptr ctx,
106 ipmi::message::Payload& p)
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700107{
James Feist7aaf3fe2019-06-25 11:52:11 -0700108 constexpr const uint8_t meId = 0x2C;
109 constexpr const uint8_t meSensorNum = 0x17;
110 constexpr const uint8_t disabled = 0x80;
111
Sujoy Ray9e58cfe2021-11-01 13:17:27 -0700112 uint8_t sysgeneratorID = 0;
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700113 uint8_t evmRev = 0;
114 uint8_t sensorType = 0;
115 uint8_t sensorNum = 0;
116 uint8_t eventType = 0;
117 uint8_t eventData1 = 0;
118 std::optional<uint8_t> eventData2 = 0;
119 std::optional<uint8_t> eventData3 = 0;
Sujoy Ray9e58cfe2021-11-01 13:17:27 -0700120 uint16_t generatorID = 0;
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000121 ipmi::ChannelInfo chInfo;
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700122
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000123 if (ipmi::getChannelInfo(ctx->channel, chInfo) != ipmi::ccSuccess)
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700124 {
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000125 phosphor::logging::log<phosphor::logging::level::ERR>(
126 "Failed to get Channel Info",
127 phosphor::logging::entry("CHANNEL=%d", ctx->channel));
128 return ipmi::responseUnspecifiedError();
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700129 }
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000130
131 if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) ==
132 ipmi::EChannelMediumType::systemInterface)
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700133 {
Sujoy Ray9e58cfe2021-11-01 13:17:27 -0700134 p.unpack(sysgeneratorID, evmRev, sensorType, sensorNum, eventType,
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700135 eventData1, eventData2, eventData3);
Vernon Mauery5d24dda2022-04-13 15:11:10 -0700136 constexpr const uint8_t isSoftwareID = 0x01;
137 if (!(sysgeneratorID & isSoftwareID))
138 {
139 return ipmi::responseInvalidFieldRequest();
140 }
Sujoy Ray9e58cfe2021-11-01 13:17:27 -0700141 // Refer to IPMI Spec Table 32: SEL Event Records
142 generatorID = (ctx->channel << 12) // Channel
143 | (0x0 << 10) // Reserved
144 | (0x0 << 8) // 0x0 for sys-soft ID
Vernon Mauery5d24dda2022-04-13 15:11:10 -0700145 | sysgeneratorID;
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700146 }
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000147 else
148 {
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000149 p.unpack(evmRev, sensorType, sensorNum, eventType, eventData1,
150 eventData2, eventData3);
Sujoy Ray9e58cfe2021-11-01 13:17:27 -0700151 // Refer to IPMI Spec Table 32: SEL Event Records
152 generatorID = (ctx->channel << 12) // Channel
153 | (0x0 << 10) // Reserved
154 | ((ctx->lun & 0x3) << 8) // Lun
155 | (ctx->rqSA << 1);
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000156 }
157
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700158 if (!p.fullyUnpacked())
159 {
160 return ipmi::responseReqDataLenInvalid();
161 }
162
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000163 // Check for valid evmRev and Sensor Type(per Table 42 of spec)
164 if (evmRev != 0x04)
165 {
166 return ipmi::responseInvalidFieldRequest();
167 }
168 if ((sensorType > 0x2C) && (sensorType < 0xC0))
169 {
170 return ipmi::responseInvalidFieldRequest();
171 }
172
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700173 // Send this request to the Redfish hooks to log it as a Redfish message
174 // instead. There is no need to add it to the SEL, so just return success.
175 intel_oem::ipmi::sel::checkRedfishHooks(
176 generatorID, evmRev, sensorType, sensorNum, eventType, eventData1,
177 eventData2.value_or(0xFF), eventData3.value_or(0xFF));
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700178
Vernon Maueryce3b7572022-04-14 13:16:25 -0700179 if (static_cast<uint8_t>(generatorID) == meId && sensorNum == meSensorNum &&
Sujoy Ray9e58cfe2021-11-01 13:17:27 -0700180 eventData2 && eventData3)
James Feist7aaf3fe2019-06-25 11:52:11 -0700181 {
182 setMeStatus(*eventData2, *eventData3, (eventType & disabled));
183 }
184
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700185 return ipmi::responseSuccess();
186}
187
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700188void registerSensorFunctions()
189{
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700190 // <Platform Event>
Vernon Mauery98bbf692019-09-16 11:14:59 -0700191 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
192 ipmi::sensor_event::cmdPlatformEvent,
193 ipmi::Privilege::Operator, ipmiSenPlatformEvent);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700194}
195} // namespace ipmi