| 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 "sensorcommands.hpp" | 
 | 18 |  | 
 | 19 | #include "commandutils.hpp" | 
 | 20 | #include "ipmi_to_redfish_hooks.hpp" | 
 | 21 | #include "sdrutils.hpp" | 
 | 22 | #include "sensorutils.hpp" | 
 | 23 | #include "storagecommands.hpp" | 
| Patrick Venture | c2a07d4 | 2020-05-30 16:35:03 -0700 | [diff] [blame] | 24 | #include "types.hpp" | 
| Patrick Venture | 31b35d5 | 2019-10-20 13:25:16 -0700 | [diff] [blame] | 25 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 26 | #include <boost/algorithm/string.hpp> | 
 | 27 | #include <boost/container/flat_map.hpp> | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 28 | #include <ipmid/api.hpp> | 
 | 29 | #include <ipmid/utils.hpp> | 
 | 30 | #include <phosphor-logging/log.hpp> | 
 | 31 | #include <sdbusplus/bus.hpp> | 
 | 32 |  | 
 | 33 | #include <algorithm> | 
 | 34 | #include <array> | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 35 | #include <chrono> | 
 | 36 | #include <cmath> | 
| Patrick Venture | 5c2d26e | 2019-09-25 17:43:53 -0700 | [diff] [blame] | 37 | #include <cstring> | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 38 | #include <iostream> | 
| Patrick Venture | b10ec8b | 2019-09-25 16:39:14 -0700 | [diff] [blame] | 39 | #include <map> | 
| Patrick Venture | fd2a938 | 2019-09-25 17:47:25 -0700 | [diff] [blame] | 40 | #include <memory> | 
| Patrick Venture | c4e9de6 | 2019-09-25 17:40:54 -0700 | [diff] [blame] | 41 | #include <optional> | 
| Patrick Venture | e615402 | 2019-09-25 17:50:25 -0700 | [diff] [blame] | 42 | #include <stdexcept> | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 43 | #include <string> | 
| Patrick Venture | 38f46f2 | 2019-09-25 17:41:26 -0700 | [diff] [blame] | 44 | #include <utility> | 
| Patrick Venture | eb02a5c | 2019-09-25 17:44:43 -0700 | [diff] [blame] | 45 | #include <variant> | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 46 |  | 
 | 47 | namespace ipmi | 
 | 48 | { | 
 | 49 | using ManagedObjectType = | 
 | 50 |     std::map<sdbusplus::message::object_path, | 
 | 51 |              std::map<std::string, std::map<std::string, DbusVariant>>>; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 52 | using SDRObjectType = | 
 | 53 |     boost::container::flat_map<uint16_t, std::vector<uint8_t>>; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 54 |  | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 55 | static constexpr int sensorMapUpdatePeriod = 10; | 
| Alex Qiu | 09701ef | 2020-07-15 17:56:21 -0700 | [diff] [blame^] | 56 | static constexpr int sensorMapSdrUpdatePeriod = 60; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 57 |  | 
 | 58 | constexpr size_t maxSDRTotalSize = | 
 | 59 |     76; // Largest SDR Record Size (type 01) + SDR Overheader Size | 
 | 60 | constexpr static const uint32_t noTimestamp = 0xFFFFFFFF; | 
 | 61 |  | 
 | 62 | static uint16_t sdrReservationID; | 
 | 63 | static uint32_t sdrLastAdd = noTimestamp; | 
 | 64 | static uint32_t sdrLastRemove = noTimestamp; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 65 | static constexpr size_t lastRecordIndex = 0xFFFF; | 
 | 66 | static constexpr int GENERAL_ERROR = -1; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 67 |  | 
| Richard Marian Thomaiyar | 01fbcb5 | 2018-11-19 22:04:34 +0530 | [diff] [blame] | 68 | SensorSubTree sensorTree; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 69 | SDRObjectType sensorDataRecords; | 
 | 70 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 71 | static boost::container::flat_map<std::string, ManagedObjectType> SensorCache; | 
 | 72 |  | 
| Jason M. Bills | 17add59 | 2018-11-12 14:30:12 -0800 | [diff] [blame] | 73 | // Specify the comparison required to sort and find char* map objects | 
 | 74 | struct CmpStr | 
 | 75 | { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 76 |     bool operator()(const char* a, const char* b) const | 
| Jason M. Bills | 17add59 | 2018-11-12 14:30:12 -0800 | [diff] [blame] | 77 |     { | 
 | 78 |         return std::strcmp(a, b) < 0; | 
 | 79 |     } | 
 | 80 | }; | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 81 | const static boost::container::flat_map<const char*, SensorUnits, CmpStr> | 
| Jason M. Bills | 17add59 | 2018-11-12 14:30:12 -0800 | [diff] [blame] | 82 |     sensorUnits{{{"temperature", SensorUnits::degreesC}, | 
 | 83 |                  {"voltage", SensorUnits::volts}, | 
 | 84 |                  {"current", SensorUnits::amps}, | 
 | 85 |                  {"fan_tach", SensorUnits::rpm}, | 
 | 86 |                  {"power", SensorUnits::watts}}}; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 87 |  | 
 | 88 | void registerSensorFunctions() __attribute__((constructor)); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 89 |  | 
 | 90 | static sdbusplus::bus::match::match sensorAdded( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 91 |     *getSdBus(), | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 92 |     "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/" | 
 | 93 |     "sensors/'", | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 94 |     [](sdbusplus::message::message& m) { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 95 |         sensorTree.clear(); | 
 | 96 |         sdrLastAdd = std::chrono::duration_cast<std::chrono::seconds>( | 
 | 97 |                          std::chrono::system_clock::now().time_since_epoch()) | 
 | 98 |                          .count(); | 
 | 99 |     }); | 
 | 100 |  | 
 | 101 | static sdbusplus::bus::match::match sensorRemoved( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 102 |     *getSdBus(), | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 103 |     "type='signal',member='InterfacesRemoved',arg0path='/xyz/openbmc_project/" | 
 | 104 |     "sensors/'", | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 105 |     [](sdbusplus::message::message& m) { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 106 |         sensorTree.clear(); | 
 | 107 |         sdrLastRemove = std::chrono::duration_cast<std::chrono::seconds>( | 
 | 108 |                             std::chrono::system_clock::now().time_since_epoch()) | 
 | 109 |                             .count(); | 
 | 110 |     }); | 
 | 111 |  | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 112 | // this keeps track of deassertions for sensor event status command. A | 
 | 113 | // deasertion can only happen if an assertion was seen first. | 
 | 114 | static boost::container::flat_map< | 
 | 115 |     std::string, boost::container::flat_map<std::string, std::optional<bool>>> | 
 | 116 |     thresholdDeassertMap; | 
 | 117 |  | 
 | 118 | static sdbusplus::bus::match::match thresholdChanged( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 119 |     *getSdBus(), | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 120 |     "type='signal',member='PropertiesChanged',interface='org.freedesktop.DBus." | 
 | 121 |     "Properties',arg0namespace='xyz.openbmc_project.Sensor.Threshold'", | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 122 |     [](sdbusplus::message::message& m) { | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 123 |         boost::container::flat_map<std::string, std::variant<bool, double>> | 
 | 124 |             values; | 
 | 125 |         m.read(std::string(), values); | 
 | 126 |  | 
 | 127 |         auto findAssert = | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 128 |             std::find_if(values.begin(), values.end(), [](const auto& pair) { | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 129 |                 return pair.first.find("Alarm") != std::string::npos; | 
 | 130 |             }); | 
 | 131 |         if (findAssert != values.end()) | 
 | 132 |         { | 
 | 133 |             auto ptr = std::get_if<bool>(&(findAssert->second)); | 
 | 134 |             if (ptr == nullptr) | 
 | 135 |             { | 
 | 136 |                 phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 137 |                     "thresholdChanged: Assert non bool"); | 
 | 138 |                 return; | 
 | 139 |             } | 
 | 140 |             if (*ptr) | 
 | 141 |             { | 
 | 142 |                 phosphor::logging::log<phosphor::logging::level::INFO>( | 
 | 143 |                     "thresholdChanged: Assert", | 
 | 144 |                     phosphor::logging::entry("SENSOR=%s", m.get_path())); | 
 | 145 |                 thresholdDeassertMap[m.get_path()][findAssert->first] = *ptr; | 
 | 146 |             } | 
 | 147 |             else | 
 | 148 |             { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 149 |                 auto& value = | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 150 |                     thresholdDeassertMap[m.get_path()][findAssert->first]; | 
 | 151 |                 if (value) | 
 | 152 |                 { | 
 | 153 |                     phosphor::logging::log<phosphor::logging::level::INFO>( | 
 | 154 |                         "thresholdChanged: deassert", | 
 | 155 |                         phosphor::logging::entry("SENSOR=%s", m.get_path())); | 
 | 156 |                     value = *ptr; | 
 | 157 |                 } | 
 | 158 |             } | 
 | 159 |         } | 
 | 160 |     }); | 
 | 161 |  | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 162 | static void getSensorMaxMin(const SensorMap& sensorMap, double& max, | 
 | 163 |                             double& min) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 164 | { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 165 |     max = 127; | 
 | 166 |     min = -128; | 
 | 167 |  | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 168 |     auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value"); | 
 | 169 |     auto critical = | 
 | 170 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical"); | 
 | 171 |     auto warning = | 
 | 172 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning"); | 
 | 173 |  | 
 | 174 |     if (sensorObject != sensorMap.end()) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 175 |     { | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 176 |         auto maxMap = sensorObject->second.find("MaxValue"); | 
 | 177 |         auto minMap = sensorObject->second.find("MinValue"); | 
 | 178 |  | 
 | 179 |         if (maxMap != sensorObject->second.end()) | 
 | 180 |         { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 181 |             max = std::visit(VariantToDoubleVisitor(), maxMap->second); | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 182 |         } | 
 | 183 |         if (minMap != sensorObject->second.end()) | 
 | 184 |         { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 185 |             min = std::visit(VariantToDoubleVisitor(), minMap->second); | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 186 |         } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 187 |     } | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 188 |     if (critical != sensorMap.end()) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 189 |     { | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 190 |         auto lower = critical->second.find("CriticalLow"); | 
 | 191 |         auto upper = critical->second.find("CriticalHigh"); | 
 | 192 |         if (lower != critical->second.end()) | 
 | 193 |         { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 194 |             double value = std::visit(VariantToDoubleVisitor(), lower->second); | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 195 |             min = std::min(value, min); | 
 | 196 |         } | 
 | 197 |         if (upper != critical->second.end()) | 
 | 198 |         { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 199 |             double value = std::visit(VariantToDoubleVisitor(), upper->second); | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 200 |             max = std::max(value, max); | 
 | 201 |         } | 
 | 202 |     } | 
 | 203 |     if (warning != sensorMap.end()) | 
 | 204 |     { | 
 | 205 |  | 
 | 206 |         auto lower = warning->second.find("WarningLow"); | 
 | 207 |         auto upper = warning->second.find("WarningHigh"); | 
 | 208 |         if (lower != warning->second.end()) | 
 | 209 |         { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 210 |             double value = std::visit(VariantToDoubleVisitor(), lower->second); | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 211 |             min = std::min(value, min); | 
 | 212 |         } | 
 | 213 |         if (upper != warning->second.end()) | 
 | 214 |         { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 215 |             double value = std::visit(VariantToDoubleVisitor(), upper->second); | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 216 |             max = std::max(value, max); | 
 | 217 |         } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 218 |     } | 
 | 219 | } | 
 | 220 |  | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 221 | static bool getSensorMap(boost::asio::yield_context yield, | 
 | 222 |                          std::string sensorConnection, std::string sensorPath, | 
| Alex Qiu | 09701ef | 2020-07-15 17:56:21 -0700 | [diff] [blame^] | 223 |                          SensorMap& sensorMap, | 
 | 224 |                          int updatePeriod = sensorMapUpdatePeriod) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 225 | { | 
 | 226 |     static boost::container::flat_map< | 
 | 227 |         std::string, std::chrono::time_point<std::chrono::steady_clock>> | 
 | 228 |         updateTimeMap; | 
 | 229 |  | 
 | 230 |     auto updateFind = updateTimeMap.find(sensorConnection); | 
 | 231 |     auto lastUpdate = std::chrono::time_point<std::chrono::steady_clock>(); | 
 | 232 |     if (updateFind != updateTimeMap.end()) | 
 | 233 |     { | 
 | 234 |         lastUpdate = updateFind->second; | 
 | 235 |     } | 
 | 236 |  | 
 | 237 |     auto now = std::chrono::steady_clock::now(); | 
 | 238 |  | 
 | 239 |     if (std::chrono::duration_cast<std::chrono::seconds>(now - lastUpdate) | 
| Alex Qiu | 09701ef | 2020-07-15 17:56:21 -0700 | [diff] [blame^] | 240 |             .count() > updatePeriod) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 241 |     { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 242 |         std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 243 |         boost::system::error_code ec; | 
 | 244 |         auto managedObjects = dbus->yield_method_call<ManagedObjectType>( | 
 | 245 |             yield, ec, sensorConnection.c_str(), "/", | 
 | 246 |             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); | 
 | 247 |         if (ec) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 248 |         { | 
 | 249 |             phosphor::logging::log<phosphor::logging::level::ERR>( | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 250 |                 "GetMangagedObjects for getSensorMap failed", | 
 | 251 |                 phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
 | 252 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 253 |             return false; | 
 | 254 |         } | 
 | 255 |  | 
 | 256 |         SensorCache[sensorConnection] = managedObjects; | 
| Alex Qiu | 09701ef | 2020-07-15 17:56:21 -0700 | [diff] [blame^] | 257 |         // Update time after finish building the map which allow the | 
 | 258 |         // data to be cached for updatePeriod plus the build time. | 
 | 259 |         updateTimeMap[sensorConnection] = std::chrono::steady_clock::now(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 260 |     } | 
 | 261 |     auto connection = SensorCache.find(sensorConnection); | 
 | 262 |     if (connection == SensorCache.end()) | 
 | 263 |     { | 
 | 264 |         return false; | 
 | 265 |     } | 
 | 266 |     auto path = connection->second.find(sensorPath); | 
 | 267 |     if (path == connection->second.end()) | 
 | 268 |     { | 
 | 269 |         return false; | 
 | 270 |     } | 
 | 271 |     sensorMap = path->second; | 
 | 272 |  | 
 | 273 |     return true; | 
 | 274 | } | 
 | 275 |  | 
 | 276 | /* sensor commands */ | 
| James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 277 | namespace meHealth | 
 | 278 | { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 279 | constexpr const char* busname = "xyz.openbmc_project.NodeManagerProxy"; | 
 | 280 | constexpr const char* path = "/xyz/openbmc_project/status/me"; | 
 | 281 | constexpr const char* interface = "xyz.openbmc_project.SetHealth"; | 
 | 282 | constexpr const char* method = "SetHealth"; | 
 | 283 | constexpr const char* critical = "critical"; | 
 | 284 | constexpr const char* warning = "warning"; | 
 | 285 | constexpr const char* ok = "ok"; | 
| James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 286 | } // namespace meHealth | 
 | 287 |  | 
 | 288 | static void setMeStatus(uint8_t eventData2, uint8_t eventData3, bool disable) | 
 | 289 | { | 
 | 290 |     constexpr const std::array<uint8_t, 10> critical = { | 
 | 291 |         0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xD, 0xE}; | 
 | 292 |     constexpr const std::array<uint8_t, 5> warning = {0x3, 0xA, 0x13, 0x19, | 
 | 293 |                                                       0x1A}; | 
 | 294 |  | 
 | 295 |     std::string state; | 
 | 296 |     if (std::find(critical.begin(), critical.end(), eventData2) != | 
 | 297 |         critical.end()) | 
 | 298 |     { | 
 | 299 |         state = meHealth::critical; | 
 | 300 |     } | 
 | 301 |     // special case 0x3 as we only care about a few states | 
 | 302 |     else if (eventData2 == 0x3) | 
 | 303 |     { | 
 | 304 |         if (eventData3 <= 0x2) | 
 | 305 |         { | 
 | 306 |             state = meHealth::warning; | 
 | 307 |         } | 
 | 308 |         else | 
 | 309 |         { | 
 | 310 |             return; | 
 | 311 |         } | 
 | 312 |     } | 
 | 313 |     else if (std::find(warning.begin(), warning.end(), eventData2) != | 
 | 314 |              warning.end()) | 
 | 315 |     { | 
 | 316 |         state = meHealth::warning; | 
 | 317 |     } | 
 | 318 |     else | 
 | 319 |     { | 
 | 320 |         return; | 
 | 321 |     } | 
 | 322 |     if (disable) | 
 | 323 |     { | 
 | 324 |         state = meHealth::ok; | 
 | 325 |     } | 
 | 326 |  | 
 | 327 |     std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
 | 328 |     auto setHealth = | 
 | 329 |         dbus->new_method_call(meHealth::busname, meHealth::path, | 
 | 330 |                               meHealth::interface, meHealth::method); | 
 | 331 |     setHealth.append(std::to_string(static_cast<size_t>(eventData2)), state); | 
 | 332 |     try | 
 | 333 |     { | 
 | 334 |         dbus->call(setHealth); | 
 | 335 |     } | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 336 |     catch (sdbusplus::exception_t&) | 
| James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 337 |     { | 
 | 338 |         phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 339 |             "Failed to set ME Health"); | 
 | 340 |     } | 
 | 341 | } | 
 | 342 |  | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 343 | ipmi::RspType<> ipmiSenPlatformEvent(ipmi::message::Payload& p) | 
| Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 344 | { | 
| James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 345 |     constexpr const uint8_t meId = 0x2C; | 
 | 346 |     constexpr const uint8_t meSensorNum = 0x17; | 
 | 347 |     constexpr const uint8_t disabled = 0x80; | 
 | 348 |  | 
| Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 349 |     uint8_t generatorID = 0; | 
 | 350 |     uint8_t evmRev = 0; | 
 | 351 |     uint8_t sensorType = 0; | 
 | 352 |     uint8_t sensorNum = 0; | 
 | 353 |     uint8_t eventType = 0; | 
 | 354 |     uint8_t eventData1 = 0; | 
 | 355 |     std::optional<uint8_t> eventData2 = 0; | 
 | 356 |     std::optional<uint8_t> eventData3 = 0; | 
 | 357 |  | 
 | 358 |     // todo: This check is supposed to be based on the incoming channel. | 
 | 359 |     //      e.g. system channel will provide upto 8 bytes including generator | 
 | 360 |     //      ID, but ipmb channel will provide only up to 7 bytes without the | 
 | 361 |     //      generator ID. | 
 | 362 |     // Support for this check is coming in future patches, so for now just base | 
 | 363 |     // it on if the first byte is the EvMRev (0x04). | 
 | 364 |     if (p.size() && p.data()[0] == 0x04) | 
 | 365 |     { | 
 | 366 |         p.unpack(evmRev, sensorType, sensorNum, eventType, eventData1, | 
 | 367 |                  eventData2, eventData3); | 
 | 368 |         // todo: the generator ID for this channel is supposed to come from the | 
 | 369 |         // IPMB requesters slave address. Support for this is coming in future | 
 | 370 |         // patches, so for now just assume it is coming from the ME (0x2C). | 
 | 371 |         generatorID = 0x2C; | 
 | 372 |     } | 
 | 373 |     else | 
 | 374 |     { | 
 | 375 |         p.unpack(generatorID, evmRev, sensorType, sensorNum, eventType, | 
 | 376 |                  eventData1, eventData2, eventData3); | 
 | 377 |     } | 
 | 378 |     if (!p.fullyUnpacked()) | 
 | 379 |     { | 
 | 380 |         return ipmi::responseReqDataLenInvalid(); | 
 | 381 |     } | 
 | 382 |  | 
| Jason M. Bills | 6dd8f04 | 2019-04-11 10:39:02 -0700 | [diff] [blame] | 383 |     // Send this request to the Redfish hooks to log it as a Redfish message | 
 | 384 |     // instead.  There is no need to add it to the SEL, so just return success. | 
 | 385 |     intel_oem::ipmi::sel::checkRedfishHooks( | 
 | 386 |         generatorID, evmRev, sensorType, sensorNum, eventType, eventData1, | 
 | 387 |         eventData2.value_or(0xFF), eventData3.value_or(0xFF)); | 
| Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 388 |  | 
| James Feist | 7aaf3fe | 2019-06-25 11:52:11 -0700 | [diff] [blame] | 389 |     if (generatorID == meId && sensorNum == meSensorNum && eventData2 && | 
 | 390 |         eventData3) | 
 | 391 |     { | 
 | 392 |         setMeStatus(*eventData2, *eventData3, (eventType & disabled)); | 
 | 393 |     } | 
 | 394 |  | 
| Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 395 |     return ipmi::responseSuccess(); | 
 | 396 | } | 
 | 397 |  | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 398 | ipmi::RspType<uint8_t, uint8_t, uint8_t, std::optional<uint8_t>> | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 399 |     ipmiSenGetSensorReading(ipmi::Context::ptr ctx, uint8_t sensnum) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 400 | { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 401 |     std::string connection; | 
 | 402 |     std::string path; | 
 | 403 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 404 |     auto status = getSensorConnection(ctx, sensnum, connection, path); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 405 |     if (status) | 
 | 406 |     { | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 407 |         return ipmi::response(status); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 408 |     } | 
 | 409 |  | 
 | 410 |     SensorMap sensorMap; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 411 |     if (!getSensorMap(ctx->yield, connection, path, sensorMap)) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 412 |     { | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 413 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 414 |     } | 
 | 415 |     auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value"); | 
 | 416 |  | 
 | 417 |     if (sensorObject == sensorMap.end() || | 
 | 418 |         sensorObject->second.find("Value") == sensorObject->second.end()) | 
 | 419 |     { | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 420 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 421 |     } | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 422 |     auto& valueVariant = sensorObject->second["Value"]; | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 423 |     double reading = std::visit(VariantToDoubleVisitor(), valueVariant); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 424 |  | 
| Yong Li | 1f2eb5e | 2019-05-23 14:07:17 +0800 | [diff] [blame] | 425 |     double max = 0; | 
 | 426 |     double min = 0; | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 427 |     getSensorMaxMin(sensorMap, max, min); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 428 |  | 
 | 429 |     int16_t mValue = 0; | 
 | 430 |     int16_t bValue = 0; | 
 | 431 |     int8_t rExp = 0; | 
 | 432 |     int8_t bExp = 0; | 
 | 433 |     bool bSigned = false; | 
 | 434 |  | 
 | 435 |     if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned)) | 
 | 436 |     { | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 437 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 438 |     } | 
 | 439 |  | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 440 |     uint8_t value = | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 441 |         scaleIPMIValueFromDouble(reading, mValue, rExp, bValue, bExp, bSigned); | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 442 |     uint8_t operation = | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 443 |         static_cast<uint8_t>(IPMISensorReadingByte2::sensorScanningEnable); | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 444 |     operation |= | 
| James Feist | 81a95c1 | 2019-03-01 15:08:28 -0800 | [diff] [blame] | 445 |         static_cast<uint8_t>(IPMISensorReadingByte2::eventMessagesEnable); | 
| James Feist | 1ee6ed8 | 2020-06-17 16:16:50 -0700 | [diff] [blame] | 446 |     bool notReading = std::isnan(reading); | 
 | 447 |  | 
 | 448 |     if (!notReading) | 
 | 449 |     { | 
 | 450 |         auto availableObject = | 
 | 451 |             sensorMap.find("xyz.openbmc_project.State.Decorator.Availability"); | 
 | 452 |         if (availableObject != sensorMap.end()) | 
 | 453 |         { | 
 | 454 |             auto findAvailable = availableObject->second.find("Available"); | 
 | 455 |             if (findAvailable != availableObject->second.end()) | 
 | 456 |             { | 
 | 457 |                 bool* available = std::get_if<bool>(&(findAvailable->second)); | 
 | 458 |                 if (available && !(*available)) | 
 | 459 |                 { | 
 | 460 |                     notReading = true; | 
 | 461 |                 } | 
 | 462 |             } | 
 | 463 |         } | 
 | 464 |     } | 
 | 465 |  | 
 | 466 |     if (notReading) | 
 | 467 |     { | 
 | 468 |         operation |= static_cast<uint8_t>( | 
 | 469 |             IPMISensorReadingByte2::readingStateUnavailable); | 
 | 470 |     } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 471 |  | 
| James Feist | 0cd014a | 2019-04-08 15:04:33 -0700 | [diff] [blame] | 472 |     uint8_t thresholds = 0; | 
 | 473 |  | 
 | 474 |     auto warningObject = | 
 | 475 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning"); | 
 | 476 |     if (warningObject != sensorMap.end()) | 
 | 477 |     { | 
 | 478 |         auto alarmHigh = warningObject->second.find("WarningAlarmHigh"); | 
 | 479 |         auto alarmLow = warningObject->second.find("WarningAlarmLow"); | 
 | 480 |         if (alarmHigh != warningObject->second.end()) | 
 | 481 |         { | 
 | 482 |             if (std::get<bool>(alarmHigh->second)) | 
 | 483 |             { | 
 | 484 |                 thresholds |= static_cast<uint8_t>( | 
 | 485 |                     IPMISensorReadingByte3::upperNonCritical); | 
 | 486 |             } | 
 | 487 |         } | 
 | 488 |         if (alarmLow != warningObject->second.end()) | 
 | 489 |         { | 
 | 490 |             if (std::get<bool>(alarmLow->second)) | 
 | 491 |             { | 
 | 492 |                 thresholds |= static_cast<uint8_t>( | 
 | 493 |                     IPMISensorReadingByte3::lowerNonCritical); | 
 | 494 |             } | 
 | 495 |         } | 
 | 496 |     } | 
 | 497 |  | 
 | 498 |     auto criticalObject = | 
 | 499 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical"); | 
 | 500 |     if (criticalObject != sensorMap.end()) | 
 | 501 |     { | 
 | 502 |         auto alarmHigh = criticalObject->second.find("CriticalAlarmHigh"); | 
 | 503 |         auto alarmLow = criticalObject->second.find("CriticalAlarmLow"); | 
 | 504 |         if (alarmHigh != criticalObject->second.end()) | 
 | 505 |         { | 
 | 506 |             if (std::get<bool>(alarmHigh->second)) | 
 | 507 |             { | 
 | 508 |                 thresholds |= | 
 | 509 |                     static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical); | 
 | 510 |             } | 
 | 511 |         } | 
 | 512 |         if (alarmLow != criticalObject->second.end()) | 
 | 513 |         { | 
 | 514 |             if (std::get<bool>(alarmLow->second)) | 
 | 515 |             { | 
 | 516 |                 thresholds |= | 
 | 517 |                     static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical); | 
 | 518 |             } | 
 | 519 |         } | 
 | 520 |     } | 
 | 521 |  | 
 | 522 |     // no discrete as of today so optional byte is never returned | 
 | 523 |     return ipmi::responseSuccess(value, operation, thresholds, std::nullopt); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 524 | } | 
 | 525 |  | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 526 | /** @brief implements the Set Sensor threshold command | 
 | 527 |  *  @param sensorNumber        - sensor number | 
 | 528 |  *  @param lowerNonCriticalThreshMask | 
 | 529 |  *  @param lowerCriticalThreshMask | 
 | 530 |  *  @param lowerNonRecovThreshMask | 
 | 531 |  *  @param upperNonCriticalThreshMask | 
 | 532 |  *  @param upperCriticalThreshMask | 
 | 533 |  *  @param upperNonRecovThreshMask | 
 | 534 |  *  @param reserved | 
 | 535 |  *  @param lowerNonCritical    - lower non-critical threshold | 
 | 536 |  *  @param lowerCritical       - Lower critical threshold | 
 | 537 |  *  @param lowerNonRecoverable - Lower non recovarable threshold | 
 | 538 |  *  @param upperNonCritical    - Upper non-critical threshold | 
 | 539 |  *  @param upperCritical       - Upper critical | 
 | 540 |  *  @param upperNonRecoverable - Upper Non-recoverable | 
 | 541 |  * | 
 | 542 |  *  @returns IPMI completion code | 
 | 543 |  */ | 
 | 544 | ipmi::RspType<> ipmiSenSetSensorThresholds( | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 545 |     ipmi::Context::ptr ctx, uint8_t sensorNum, bool lowerNonCriticalThreshMask, | 
 | 546 |     bool lowerCriticalThreshMask, bool lowerNonRecovThreshMask, | 
 | 547 |     bool upperNonCriticalThreshMask, bool upperCriticalThreshMask, | 
 | 548 |     bool upperNonRecovThreshMask, uint2_t reserved, uint8_t lowerNonCritical, | 
 | 549 |     uint8_t lowerCritical, uint8_t lowerNonRecoverable, | 
 | 550 |     uint8_t upperNonCritical, uint8_t upperCritical, | 
 | 551 |     uint8_t upperNonRecoverable) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 552 | { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 553 |     constexpr uint8_t thresholdMask = 0xFF; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 554 |  | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 555 |     if (reserved) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 556 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 557 |         return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 558 |     } | 
 | 559 |  | 
 | 560 |     // lower nc and upper nc not suppported on any sensor | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 561 |     if (lowerNonRecovThreshMask || upperNonRecovThreshMask) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 562 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 563 |         return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 564 |     } | 
 | 565 |  | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 566 |     // if none of the threshold mask are set, nothing to do | 
 | 567 |     if (!(lowerNonCriticalThreshMask | lowerCriticalThreshMask | | 
 | 568 |           lowerNonRecovThreshMask | upperNonCriticalThreshMask | | 
 | 569 |           upperCriticalThreshMask | upperNonRecovThreshMask)) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 570 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 571 |         return ipmi::responseSuccess(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 572 |     } | 
 | 573 |  | 
 | 574 |     std::string connection; | 
 | 575 |     std::string path; | 
 | 576 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 577 |     ipmi::Cc status = getSensorConnection(ctx, sensorNum, connection, path); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 578 |     if (status) | 
 | 579 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 580 |         return ipmi::response(status); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 581 |     } | 
 | 582 |     SensorMap sensorMap; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 583 |     if (!getSensorMap(ctx->yield, connection, path, sensorMap)) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 584 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 585 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 586 |     } | 
 | 587 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 588 |     double max = 0; | 
 | 589 |     double min = 0; | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 590 |     getSensorMaxMin(sensorMap, max, min); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 591 |  | 
 | 592 |     int16_t mValue = 0; | 
 | 593 |     int16_t bValue = 0; | 
 | 594 |     int8_t rExp = 0; | 
 | 595 |     int8_t bExp = 0; | 
 | 596 |     bool bSigned = false; | 
 | 597 |  | 
 | 598 |     if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned)) | 
 | 599 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 600 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 601 |     } | 
 | 602 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 603 |     // store a vector of property name, value to set, and interface | 
 | 604 |     std::vector<std::tuple<std::string, uint8_t, std::string>> thresholdsToSet; | 
 | 605 |  | 
 | 606 |     // define the indexes of the tuple | 
 | 607 |     constexpr uint8_t propertyName = 0; | 
 | 608 |     constexpr uint8_t thresholdValue = 1; | 
 | 609 |     constexpr uint8_t interface = 2; | 
 | 610 |     // verifiy all needed fields are present | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 611 |     if (lowerCriticalThreshMask || upperCriticalThreshMask) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 612 |     { | 
 | 613 |         auto findThreshold = | 
 | 614 |             sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical"); | 
 | 615 |         if (findThreshold == sensorMap.end()) | 
 | 616 |         { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 617 |             return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 618 |         } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 619 |         if (lowerCriticalThreshMask) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 620 |         { | 
 | 621 |             auto findLower = findThreshold->second.find("CriticalLow"); | 
 | 622 |             if (findLower == findThreshold->second.end()) | 
 | 623 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 624 |                 return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 625 |             } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 626 |             thresholdsToSet.emplace_back("CriticalLow", lowerCritical, | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 627 |                                          findThreshold->first); | 
 | 628 |         } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 629 |         if (upperCriticalThreshMask) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 630 |         { | 
 | 631 |             auto findUpper = findThreshold->second.find("CriticalHigh"); | 
 | 632 |             if (findUpper == findThreshold->second.end()) | 
 | 633 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 634 |                 return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 635 |             } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 636 |             thresholdsToSet.emplace_back("CriticalHigh", upperCritical, | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 637 |                                          findThreshold->first); | 
 | 638 |         } | 
 | 639 |     } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 640 |     if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 641 |     { | 
 | 642 |         auto findThreshold = | 
 | 643 |             sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning"); | 
 | 644 |         if (findThreshold == sensorMap.end()) | 
 | 645 |         { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 646 |             return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 647 |         } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 648 |         if (lowerNonCriticalThreshMask) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 649 |         { | 
 | 650 |             auto findLower = findThreshold->second.find("WarningLow"); | 
 | 651 |             if (findLower == findThreshold->second.end()) | 
 | 652 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 653 |                 return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 654 |             } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 655 |             thresholdsToSet.emplace_back("WarningLow", lowerNonCritical, | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 656 |                                          findThreshold->first); | 
 | 657 |         } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 658 |         if (upperNonCriticalThreshMask) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 659 |         { | 
 | 660 |             auto findUpper = findThreshold->second.find("WarningHigh"); | 
 | 661 |             if (findUpper == findThreshold->second.end()) | 
 | 662 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 663 |                 return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 664 |             } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 665 |             thresholdsToSet.emplace_back("WarningHigh", upperNonCritical, | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 666 |                                          findThreshold->first); | 
 | 667 |         } | 
 | 668 |     } | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 669 |     for (const auto& property : thresholdsToSet) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 670 |     { | 
 | 671 |         // from section 36.3 in the IPMI Spec, assume all linear | 
 | 672 |         double valueToSet = ((mValue * std::get<thresholdValue>(property)) + | 
| Josh Lehan | 86236a2 | 2019-11-18 17:53:33 -0800 | [diff] [blame] | 673 |                              (bValue * std::pow(10.0, bExp))) * | 
 | 674 |                             std::pow(10.0, rExp); | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 675 |         setDbusProperty( | 
 | 676 |             *getSdBus(), connection, path, std::get<interface>(property), | 
 | 677 |             std::get<propertyName>(property), ipmi::Value(valueToSet)); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 678 |     } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 679 |     return ipmi::responseSuccess(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 680 | } | 
 | 681 |  | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 682 | IPMIThresholds getIPMIThresholds(const SensorMap& sensorMap) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 683 | { | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 684 |     IPMIThresholds resp; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 685 |     auto warningInterface = | 
 | 686 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning"); | 
 | 687 |     auto criticalInterface = | 
 | 688 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical"); | 
 | 689 |  | 
 | 690 |     if ((warningInterface != sensorMap.end()) || | 
 | 691 |         (criticalInterface != sensorMap.end())) | 
 | 692 |     { | 
 | 693 |         auto sensorPair = sensorMap.find("xyz.openbmc_project.Sensor.Value"); | 
 | 694 |  | 
 | 695 |         if (sensorPair == sensorMap.end()) | 
 | 696 |         { | 
 | 697 |             // should not have been able to find a sensor not implementing | 
 | 698 |             // the sensor object | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 699 |             throw std::runtime_error("Invalid sensor map"); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 700 |         } | 
 | 701 |  | 
| Chen,Yugang | 606dd9f | 2019-07-01 10:37:30 +0800 | [diff] [blame] | 702 |         double max = 0; | 
 | 703 |         double min = 0; | 
| James Feist | aecaef7 | 2019-04-26 10:30:32 -0700 | [diff] [blame] | 704 |         getSensorMaxMin(sensorMap, max, min); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 705 |  | 
 | 706 |         int16_t mValue = 0; | 
 | 707 |         int16_t bValue = 0; | 
 | 708 |         int8_t rExp = 0; | 
 | 709 |         int8_t bExp = 0; | 
 | 710 |         bool bSigned = false; | 
 | 711 |  | 
 | 712 |         if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned)) | 
 | 713 |         { | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 714 |             throw std::runtime_error("Invalid sensor atrributes"); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 715 |         } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 716 |         if (warningInterface != sensorMap.end()) | 
 | 717 |         { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 718 |             auto& warningMap = warningInterface->second; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 719 |  | 
 | 720 |             auto warningHigh = warningMap.find("WarningHigh"); | 
 | 721 |             auto warningLow = warningMap.find("WarningLow"); | 
 | 722 |  | 
 | 723 |             if (warningHigh != warningMap.end()) | 
 | 724 |             { | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 725 |  | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 726 |                 double value = | 
 | 727 |                     std::visit(VariantToDoubleVisitor(), warningHigh->second); | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 728 |                 resp.warningHigh = scaleIPMIValueFromDouble( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 729 |                     value, mValue, rExp, bValue, bExp, bSigned); | 
 | 730 |             } | 
 | 731 |             if (warningLow != warningMap.end()) | 
 | 732 |             { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 733 |                 double value = | 
 | 734 |                     std::visit(VariantToDoubleVisitor(), warningLow->second); | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 735 |                 resp.warningLow = scaleIPMIValueFromDouble( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 736 |                     value, mValue, rExp, bValue, bExp, bSigned); | 
 | 737 |             } | 
 | 738 |         } | 
 | 739 |         if (criticalInterface != sensorMap.end()) | 
 | 740 |         { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 741 |             auto& criticalMap = criticalInterface->second; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 742 |  | 
 | 743 |             auto criticalHigh = criticalMap.find("CriticalHigh"); | 
 | 744 |             auto criticalLow = criticalMap.find("CriticalLow"); | 
 | 745 |  | 
 | 746 |             if (criticalHigh != criticalMap.end()) | 
 | 747 |             { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 748 |                 double value = | 
 | 749 |                     std::visit(VariantToDoubleVisitor(), criticalHigh->second); | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 750 |                 resp.criticalHigh = scaleIPMIValueFromDouble( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 751 |                     value, mValue, rExp, bValue, bExp, bSigned); | 
 | 752 |             } | 
 | 753 |             if (criticalLow != criticalMap.end()) | 
 | 754 |             { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 755 |                 double value = | 
 | 756 |                     std::visit(VariantToDoubleVisitor(), criticalLow->second); | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 757 |                 resp.criticalLow = scaleIPMIValueFromDouble( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 758 |                     value, mValue, rExp, bValue, bExp, bSigned); | 
 | 759 |             } | 
 | 760 |         } | 
 | 761 |     } | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 762 |     return resp; | 
 | 763 | } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 764 |  | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 765 | ipmi::RspType<uint8_t, // readable | 
 | 766 |               uint8_t, // lowerNCrit | 
 | 767 |               uint8_t, // lowerCrit | 
 | 768 |               uint8_t, // lowerNrecoverable | 
 | 769 |               uint8_t, // upperNC | 
 | 770 |               uint8_t, // upperCrit | 
 | 771 |               uint8_t> // upperNRecoverable | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 772 |     ipmiSenGetSensorThresholds(ipmi::Context::ptr ctx, uint8_t sensorNumber) | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 773 | { | 
 | 774 |     std::string connection; | 
 | 775 |     std::string path; | 
 | 776 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 777 |     auto status = getSensorConnection(ctx, sensorNumber, connection, path); | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 778 |     if (status) | 
 | 779 |     { | 
 | 780 |         return ipmi::response(status); | 
 | 781 |     } | 
 | 782 |  | 
 | 783 |     SensorMap sensorMap; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 784 |     if (!getSensorMap(ctx->yield, connection, path, sensorMap)) | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 785 |     { | 
 | 786 |         return ipmi::responseResponseError(); | 
 | 787 |     } | 
 | 788 |  | 
 | 789 |     IPMIThresholds thresholdData; | 
 | 790 |     try | 
 | 791 |     { | 
 | 792 |         thresholdData = getIPMIThresholds(sensorMap); | 
 | 793 |     } | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 794 |     catch (std::exception&) | 
| James Feist | 902c4c5 | 2019-04-16 14:51:31 -0700 | [diff] [blame] | 795 |     { | 
 | 796 |         return ipmi::responseResponseError(); | 
 | 797 |     } | 
 | 798 |  | 
 | 799 |     uint8_t readable = 0; | 
 | 800 |     uint8_t lowerNC = 0; | 
 | 801 |     uint8_t lowerCritical = 0; | 
 | 802 |     uint8_t lowerNonRecoverable = 0; | 
 | 803 |     uint8_t upperNC = 0; | 
 | 804 |     uint8_t upperCritical = 0; | 
 | 805 |     uint8_t upperNonRecoverable = 0; | 
 | 806 |  | 
 | 807 |     if (thresholdData.warningHigh) | 
 | 808 |     { | 
 | 809 |         readable |= | 
 | 810 |             1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperNonCritical); | 
 | 811 |         upperNC = *thresholdData.warningHigh; | 
 | 812 |     } | 
 | 813 |     if (thresholdData.warningLow) | 
 | 814 |     { | 
 | 815 |         readable |= | 
 | 816 |             1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerNonCritical); | 
 | 817 |         lowerNC = *thresholdData.warningLow; | 
 | 818 |     } | 
 | 819 |  | 
 | 820 |     if (thresholdData.criticalHigh) | 
 | 821 |     { | 
 | 822 |         readable |= | 
 | 823 |             1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperCritical); | 
 | 824 |         upperCritical = *thresholdData.criticalHigh; | 
 | 825 |     } | 
 | 826 |     if (thresholdData.criticalLow) | 
 | 827 |     { | 
 | 828 |         readable |= | 
 | 829 |             1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerCritical); | 
 | 830 |         lowerCritical = *thresholdData.criticalLow; | 
 | 831 |     } | 
 | 832 |  | 
 | 833 |     return ipmi::responseSuccess(readable, lowerNC, lowerCritical, | 
 | 834 |                                  lowerNonRecoverable, upperNC, upperCritical, | 
 | 835 |                                  upperNonRecoverable); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 836 | } | 
 | 837 |  | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 838 | /** @brief implements the get Sensor event enable command | 
 | 839 |  *  @param sensorNumber - sensor number | 
 | 840 |  * | 
 | 841 |  *  @returns IPMI completion code plus response data | 
 | 842 |  *   - enabled               - Sensor Event messages | 
 | 843 |  *   - assertionEnabledLsb   - Assertion event messages | 
 | 844 |  *   - assertionEnabledMsb   - Assertion event messages | 
 | 845 |  *   - deassertionEnabledLsb - Deassertion event messages | 
 | 846 |  *   - deassertionEnabledMsb - Deassertion event messages | 
 | 847 |  */ | 
 | 848 |  | 
 | 849 | ipmi::RspType<uint8_t, // enabled | 
 | 850 |               uint8_t, // assertionEnabledLsb | 
 | 851 |               uint8_t, // assertionEnabledMsb | 
 | 852 |               uint8_t, // deassertionEnabledLsb | 
 | 853 |               uint8_t> // deassertionEnabledMsb | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 854 |     ipmiSenGetSensorEventEnable(ipmi::Context::ptr ctx, uint8_t sensorNum) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 855 | { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 856 |     std::string connection; | 
 | 857 |     std::string path; | 
 | 858 |  | 
| Patrick Venture | a41714c | 2019-09-25 16:59:41 -0700 | [diff] [blame] | 859 |     uint8_t enabled = 0; | 
 | 860 |     uint8_t assertionEnabledLsb = 0; | 
 | 861 |     uint8_t assertionEnabledMsb = 0; | 
 | 862 |     uint8_t deassertionEnabledLsb = 0; | 
 | 863 |     uint8_t deassertionEnabledMsb = 0; | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 864 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 865 |     auto status = getSensorConnection(ctx, sensorNum, connection, path); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 866 |     if (status) | 
 | 867 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 868 |         return ipmi::response(status); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 869 |     } | 
 | 870 |  | 
 | 871 |     SensorMap sensorMap; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 872 |     if (!getSensorMap(ctx->yield, connection, path, sensorMap)) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 873 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 874 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 875 |     } | 
 | 876 |  | 
 | 877 |     auto warningInterface = | 
 | 878 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning"); | 
 | 879 |     auto criticalInterface = | 
 | 880 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical"); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 881 |     if ((warningInterface != sensorMap.end()) || | 
 | 882 |         (criticalInterface != sensorMap.end())) | 
 | 883 |     { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 884 |         enabled = static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 885 |             IPMISensorEventEnableByte2::sensorScanningEnable); | 
 | 886 |         if (warningInterface != sensorMap.end()) | 
 | 887 |         { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 888 |             auto& warningMap = warningInterface->second; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 889 |  | 
 | 890 |             auto warningHigh = warningMap.find("WarningHigh"); | 
 | 891 |             auto warningLow = warningMap.find("WarningLow"); | 
 | 892 |             if (warningHigh != warningMap.end()) | 
 | 893 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 894 |                 assertionEnabledLsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 895 |                     IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh); | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 896 |                 deassertionEnabledLsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 897 |                     IPMISensorEventEnableThresholds::upperNonCriticalGoingLow); | 
 | 898 |             } | 
 | 899 |             if (warningLow != warningMap.end()) | 
 | 900 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 901 |                 assertionEnabledLsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 902 |                     IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow); | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 903 |                 deassertionEnabledLsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 904 |                     IPMISensorEventEnableThresholds::lowerNonCriticalGoingHigh); | 
 | 905 |             } | 
 | 906 |         } | 
 | 907 |         if (criticalInterface != sensorMap.end()) | 
 | 908 |         { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 909 |             auto& criticalMap = criticalInterface->second; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 910 |  | 
 | 911 |             auto criticalHigh = criticalMap.find("CriticalHigh"); | 
 | 912 |             auto criticalLow = criticalMap.find("CriticalLow"); | 
 | 913 |  | 
 | 914 |             if (criticalHigh != criticalMap.end()) | 
 | 915 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 916 |                 assertionEnabledMsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 917 |                     IPMISensorEventEnableThresholds::upperCriticalGoingHigh); | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 918 |                 deassertionEnabledMsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 919 |                     IPMISensorEventEnableThresholds::upperCriticalGoingLow); | 
 | 920 |             } | 
 | 921 |             if (criticalLow != criticalMap.end()) | 
 | 922 |             { | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 923 |                 assertionEnabledLsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 924 |                     IPMISensorEventEnableThresholds::lowerCriticalGoingLow); | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 925 |                 deassertionEnabledLsb |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 926 |                     IPMISensorEventEnableThresholds::lowerCriticalGoingHigh); | 
 | 927 |             } | 
 | 928 |         } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 929 |     } | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 930 |  | 
 | 931 |     return ipmi::responseSuccess(enabled, assertionEnabledLsb, | 
 | 932 |                                  assertionEnabledMsb, deassertionEnabledLsb, | 
 | 933 |                                  deassertionEnabledMsb); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 934 | } | 
 | 935 |  | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 936 | /** @brief implements the get Sensor event status command | 
 | 937 |  *  @param sensorNumber - sensor number, FFh = reserved | 
 | 938 |  * | 
 | 939 |  *  @returns IPMI completion code plus response data | 
 | 940 |  *   - sensorEventStatus - Sensor Event messages state | 
 | 941 |  *   - assertions        - Assertion event messages | 
 | 942 |  *   - deassertions      - Deassertion event messages | 
 | 943 |  */ | 
 | 944 | ipmi::RspType<uint8_t,         // sensorEventStatus | 
 | 945 |               std::bitset<16>, // assertions | 
 | 946 |               std::bitset<16>  // deassertion | 
 | 947 |               > | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 948 |     ipmiSenGetSensorEventStatus(ipmi::Context::ptr ctx, uint8_t sensorNum) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 949 | { | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 950 |     if (sensorNum == reservedSensorNumber) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 951 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 952 |         return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 953 |     } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 954 |  | 
 | 955 |     std::string connection; | 
 | 956 |     std::string path; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 957 |     auto status = getSensorConnection(ctx, sensorNum, connection, path); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 958 |     if (status) | 
 | 959 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 960 |         phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 961 |             "ipmiSenGetSensorEventStatus: Sensor connection Error", | 
 | 962 |             phosphor::logging::entry("SENSOR=%d", sensorNum)); | 
 | 963 |         return ipmi::response(status); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 964 |     } | 
 | 965 |  | 
 | 966 |     SensorMap sensorMap; | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 967 |     if (!getSensorMap(ctx->yield, connection, path, sensorMap)) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 968 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 969 |         phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 970 |             "ipmiSenGetSensorEventStatus: Sensor Mapping Error", | 
 | 971 |             phosphor::logging::entry("SENSOR=%s", path.c_str())); | 
 | 972 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 973 |     } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 974 |     auto warningInterface = | 
 | 975 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning"); | 
 | 976 |     auto criticalInterface = | 
 | 977 |         sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical"); | 
 | 978 |  | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 979 |     uint8_t sensorEventStatus = | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 980 |         static_cast<uint8_t>(IPMISensorEventEnableByte2::sensorScanningEnable); | 
 | 981 |  | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 982 |     std::optional<bool> criticalDeassertHigh = | 
 | 983 |         thresholdDeassertMap[path]["CriticalAlarmHigh"]; | 
 | 984 |     std::optional<bool> criticalDeassertLow = | 
 | 985 |         thresholdDeassertMap[path]["CriticalAlarmLow"]; | 
 | 986 |     std::optional<bool> warningDeassertHigh = | 
 | 987 |         thresholdDeassertMap[path]["WarningAlarmHigh"]; | 
 | 988 |     std::optional<bool> warningDeassertLow = | 
 | 989 |         thresholdDeassertMap[path]["WarningAlarmLow"]; | 
 | 990 |  | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 991 |     std::bitset<16> assertions = 0; | 
 | 992 |     std::bitset<16> deassertions = 0; | 
 | 993 |  | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 994 |     if (criticalDeassertHigh && !*criticalDeassertHigh) | 
 | 995 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 996 |         deassertions.set(static_cast<size_t>( | 
 | 997 |             IPMIGetSensorEventEnableThresholds::upperCriticalGoingHigh)); | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 998 |     } | 
 | 999 |     if (criticalDeassertLow && !*criticalDeassertLow) | 
 | 1000 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1001 |         deassertions.set(static_cast<size_t>( | 
 | 1002 |             IPMIGetSensorEventEnableThresholds::upperCriticalGoingLow)); | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 1003 |     } | 
 | 1004 |     if (warningDeassertHigh && !*warningDeassertHigh) | 
 | 1005 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1006 |         deassertions.set(static_cast<size_t>( | 
 | 1007 |             IPMIGetSensorEventEnableThresholds::upperNonCriticalGoingHigh)); | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 1008 |     } | 
 | 1009 |     if (warningDeassertLow && !*warningDeassertLow) | 
 | 1010 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1011 |         deassertions.set(static_cast<size_t>( | 
 | 1012 |             IPMIGetSensorEventEnableThresholds::lowerNonCriticalGoingHigh)); | 
| James Feist | 392786a | 2019-03-19 13:36:10 -0700 | [diff] [blame] | 1013 |     } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1014 |     if ((warningInterface != sensorMap.end()) || | 
 | 1015 |         (criticalInterface != sensorMap.end())) | 
 | 1016 |     { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1017 |         sensorEventStatus = static_cast<size_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1018 |             IPMISensorEventEnableByte2::eventMessagesEnable); | 
 | 1019 |         if (warningInterface != sensorMap.end()) | 
 | 1020 |         { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 1021 |             auto& warningMap = warningInterface->second; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1022 |  | 
 | 1023 |             auto warningHigh = warningMap.find("WarningAlarmHigh"); | 
 | 1024 |             auto warningLow = warningMap.find("WarningAlarmLow"); | 
 | 1025 |             auto warningHighAlarm = false; | 
 | 1026 |             auto warningLowAlarm = false; | 
 | 1027 |  | 
 | 1028 |             if (warningHigh != warningMap.end()) | 
 | 1029 |             { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 1030 |                 warningHighAlarm = std::get<bool>(warningHigh->second); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1031 |             } | 
 | 1032 |             if (warningLow != warningMap.end()) | 
 | 1033 |             { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 1034 |                 warningLowAlarm = std::get<bool>(warningLow->second); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1035 |             } | 
 | 1036 |             if (warningHighAlarm) | 
 | 1037 |             { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1038 |                 assertions.set( | 
 | 1039 |                     static_cast<size_t>(IPMIGetSensorEventEnableThresholds:: | 
 | 1040 |                                             upperNonCriticalGoingHigh)); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1041 |             } | 
 | 1042 |             if (warningLowAlarm) | 
 | 1043 |             { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1044 |                 assertions.set( | 
 | 1045 |                     static_cast<size_t>(IPMIGetSensorEventEnableThresholds:: | 
 | 1046 |                                             lowerNonCriticalGoingLow)); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1047 |             } | 
 | 1048 |         } | 
 | 1049 |         if (criticalInterface != sensorMap.end()) | 
 | 1050 |         { | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 1051 |             auto& criticalMap = criticalInterface->second; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1052 |  | 
 | 1053 |             auto criticalHigh = criticalMap.find("CriticalAlarmHigh"); | 
 | 1054 |             auto criticalLow = criticalMap.find("CriticalAlarmLow"); | 
 | 1055 |             auto criticalHighAlarm = false; | 
 | 1056 |             auto criticalLowAlarm = false; | 
 | 1057 |  | 
 | 1058 |             if (criticalHigh != criticalMap.end()) | 
 | 1059 |             { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 1060 |                 criticalHighAlarm = std::get<bool>(criticalHigh->second); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1061 |             } | 
 | 1062 |             if (criticalLow != criticalMap.end()) | 
 | 1063 |             { | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 1064 |                 criticalLowAlarm = std::get<bool>(criticalLow->second); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1065 |             } | 
 | 1066 |             if (criticalHighAlarm) | 
 | 1067 |             { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1068 |                 assertions.set( | 
 | 1069 |                     static_cast<size_t>(IPMIGetSensorEventEnableThresholds:: | 
 | 1070 |                                             upperCriticalGoingHigh)); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1071 |             } | 
 | 1072 |             if (criticalLowAlarm) | 
 | 1073 |             { | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1074 |                 assertions.set(static_cast<size_t>( | 
 | 1075 |                     IPMIGetSensorEventEnableThresholds::lowerCriticalGoingLow)); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1076 |             } | 
 | 1077 |         } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1078 |     } | 
 | 1079 |  | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1080 |     return ipmi::responseSuccess(sensorEventStatus, assertions, deassertions); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1081 | } | 
 | 1082 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1083 | static int getSensorDataRecords(ipmi::Context::ptr ctx) | 
 | 1084 | { | 
 | 1085 |  | 
 | 1086 |     size_t recordID = 0; | 
 | 1087 |     size_t fruCount = 0; | 
 | 1088 |  | 
 | 1089 |     ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount); | 
 | 1090 |     if (ret != ipmi::ccSuccess) | 
 | 1091 |     { | 
 | 1092 |         return GENERAL_ERROR; | 
 | 1093 |     } | 
 | 1094 |  | 
 | 1095 |     size_t lastRecord = sensorTree.size() + fruCount + | 
 | 1096 |                         ipmi::storage::type12Count + | 
 | 1097 |                         ipmi::storage::nmDiscoverySDRCount - 1; | 
 | 1098 |     if (lastRecord > lastRecordIndex) | 
 | 1099 |     { | 
 | 1100 |         return GENERAL_ERROR; | 
 | 1101 |     } | 
 | 1102 |  | 
 | 1103 |     std::string connection; | 
 | 1104 |     std::string path; | 
 | 1105 |     for (const auto& sensor : sensorTree) | 
 | 1106 |     { | 
 | 1107 |  | 
 | 1108 |         connection = sensor.second.begin()->first; | 
 | 1109 |         path = sensor.first; | 
 | 1110 |  | 
 | 1111 |         SensorMap sensorMap; | 
| Alex Qiu | 09701ef | 2020-07-15 17:56:21 -0700 | [diff] [blame^] | 1112 |         if (!getSensorMap(ctx->yield, connection, path, sensorMap, | 
 | 1113 |                           sensorMapSdrUpdatePeriod)) | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1114 |         { | 
 | 1115 |             return GENERAL_ERROR; | 
 | 1116 |         } | 
 | 1117 |         uint16_t sensorNum = getSensorNumberFromPath(path); | 
 | 1118 |         if (sensorNum == invalidSensorNumber) | 
 | 1119 |         { | 
 | 1120 |             return GENERAL_ERROR; | 
 | 1121 |         } | 
 | 1122 |         uint8_t sensornumber = static_cast<uint8_t>(sensorNum); | 
 | 1123 |         uint8_t lun = static_cast<uint8_t>(sensorNum >> 8); | 
 | 1124 |  | 
 | 1125 |         get_sdr::SensorDataFullRecord record = {0}; | 
 | 1126 |  | 
 | 1127 |         get_sdr::header::set_record_id( | 
 | 1128 |             recordID, | 
 | 1129 |             reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&record)); | 
 | 1130 |         record.header.sdr_version = ipmiSdrVersion; | 
 | 1131 |         record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; | 
 | 1132 |         record.header.record_length = sizeof(get_sdr::SensorDataFullRecord) - | 
 | 1133 |                                       sizeof(get_sdr::SensorDataRecordHeader); | 
 | 1134 |         record.key.owner_id = 0x20; | 
 | 1135 |         record.key.owner_lun = lun; | 
 | 1136 |         record.key.sensor_number = sensornumber; | 
 | 1137 |  | 
 | 1138 |         record.body.sensor_capabilities = 0x68; // auto rearm - todo hysteresis | 
 | 1139 |         record.body.sensor_type = getSensorTypeFromPath(path); | 
 | 1140 |         std::string type = getSensorTypeStringFromPath(path); | 
 | 1141 |         auto typeCstr = type.c_str(); | 
 | 1142 |         auto findUnits = sensorUnits.find(typeCstr); | 
 | 1143 |         if (findUnits != sensorUnits.end()) | 
 | 1144 |         { | 
 | 1145 |             record.body.sensor_units_2_base = | 
 | 1146 |                 static_cast<uint8_t>(findUnits->second); | 
 | 1147 |         } // else default 0x0 unspecified | 
 | 1148 |  | 
 | 1149 |         record.body.event_reading_type = getSensorEventTypeFromPath(path); | 
 | 1150 |  | 
 | 1151 |         auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value"); | 
 | 1152 |         if (sensorObject == sensorMap.end()) | 
 | 1153 |         { | 
 | 1154 |             return GENERAL_ERROR; | 
 | 1155 |         } | 
 | 1156 |  | 
 | 1157 |         uint8_t entityId = 0; | 
 | 1158 |         uint8_t entityInstance = 0x01; | 
 | 1159 |  | 
 | 1160 |         // follow the association chain to get the parent board's entityid and | 
 | 1161 |         // entityInstance | 
 | 1162 |         updateIpmiFromAssociation(path, sensorMap, entityId, entityInstance); | 
 | 1163 |  | 
 | 1164 |         record.body.entity_id = entityId; | 
 | 1165 |         record.body.entity_instance = entityInstance; | 
 | 1166 |  | 
 | 1167 |         auto maxObject = sensorObject->second.find("MaxValue"); | 
 | 1168 |         auto minObject = sensorObject->second.find("MinValue"); | 
 | 1169 |  | 
 | 1170 |         // If min and/or max are left unpopulated, | 
 | 1171 |         // then default to what a signed byte would be, namely (-128,127) range. | 
 | 1172 |         auto max = static_cast<double>(std::numeric_limits<int8_t>::max()); | 
 | 1173 |         auto min = static_cast<double>(std::numeric_limits<int8_t>::lowest()); | 
 | 1174 |         if (maxObject != sensorObject->second.end()) | 
 | 1175 |         { | 
 | 1176 |             max = std::visit(VariantToDoubleVisitor(), maxObject->second); | 
 | 1177 |         } | 
 | 1178 |  | 
 | 1179 |         if (minObject != sensorObject->second.end()) | 
 | 1180 |         { | 
 | 1181 |             min = std::visit(VariantToDoubleVisitor(), minObject->second); | 
 | 1182 |         } | 
 | 1183 |  | 
 | 1184 |         int16_t mValue = 0; | 
 | 1185 |         int8_t rExp = 0; | 
 | 1186 |         int16_t bValue = 0; | 
 | 1187 |         int8_t bExp = 0; | 
 | 1188 |         bool bSigned = false; | 
 | 1189 |  | 
 | 1190 |         if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned)) | 
 | 1191 |         { | 
 | 1192 |             return GENERAL_ERROR; | 
 | 1193 |         } | 
 | 1194 |  | 
 | 1195 |         // The record.body is a struct SensorDataFullRecordBody | 
 | 1196 |         // from sensorhandler.hpp in phosphor-ipmi-host. | 
 | 1197 |         // The meaning of these bits appears to come from | 
 | 1198 |         // table 43.1 of the IPMI spec. | 
 | 1199 |         // The above 5 sensor attributes are stuffed in as follows: | 
 | 1200 |         // Byte 21 = AA000000 = analog interpretation, 10 signed, 00 unsigned | 
 | 1201 |         // Byte 22-24 are for other purposes | 
 | 1202 |         // Byte 25 = MMMMMMMM = LSB of M | 
 | 1203 |         // Byte 26 = MMTTTTTT = MSB of M (signed), and Tolerance | 
 | 1204 |         // Byte 27 = BBBBBBBB = LSB of B | 
 | 1205 |         // Byte 28 = BBAAAAAA = MSB of B (signed), and LSB of Accuracy | 
 | 1206 |         // Byte 29 = AAAAEE00 = MSB of Accuracy, exponent of Accuracy | 
 | 1207 |         // Byte 30 = RRRRBBBB = rExp (signed), bExp (signed) | 
 | 1208 |  | 
 | 1209 |         // apply M, B, and exponents, M and B are 10 bit values, exponents are 4 | 
 | 1210 |         record.body.m_lsb = mValue & 0xFF; | 
 | 1211 |  | 
 | 1212 |         uint8_t mBitSign = (mValue < 0) ? 1 : 0; | 
 | 1213 |         uint8_t mBitNine = (mValue & 0x0100) >> 8; | 
 | 1214 |  | 
 | 1215 |         // move the smallest bit of the MSB into place (bit 9) | 
 | 1216 |         // the MSbs are bits 7:8 in m_msb_and_tolerance | 
 | 1217 |         record.body.m_msb_and_tolerance = (mBitSign << 7) | (mBitNine << 6); | 
 | 1218 |  | 
 | 1219 |         record.body.b_lsb = bValue & 0xFF; | 
 | 1220 |  | 
 | 1221 |         uint8_t bBitSign = (bValue < 0) ? 1 : 0; | 
 | 1222 |         uint8_t bBitNine = (bValue & 0x0100) >> 8; | 
 | 1223 |  | 
 | 1224 |         // move the smallest bit of the MSB into place (bit 9) | 
 | 1225 |         // the MSbs are bits 7:8 in b_msb_and_accuracy_lsb | 
 | 1226 |         record.body.b_msb_and_accuracy_lsb = (bBitSign << 7) | (bBitNine << 6); | 
 | 1227 |  | 
 | 1228 |         uint8_t rExpSign = (rExp < 0) ? 1 : 0; | 
 | 1229 |         uint8_t rExpBits = rExp & 0x07; | 
 | 1230 |  | 
 | 1231 |         uint8_t bExpSign = (bExp < 0) ? 1 : 0; | 
 | 1232 |         uint8_t bExpBits = bExp & 0x07; | 
 | 1233 |  | 
 | 1234 |         // move rExp and bExp into place | 
 | 1235 |         record.body.r_b_exponents = | 
 | 1236 |             (rExpSign << 7) | (rExpBits << 4) | (bExpSign << 3) | bExpBits; | 
 | 1237 |  | 
 | 1238 |         // Set the analog reading byte interpretation accordingly | 
 | 1239 |         record.body.sensor_units_1 = (bSigned ? 1 : 0) << 7; | 
 | 1240 |  | 
 | 1241 |         // TODO(): Perhaps care about Tolerance, Accuracy, and so on | 
 | 1242 |         // These seem redundant, but derivable from the above 5 attributes | 
 | 1243 |         // Original comment said "todo fill out rest of units" | 
 | 1244 |  | 
 | 1245 |         // populate sensor name from path | 
 | 1246 |         std::string name; | 
 | 1247 |         size_t nameStart = path.rfind("/"); | 
 | 1248 |         if (nameStart != std::string::npos) | 
 | 1249 |         { | 
 | 1250 |             name = path.substr(nameStart + 1, std::string::npos - nameStart); | 
 | 1251 |         } | 
 | 1252 |  | 
 | 1253 |         std::replace(name.begin(), name.end(), '_', ' '); | 
 | 1254 |         if (name.size() > FULL_RECORD_ID_STR_MAX_LENGTH) | 
 | 1255 |         { | 
 | 1256 |             // try to not truncate by replacing common words | 
 | 1257 |             constexpr std::array<std::pair<const char*, const char*>, 2> | 
 | 1258 |                 replaceWords = {std::make_pair("Output", "Out"), | 
 | 1259 |                                 std::make_pair("Input", "In")}; | 
 | 1260 |             for (const auto& [find, replace] : replaceWords) | 
 | 1261 |             { | 
 | 1262 |                 boost::replace_all(name, find, replace); | 
 | 1263 |             } | 
 | 1264 |  | 
 | 1265 |             name.resize(FULL_RECORD_ID_STR_MAX_LENGTH); | 
 | 1266 |         } | 
 | 1267 |         record.body.id_string_info = name.size(); | 
 | 1268 |         std::strncpy(record.body.id_string, name.c_str(), | 
 | 1269 |                      sizeof(record.body.id_string)); | 
 | 1270 |  | 
 | 1271 |         IPMIThresholds thresholdData; | 
 | 1272 |         try | 
 | 1273 |         { | 
 | 1274 |             thresholdData = getIPMIThresholds(sensorMap); | 
 | 1275 |         } | 
 | 1276 |         catch (std::exception&) | 
 | 1277 |         { | 
 | 1278 |             return GENERAL_ERROR; | 
 | 1279 |         } | 
 | 1280 |  | 
 | 1281 |         if (thresholdData.criticalHigh) | 
 | 1282 |         { | 
 | 1283 |             record.body.upper_critical_threshold = *thresholdData.criticalHigh; | 
 | 1284 |             record.body.supported_deassertions[1] |= static_cast<uint8_t>( | 
 | 1285 |                 IPMISensorEventEnableThresholds::criticalThreshold); | 
 | 1286 |             record.body.supported_deassertions[1] |= static_cast<uint8_t>( | 
 | 1287 |                 IPMISensorEventEnableThresholds::upperCriticalGoingHigh); | 
 | 1288 |             record.body.supported_assertions[1] |= static_cast<uint8_t>( | 
 | 1289 |                 IPMISensorEventEnableThresholds::upperCriticalGoingHigh); | 
 | 1290 |             record.body.discrete_reading_setting_mask[0] |= | 
 | 1291 |                 static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical); | 
 | 1292 |         } | 
 | 1293 |         if (thresholdData.warningHigh) | 
 | 1294 |         { | 
 | 1295 |             record.body.upper_noncritical_threshold = | 
 | 1296 |                 *thresholdData.warningHigh; | 
 | 1297 |             record.body.supported_deassertions[1] |= static_cast<uint8_t>( | 
 | 1298 |                 IPMISensorEventEnableThresholds::nonCriticalThreshold); | 
 | 1299 |             record.body.supported_deassertions[0] |= static_cast<uint8_t>( | 
 | 1300 |                 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh); | 
 | 1301 |             record.body.supported_assertions[0] |= static_cast<uint8_t>( | 
 | 1302 |                 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh); | 
 | 1303 |             record.body.discrete_reading_setting_mask[0] |= | 
 | 1304 |                 static_cast<uint8_t>(IPMISensorReadingByte3::upperNonCritical); | 
 | 1305 |         } | 
 | 1306 |         if (thresholdData.criticalLow) | 
 | 1307 |         { | 
 | 1308 |             record.body.lower_critical_threshold = *thresholdData.criticalLow; | 
 | 1309 |             record.body.supported_assertions[1] |= static_cast<uint8_t>( | 
 | 1310 |                 IPMISensorEventEnableThresholds::criticalThreshold); | 
 | 1311 |             record.body.supported_deassertions[0] |= static_cast<uint8_t>( | 
 | 1312 |                 IPMISensorEventEnableThresholds::lowerCriticalGoingLow); | 
 | 1313 |             record.body.supported_assertions[0] |= static_cast<uint8_t>( | 
 | 1314 |                 IPMISensorEventEnableThresholds::lowerCriticalGoingLow); | 
 | 1315 |             record.body.discrete_reading_setting_mask[0] |= | 
 | 1316 |                 static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical); | 
 | 1317 |         } | 
 | 1318 |         if (thresholdData.warningLow) | 
 | 1319 |         { | 
 | 1320 |             record.body.lower_noncritical_threshold = *thresholdData.warningLow; | 
 | 1321 |             record.body.supported_assertions[1] |= static_cast<uint8_t>( | 
 | 1322 |                 IPMISensorEventEnableThresholds::nonCriticalThreshold); | 
 | 1323 |             record.body.supported_deassertions[0] |= static_cast<uint8_t>( | 
 | 1324 |                 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow); | 
 | 1325 |             record.body.supported_assertions[0] |= static_cast<uint8_t>( | 
 | 1326 |                 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow); | 
 | 1327 |             record.body.discrete_reading_setting_mask[0] |= | 
 | 1328 |                 static_cast<uint8_t>(IPMISensorReadingByte3::lowerNonCritical); | 
 | 1329 |         } | 
 | 1330 |  | 
 | 1331 |         // everything that is readable is setable | 
 | 1332 |         record.body.discrete_reading_setting_mask[1] = | 
 | 1333 |             record.body.discrete_reading_setting_mask[0]; | 
 | 1334 |  | 
 | 1335 |         // insert the record into the map | 
 | 1336 |         std::vector<uint8_t> sdr; | 
 | 1337 |         sdr.insert(sdr.end(), (uint8_t*)&record, | 
 | 1338 |                    ((uint8_t*)&record) + sizeof(record)); | 
 | 1339 |         sensorDataRecords.insert_or_assign(recordID, sdr); | 
 | 1340 |         recordID++; | 
 | 1341 |     } | 
 | 1342 |  | 
 | 1343 |     size_t nonSensorRecCount = fruCount + ipmi::storage::type12Count + | 
 | 1344 |                                ipmi::storage::nmDiscoverySDRCount; | 
 | 1345 |     size_t type12End = fruCount + ipmi::storage::type12Count; | 
 | 1346 |     do | 
 | 1347 |     { | 
 | 1348 |         size_t fruIndex = recordID - sensorTree.size(); | 
 | 1349 |  | 
 | 1350 |         if (fruIndex >= type12End) | 
 | 1351 |         { | 
 | 1352 |             // NM discovery SDR | 
 | 1353 |             size_t nmDiscoveryIndex = fruIndex - type12End; | 
 | 1354 |             if (nmDiscoveryIndex >= ipmi::storage::nmDiscoverySDRCount) | 
 | 1355 |             { | 
 | 1356 |                 return GENERAL_ERROR; | 
 | 1357 |             } | 
 | 1358 |  | 
 | 1359 |             std::vector<uint8_t> record = | 
 | 1360 |                 ipmi::storage::getNMDiscoverySDR(nmDiscoveryIndex, recordID); | 
 | 1361 |             sensorDataRecords.insert_or_assign(recordID, record); | 
 | 1362 |         } | 
 | 1363 |         else if (fruIndex >= fruCount) | 
 | 1364 |         { | 
 | 1365 |             // handle type 12 hardcoded records | 
 | 1366 |             size_t type12Index = fruIndex - fruCount; | 
 | 1367 |             if (type12Index >= ipmi::storage::type12Count) | 
 | 1368 |             { | 
 | 1369 |                 return GENERAL_ERROR; | 
 | 1370 |             } | 
 | 1371 |             std::vector<uint8_t> record = | 
 | 1372 |                 ipmi::storage::getType12SDRs(type12Index, recordID); | 
 | 1373 |             sensorDataRecords.insert_or_assign(recordID, record); | 
 | 1374 |         } | 
 | 1375 |         else | 
 | 1376 |         { | 
 | 1377 |             // handle fru records | 
 | 1378 |             get_sdr::SensorDataFruRecord data; | 
 | 1379 |             ret = ipmi::storage::getFruSdrs(ctx, fruIndex, data); | 
 | 1380 |             if (ret != IPMI_CC_OK) | 
 | 1381 |             { | 
 | 1382 |                 return GENERAL_ERROR; | 
 | 1383 |             } | 
 | 1384 |             get_sdr::header::set_record_id( | 
 | 1385 |                 recordID, | 
 | 1386 |                 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&data)); | 
 | 1387 |  | 
 | 1388 |             std::vector<uint8_t> record; | 
 | 1389 |             record.insert(record.end(), (uint8_t*)&data, | 
 | 1390 |                           ((uint8_t*)&data) + sizeof(data)); | 
 | 1391 |             sensorDataRecords.insert_or_assign(recordID, record); | 
 | 1392 |         } | 
 | 1393 |         recordID++; | 
 | 1394 |     } while (--nonSensorRecCount); | 
 | 1395 |     return 0; | 
 | 1396 | } | 
 | 1397 |  | 
 | 1398 | /** @brief implements the get SDR Info command | 
 | 1399 |  *  @param count - Operation | 
 | 1400 |  * | 
 | 1401 |  *  @returns IPMI completion code plus response data | 
 | 1402 |  *   - sdrCount - sensor/SDR count | 
 | 1403 |  *   - lunsAndDynamicPopulation - static/Dynamic sensor population flag | 
 | 1404 |  */ | 
 | 1405 | static ipmi::RspType<uint8_t, // respcount | 
 | 1406 |                      uint8_t, // dynamic population flags | 
 | 1407 |                      uint32_t // last time a sensor was added | 
 | 1408 |                      > | 
 | 1409 |     ipmiSensorGetDeviceSdrInfo(ipmi::Context::ptr ctx, | 
 | 1410 |                                std::optional<uint8_t> count) | 
 | 1411 | { | 
 | 1412 |     uint8_t sdrCount = 0; | 
 | 1413 |     // Sensors are dynamically allocated, and there is at least one LUN | 
 | 1414 |     uint8_t lunsAndDynamicPopulation = 0x80; | 
 | 1415 |     constexpr uint8_t getSdrCount = 0x01; | 
 | 1416 |     constexpr uint8_t getSensorCount = 0x00; | 
 | 1417 |  | 
 | 1418 |     if (!getSensorSubtree(sensorTree) || sensorTree.empty()) | 
 | 1419 |     { | 
 | 1420 |         return ipmi::responseResponseError(); | 
 | 1421 |     } | 
 | 1422 |  | 
 | 1423 |     if (sensorDataRecords.empty() && getSensorDataRecords(ctx)) | 
 | 1424 |     { | 
 | 1425 |         return ipmi::responseResponseError(); | 
 | 1426 |     } | 
 | 1427 |  | 
 | 1428 |     uint16_t numSensors = sensorTree.size(); | 
 | 1429 |     if (count.value_or(0) == getSdrCount) | 
 | 1430 |     { | 
 | 1431 |         // Count the number of Type 1 SDR entries assigned to the LUN | 
 | 1432 |         for (auto sdr : sensorDataRecords) | 
 | 1433 |         { | 
 | 1434 |             get_sdr::SensorDataRecordHeader* hdr = | 
 | 1435 |                 reinterpret_cast<get_sdr::SensorDataRecordHeader*>( | 
 | 1436 |                     sdr.second.data()); | 
 | 1437 |             if (hdr->record_type == get_sdr::SENSOR_DATA_FULL_RECORD) | 
 | 1438 |             { | 
 | 1439 |                 get_sdr::SensorDataFullRecord* record = | 
 | 1440 |                     reinterpret_cast<get_sdr::SensorDataFullRecord*>( | 
 | 1441 |                         sdr.second.data()); | 
 | 1442 |                 if (ctx->lun == record->key.owner_lun) | 
 | 1443 |                 { | 
 | 1444 |                     sdrCount++; | 
 | 1445 |                 } | 
 | 1446 |             } | 
 | 1447 |         } | 
 | 1448 |     } | 
 | 1449 |     else if (count.value_or(0) == getSensorCount) | 
 | 1450 |     { | 
 | 1451 |         // Return the number of sensors attached to the LUN | 
 | 1452 |         if ((ctx->lun == 0) && (numSensors > 0)) | 
 | 1453 |         { | 
 | 1454 |             sdrCount = | 
 | 1455 |                 (numSensors > maxSensorsPerLUN) ? maxSensorsPerLUN : numSensors; | 
 | 1456 |         } | 
 | 1457 |         else if ((ctx->lun == 1) && (numSensors > maxSensorsPerLUN)) | 
 | 1458 |         { | 
 | 1459 |             sdrCount = (numSensors > (2 * maxSensorsPerLUN)) | 
 | 1460 |                            ? maxSensorsPerLUN | 
 | 1461 |                            : (numSensors - maxSensorsPerLUN) & maxSensorsPerLUN; | 
 | 1462 |         } | 
 | 1463 |         else if (ctx->lun == 3) | 
 | 1464 |         { | 
 | 1465 |             if (numSensors <= maxIPMISensors) | 
 | 1466 |             { | 
 | 1467 |                 sdrCount = | 
 | 1468 |                     (numSensors - (2 * maxSensorsPerLUN)) & maxSensorsPerLUN; | 
 | 1469 |             } | 
 | 1470 |             else | 
 | 1471 |             { | 
 | 1472 |                 // error | 
 | 1473 |                 throw std::out_of_range( | 
 | 1474 |                     "Maximum number of IPMI sensors exceeded."); | 
 | 1475 |             } | 
 | 1476 |         } | 
 | 1477 |     } | 
 | 1478 |     else | 
 | 1479 |     { | 
 | 1480 |         return ipmi::responseInvalidFieldRequest(); | 
 | 1481 |     } | 
 | 1482 |  | 
 | 1483 |     // Get Sensor count. This returns the number of sensors | 
 | 1484 |     if (numSensors > 0) | 
 | 1485 |     { | 
 | 1486 |         lunsAndDynamicPopulation |= 1; | 
 | 1487 |     } | 
 | 1488 |     if (numSensors > maxSensorsPerLUN) | 
 | 1489 |     { | 
 | 1490 |         lunsAndDynamicPopulation |= 2; | 
 | 1491 |     } | 
 | 1492 |     if (numSensors >= (maxSensorsPerLUN * 2)) | 
 | 1493 |     { | 
 | 1494 |         lunsAndDynamicPopulation |= 8; | 
 | 1495 |     } | 
 | 1496 |     if (numSensors > maxIPMISensors) | 
 | 1497 |     { | 
 | 1498 |         // error | 
 | 1499 |         throw std::out_of_range("Maximum number of IPMI sensors exceeded."); | 
 | 1500 |     } | 
 | 1501 |  | 
 | 1502 |     return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation, | 
 | 1503 |                                  sdrLastAdd); | 
 | 1504 | } | 
 | 1505 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1506 | /* end sensor commands */ | 
 | 1507 |  | 
 | 1508 | /* storage commands */ | 
 | 1509 |  | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1510 | ipmi::RspType<uint8_t,  // sdr version | 
 | 1511 |               uint16_t, // record count | 
 | 1512 |               uint16_t, // free space | 
 | 1513 |               uint32_t, // most recent addition | 
 | 1514 |               uint32_t, // most recent erase | 
 | 1515 |               uint8_t   // operationSupport | 
 | 1516 |               > | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 1517 |     ipmiStorageGetSDRRepositoryInfo(ipmi::Context::ptr ctx) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1518 | { | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1519 |     constexpr const uint16_t unspecifiedFreeSpace = 0xFFFF; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1520 |     if (sensorTree.empty() && !getSensorSubtree(sensorTree)) | 
 | 1521 |     { | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1522 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1523 |     } | 
 | 1524 |  | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1525 |     size_t fruCount = 0; | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 1526 |     ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount); | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1527 |     if (ret != ipmi::ccSuccess) | 
 | 1528 |     { | 
 | 1529 |         return ipmi::response(ret); | 
 | 1530 |     } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1531 |  | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1532 |     uint16_t recordCount = | 
 | 1533 |         sensorTree.size() + fruCount + ipmi::storage::type12Count; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1534 |  | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1535 |     uint8_t operationSupport = static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1536 |         SdrRepositoryInfoOps::overflow); // write not supported | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1537 |  | 
 | 1538 |     operationSupport |= | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1539 |         static_cast<uint8_t>(SdrRepositoryInfoOps::allocCommandSupported); | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1540 |     operationSupport |= static_cast<uint8_t>( | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1541 |         SdrRepositoryInfoOps::reserveSDRRepositoryCommandSupported); | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1542 |     return ipmi::responseSuccess(ipmiSdrVersion, recordCount, | 
 | 1543 |                                  unspecifiedFreeSpace, sdrLastAdd, | 
 | 1544 |                                  sdrLastRemove, operationSupport); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1545 | } | 
 | 1546 |  | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1547 | /** @brief implements the get SDR allocation info command | 
 | 1548 |  * | 
 | 1549 |  *  @returns IPMI completion code plus response data | 
 | 1550 |  *   - allocUnits    - Number of possible allocation units | 
 | 1551 |  *   - allocUnitSize - Allocation unit size in bytes. | 
 | 1552 |  *   - allocUnitFree - Number of free allocation units | 
 | 1553 |  *   - allocUnitLargestFree - Largest free block in allocation units | 
 | 1554 |  *   - maxRecordSize    - Maximum record size in allocation units. | 
 | 1555 |  */ | 
 | 1556 | ipmi::RspType<uint16_t, // allocUnits | 
 | 1557 |               uint16_t, // allocUnitSize | 
 | 1558 |               uint16_t, // allocUnitFree | 
 | 1559 |               uint16_t, // allocUnitLargestFree | 
 | 1560 |               uint8_t   // maxRecordSize | 
 | 1561 |               > | 
 | 1562 |     ipmiStorageGetSDRAllocationInfo() | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1563 | { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1564 |     // 0000h unspecified number of alloc units | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1565 |     constexpr uint16_t allocUnits = 0; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1566 |  | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1567 |     constexpr uint16_t allocUnitFree = 0; | 
 | 1568 |     constexpr uint16_t allocUnitLargestFree = 0; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1569 |     // only allow one block at a time | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1570 |     constexpr uint8_t maxRecordSize = 1; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1571 |  | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1572 |     return ipmi::responseSuccess(allocUnits, maxSDRTotalSize, allocUnitFree, | 
 | 1573 |                                  allocUnitLargestFree, maxRecordSize); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1574 | } | 
 | 1575 |  | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1576 | /** @brief implements the reserve SDR command | 
 | 1577 |  *  @returns IPMI completion code plus response data | 
 | 1578 |  *   - sdrReservationID | 
 | 1579 |  */ | 
 | 1580 | ipmi::RspType<uint16_t> ipmiStorageReserveSDR() | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1581 | { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1582 |     sdrReservationID++; | 
| James Feist | a80cb90 | 2019-02-14 13:05:25 -0800 | [diff] [blame] | 1583 |     if (sdrReservationID == 0) | 
 | 1584 |     { | 
 | 1585 |         sdrReservationID++; | 
 | 1586 |     } | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1587 |  | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1588 |     return ipmi::responseSuccess(sdrReservationID); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1589 | } | 
 | 1590 |  | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1591 | ipmi::RspType<uint16_t,            // next record ID | 
 | 1592 |               std::vector<uint8_t> // payload | 
 | 1593 |               > | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 1594 |     ipmiStorageGetSDR(ipmi::Context::ptr ctx, uint16_t reservationID, | 
 | 1595 |                       uint16_t recordID, uint8_t offset, uint8_t bytesToRead) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1596 | { | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1597 |     // reservation required for partial reads with non zero offset into | 
 | 1598 |     // record | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1599 |     if ((sdrReservationID == 0 || reservationID != sdrReservationID) && offset) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1600 |     { | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1601 |         return ipmi::responseInvalidReservationId(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1602 |     } | 
 | 1603 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1604 |     if (sensorDataRecords.empty() && getSensorDataRecords(ctx)) | 
 | 1605 |     { | 
 | 1606 |         return ipmi::responseResponseError(); | 
 | 1607 |     } | 
 | 1608 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1609 |     if (sensorTree.empty() && !getSensorSubtree(sensorTree)) | 
 | 1610 |     { | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1611 |         return ipmi::responseResponseError(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1612 |     } | 
 | 1613 |  | 
 | 1614 |     size_t fruCount = 0; | 
| James Feist | 2569025 | 2019-12-23 12:25:49 -0800 | [diff] [blame] | 1615 |     ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount); | 
| James Feist | 74c50c6 | 2019-08-14 14:18:41 -0700 | [diff] [blame] | 1616 |     if (ret != ipmi::ccSuccess) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1617 |     { | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1618 |         return ipmi::response(ret); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1619 |     } | 
 | 1620 |  | 
| Yong Li | fee5e4c | 2020-01-17 19:36:29 +0800 | [diff] [blame] | 1621 |     size_t lastRecord = sensorTree.size() + fruCount + | 
 | 1622 |                         ipmi::storage::type12Count + | 
 | 1623 |                         ipmi::storage::nmDiscoverySDRCount - 1; | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1624 |     if (recordID == lastRecordIndex) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1625 |     { | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1626 |         recordID = lastRecord; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1627 |     } | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1628 |     if (recordID > lastRecord) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1629 |     { | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1630 |         return ipmi::responseInvalidFieldRequest(); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1631 |     } | 
 | 1632 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1633 |     get_sdr::SensorDataRecordHeader* hdr = | 
 | 1634 |         reinterpret_cast<get_sdr::SensorDataRecordHeader*>( | 
 | 1635 |             sensorDataRecords[recordID].data()); | 
| Kuiying Wang | b910987 | 2021-01-15 15:54:59 +0800 | [diff] [blame] | 1636 |     if (!hdr) | 
 | 1637 |     { | 
 | 1638 |         phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 1639 |             "Error: record header is null"); | 
 | 1640 |         std::vector<uint8_t> emptyData; | 
 | 1641 |         uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF; | 
 | 1642 |         return ipmi::responseSuccess(nextRecordId, emptyData); | 
 | 1643 |     } | 
 | 1644 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1645 |     size_t sdrLength = | 
 | 1646 |         sizeof(get_sdr::SensorDataRecordHeader) + hdr->record_length; | 
 | 1647 |     if (sdrLength < (offset + bytesToRead)) | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1648 |     { | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1649 |         bytesToRead = sdrLength - offset; | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1650 |     } | 
 | 1651 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1652 |     uint8_t* respStart = reinterpret_cast<uint8_t*>(hdr) + offset; | 
| Kuiying Wang | b910987 | 2021-01-15 15:54:59 +0800 | [diff] [blame] | 1653 |     if (!respStart) | 
 | 1654 |     { | 
 | 1655 |         phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 1656 |             "Error: record is null"); | 
 | 1657 |         std::vector<uint8_t> emptyData; | 
 | 1658 |         uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF; | 
 | 1659 |         return ipmi::responseSuccess(nextRecordId, emptyData); | 
 | 1660 |     } | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1661 |     std::vector<uint8_t> recordData(respStart, respStart + bytesToRead); | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1662 |     uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF; | 
| James Feist | b49a98a | 2019-04-16 13:48:09 -0700 | [diff] [blame] | 1663 |     return ipmi::responseSuccess(nextRecordId, recordData); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1664 | } | 
 | 1665 | /* end storage commands */ | 
 | 1666 |  | 
 | 1667 | void registerSensorFunctions() | 
 | 1668 | { | 
| Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 1669 |     // <Platform Event> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1670 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1671 |                           ipmi::sensor_event::cmdPlatformEvent, | 
 | 1672 |                           ipmi::Privilege::Operator, ipmiSenPlatformEvent); | 
| Jason M. Bills | ae6bdb1 | 2019-04-02 12:00:04 -0700 | [diff] [blame] | 1673 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1674 |     // <Get Sensor Reading> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1675 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1676 |                           ipmi::sensor_event::cmdGetSensorReading, | 
 | 1677 |                           ipmi::Privilege::User, ipmiSenGetSensorReading); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1678 |  | 
 | 1679 |     // <Get Sensor Threshold> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1680 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1681 |                           ipmi::sensor_event::cmdGetSensorThreshold, | 
 | 1682 |                           ipmi::Privilege::User, ipmiSenGetSensorThresholds); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1683 |  | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 1684 |     // <Set Sensor Threshold> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1685 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1686 |                           ipmi::sensor_event::cmdSetSensorThreshold, | 
 | 1687 |                           ipmi::Privilege::Operator, | 
 | 1688 |                           ipmiSenSetSensorThresholds); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1689 |  | 
 | 1690 |     // <Get Sensor Event Enable> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1691 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1692 |                           ipmi::sensor_event::cmdGetSensorEventEnable, | 
| jayaprakash Mutyala | 39fa93f | 2019-05-13 12:16:30 +0000 | [diff] [blame] | 1693 |                           ipmi::Privilege::User, ipmiSenGetSensorEventEnable); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1694 |  | 
 | 1695 |     // <Get Sensor Event Status> | 
| jayaprakash Mutyala | ccf88f6 | 2019-05-13 16:57:16 +0000 | [diff] [blame] | 1696 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1697 |                           ipmi::sensor_event::cmdGetSensorEventStatus, | 
 | 1698 |                           ipmi::Privilege::User, ipmiSenGetSensorEventStatus); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1699 |  | 
 | 1700 |     // register all storage commands for both Sensor and Storage command | 
 | 1701 |     // versions | 
 | 1702 |  | 
 | 1703 |     // <Get SDR Repository Info> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1704 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage, | 
 | 1705 |                           ipmi::storage::cmdGetSdrRepositoryInfo, | 
 | 1706 |                           ipmi::Privilege::User, | 
 | 1707 |                           ipmiStorageGetSDRRepositoryInfo); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1708 |  | 
| Johnathan Mantey | 308c3a8 | 2020-07-22 11:50:54 -0700 | [diff] [blame] | 1709 |     // <Get Device SDR Info> | 
 | 1710 |     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, | 
 | 1711 |                           ipmi::sensor_event::cmdGetDeviceSdrInfo, | 
 | 1712 |                           ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo); | 
 | 1713 |  | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1714 |     // <Get SDR Allocation Info> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1715 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage, | 
 | 1716 |                           ipmi::storage::cmdGetSdrRepositoryAllocInfo, | 
 | 1717 |                           ipmi::Privilege::User, | 
 | 1718 |                           ipmiStorageGetSDRAllocationInfo); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1719 |  | 
 | 1720 |     // <Reserve SDR Repo> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1721 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1722 |                           ipmi::sensor_event::cmdReserveDeviceSdrRepository, | 
| jayaprakash Mutyala | 6ae0818 | 2019-05-13 18:56:11 +0000 | [diff] [blame] | 1723 |                           ipmi::Privilege::User, ipmiStorageReserveSDR); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1724 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1725 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage, | 
 | 1726 |                           ipmi::storage::cmdReserveSdrRepository, | 
 | 1727 |                           ipmi::Privilege::User, ipmiStorageReserveSDR); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1728 |  | 
 | 1729 |     // <Get Sdr> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1730 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor, | 
 | 1731 |                           ipmi::sensor_event::cmdGetDeviceSdr, | 
 | 1732 |                           ipmi::Privilege::User, ipmiStorageGetSDR); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1733 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 1734 |     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage, | 
 | 1735 |                           ipmi::storage::cmdGetSdr, ipmi::Privilege::User, | 
 | 1736 |                           ipmiStorageGetSDR); | 
| Jason M. Bills | 3f7c5e4 | 2018-10-03 14:00:41 -0700 | [diff] [blame] | 1737 | } | 
 | 1738 | } // namespace ipmi |