Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1 | /* |
| 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 Venture | 31b35d5 | 2019-10-20 13:25:16 -0700 | [diff] [blame] | 17 | #include "ipmi_to_redfish_hooks.hpp" |
Patrick Venture | 31b35d5 | 2019-10-20 13:25:16 -0700 | [diff] [blame] | 18 | |
Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 19 | #include <boost/algorithm/string.hpp> |
| 20 | #include <boost/container/flat_map.hpp> |
James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 21 | #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. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 28 | #include <cmath> |
Vernon Mauery | dcff150 | 2022-09-28 11:12:46 -0700 | [diff] [blame] | 29 | #include <cstdint> |
Patrick Venture | 5c2d26e | 2019-09-25 17:43:53 -0700 | [diff] [blame] | 30 | #include <cstring> |
Patrick Venture | fd2a938 | 2019-09-25 17:47:25 -0700 | [diff] [blame] | 31 | #include <memory> |
Patrick Venture | c4e9de6 | 2019-09-25 17:40:54 -0700 | [diff] [blame] | 32 | #include <optional> |
Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 33 | #include <string> |
| 34 | |
| 35 | namespace ipmi |
| 36 | { |
Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 37 | void registerSensorFunctions() __attribute__((constructor)); |
Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 38 | |
James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 39 | namespace meHealth |
| 40 | { |
James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 41 | constexpr const char* busname = "xyz.openbmc_project.NodeManagerProxy"; |
| 42 | constexpr const char* path = "/xyz/openbmc_project/status/me"; |
| 43 | constexpr const char* interface = "xyz.openbmc_project.SetHealth"; |
| 44 | constexpr const char* method = "SetHealth"; |
| 45 | constexpr const char* critical = "critical"; |
| 46 | constexpr const char* warning = "warning"; |
| 47 | constexpr const char* ok = "ok"; |
James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 48 | } // namespace meHealth |
| 49 | |
| 50 | static 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 Williams | 1bcced0 | 2024-08-16 15:20:24 -0400 | [diff] [blame] | 90 | auto setHealth = |
| 91 | dbus->new_method_call(meHealth::busname, meHealth::path, |
| 92 | meHealth::interface, meHealth::method); |
James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 93 | setHealth.append(std::to_string(static_cast<size_t>(eventData2)), state); |
| 94 | try |
| 95 | { |
| 96 | dbus->call(setHealth); |
| 97 | } |
Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 98 | catch (const sdbusplus::exception_t&) |
James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 99 | { |
| 100 | phosphor::logging::log<phosphor::logging::level::ERR>( |
| 101 | "Failed to set ME Health"); |
| 102 | } |
| 103 | } |
| 104 | |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 105 | ipmi::RspType<> ipmiSenPlatformEvent(ipmi::Context::ptr ctx, |
| 106 | ipmi::message::Payload& p) |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 107 | { |
James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 108 | constexpr const uint8_t meId = 0x2C; |
| 109 | constexpr const uint8_t meSensorNum = 0x17; |
| 110 | constexpr const uint8_t disabled = 0x80; |
| 111 | |
Sujoy Ray | 9e58cfe | 2021-11-01 13:17:27 -0700 | [diff] [blame] | 112 | uint8_t sysgeneratorID = 0; |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 113 | 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 Ray | 9e58cfe | 2021-11-01 13:17:27 -0700 | [diff] [blame] | 120 | uint16_t generatorID = 0; |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 121 | ipmi::ChannelInfo chInfo; |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 122 | |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 123 | if (ipmi::getChannelInfo(ctx->channel, chInfo) != ipmi::ccSuccess) |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 124 | { |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 125 | 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. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 129 | } |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 130 | |
| 131 | if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) == |
| 132 | ipmi::EChannelMediumType::systemInterface) |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 133 | { |
Sujoy Ray | 9e58cfe | 2021-11-01 13:17:27 -0700 | [diff] [blame] | 134 | p.unpack(sysgeneratorID, evmRev, sensorType, sensorNum, eventType, |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 135 | eventData1, eventData2, eventData3); |
Vernon Mauery | 5d24dda | 2022-04-13 15:11:10 -0700 | [diff] [blame] | 136 | constexpr const uint8_t isSoftwareID = 0x01; |
| 137 | if (!(sysgeneratorID & isSoftwareID)) |
| 138 | { |
| 139 | return ipmi::responseInvalidFieldRequest(); |
| 140 | } |
Sujoy Ray | 9e58cfe | 2021-11-01 13:17:27 -0700 | [diff] [blame] | 141 | // 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 Mauery | 5d24dda | 2022-04-13 15:11:10 -0700 | [diff] [blame] | 145 | | sysgeneratorID; |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 146 | } |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 147 | else |
| 148 | { |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 149 | p.unpack(evmRev, sensorType, sensorNum, eventType, eventData1, |
| 150 | eventData2, eventData3); |
Sujoy Ray | 9e58cfe | 2021-11-01 13:17:27 -0700 | [diff] [blame] | 151 | // 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 Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 156 | } |
| 157 | |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 158 | if (!p.fullyUnpacked()) |
| 159 | { |
| 160 | return ipmi::responseReqDataLenInvalid(); |
| 161 | } |
| 162 | |
Chalapathi Venkataramashetty | 989a13b | 2021-06-20 19:50:33 +0000 | [diff] [blame] | 163 | // 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. Bills | 6dd8f04 | 2019-04-11 10:39:02 -0700 | [diff] [blame] | 173 | // 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. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 178 | |
Vernon Mauery | ce3b757 | 2022-04-14 13:16:25 -0700 | [diff] [blame] | 179 | if (static_cast<uint8_t>(generatorID) == meId && sensorNum == meSensorNum && |
Sujoy Ray | 9e58cfe | 2021-11-01 13:17:27 -0700 | [diff] [blame] | 180 | eventData2 && eventData3) |
James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 181 | { |
| 182 | setMeStatus(*eventData2, *eventData3, (eventType & disabled)); |
| 183 | } |
| 184 | |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 185 | return ipmi::responseSuccess(); |
| 186 | } |
| 187 | |
Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 188 | void registerSensorFunctions() |
| 189 | { |
Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 190 | // <Platform Event> |
Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 191 | ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, |
| 192 | ipmi::sensor_event::cmdPlatformEvent, |
| 193 | ipmi::Privilege::Operator, ipmiSenPlatformEvent); |
Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 194 | } |
| 195 | } // namespace ipmi |