blob: 8e17dc0f6669e27be87544f7dad63fb85cef9409 [file] [log] [blame]
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001/*
2// Copyright (c) 2017 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
Patrick Venture31b35d52019-10-20 13:25:16 -070017#include "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 Venturec2a07d42020-05-30 16:35:03 -070024#include "types.hpp"
Patrick Venture31b35d52019-10-20 13:25:16 -070025
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070026#include <boost/algorithm/string.hpp>
27#include <boost/container/flat_map.hpp>
James Feistfcd2d3a2020-05-28 10:38:15 -070028#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. Bills3f7c5e42018-10-03 14:00:41 -070035#include <chrono>
36#include <cmath>
Patrick Venture5c2d26e2019-09-25 17:43:53 -070037#include <cstring>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070038#include <iostream>
Patrick Ventureb10ec8b2019-09-25 16:39:14 -070039#include <map>
Patrick Venturefd2a9382019-09-25 17:47:25 -070040#include <memory>
Patrick Venturec4e9de62019-09-25 17:40:54 -070041#include <optional>
Patrick Venturee6154022019-09-25 17:50:25 -070042#include <stdexcept>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070043#include <string>
Patrick Venture38f46f22019-09-25 17:41:26 -070044#include <utility>
Patrick Ventureeb02a5c2019-09-25 17:44:43 -070045#include <variant>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070046
47namespace ipmi
48{
49using ManagedObjectType =
50 std::map<sdbusplus::message::object_path,
51 std::map<std::string, std::map<std::string, DbusVariant>>>;
52
James Feist25690252019-12-23 12:25:49 -080053static constexpr int sensorMapUpdatePeriod = 10;
Alex Qiu09701ef2020-07-15 17:56:21 -070054static constexpr int sensorMapSdrUpdatePeriod = 60;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070055
56constexpr size_t maxSDRTotalSize =
57 76; // Largest SDR Record Size (type 01) + SDR Overheader Size
58constexpr static const uint32_t noTimestamp = 0xFFFFFFFF;
59
60static uint16_t sdrReservationID;
61static uint32_t sdrLastAdd = noTimestamp;
62static uint32_t sdrLastRemove = noTimestamp;
Johnathan Mantey308c3a82020-07-22 11:50:54 -070063static constexpr size_t lastRecordIndex = 0xFFFF;
64static constexpr int GENERAL_ERROR = -1;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070065
Richard Marian Thomaiyar01fbcb52018-11-19 22:04:34 +053066SensorSubTree sensorTree;
Johnathan Mantey308c3a82020-07-22 11:50:54 -070067
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070068static boost::container::flat_map<std::string, ManagedObjectType> SensorCache;
69
Jason M. Bills17add592018-11-12 14:30:12 -080070// Specify the comparison required to sort and find char* map objects
71struct CmpStr
72{
James Feistfcd2d3a2020-05-28 10:38:15 -070073 bool operator()(const char* a, const char* b) const
Jason M. Bills17add592018-11-12 14:30:12 -080074 {
75 return std::strcmp(a, b) < 0;
76 }
77};
James Feistfcd2d3a2020-05-28 10:38:15 -070078const static boost::container::flat_map<const char*, SensorUnits, CmpStr>
Jason M. Bills17add592018-11-12 14:30:12 -080079 sensorUnits{{{"temperature", SensorUnits::degreesC},
80 {"voltage", SensorUnits::volts},
81 {"current", SensorUnits::amps},
82 {"fan_tach", SensorUnits::rpm},
83 {"power", SensorUnits::watts}}};
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070084
85void registerSensorFunctions() __attribute__((constructor));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070086
87static sdbusplus::bus::match::match sensorAdded(
Vernon Mauery15419dd2019-05-24 09:40:30 -070088 *getSdBus(),
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070089 "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/"
90 "sensors/'",
James Feistfcd2d3a2020-05-28 10:38:15 -070091 [](sdbusplus::message::message& m) {
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070092 sensorTree.clear();
93 sdrLastAdd = std::chrono::duration_cast<std::chrono::seconds>(
94 std::chrono::system_clock::now().time_since_epoch())
95 .count();
96 });
97
98static sdbusplus::bus::match::match sensorRemoved(
Vernon Mauery15419dd2019-05-24 09:40:30 -070099 *getSdBus(),
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700100 "type='signal',member='InterfacesRemoved',arg0path='/xyz/openbmc_project/"
101 "sensors/'",
James Feistfcd2d3a2020-05-28 10:38:15 -0700102 [](sdbusplus::message::message& m) {
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700103 sensorTree.clear();
104 sdrLastRemove = std::chrono::duration_cast<std::chrono::seconds>(
105 std::chrono::system_clock::now().time_since_epoch())
106 .count();
107 });
108
James Feist392786a2019-03-19 13:36:10 -0700109// this keeps track of deassertions for sensor event status command. A
110// deasertion can only happen if an assertion was seen first.
111static boost::container::flat_map<
112 std::string, boost::container::flat_map<std::string, std::optional<bool>>>
113 thresholdDeassertMap;
114
115static sdbusplus::bus::match::match thresholdChanged(
Vernon Mauery15419dd2019-05-24 09:40:30 -0700116 *getSdBus(),
James Feist392786a2019-03-19 13:36:10 -0700117 "type='signal',member='PropertiesChanged',interface='org.freedesktop.DBus."
118 "Properties',arg0namespace='xyz.openbmc_project.Sensor.Threshold'",
James Feistfcd2d3a2020-05-28 10:38:15 -0700119 [](sdbusplus::message::message& m) {
James Feist392786a2019-03-19 13:36:10 -0700120 boost::container::flat_map<std::string, std::variant<bool, double>>
121 values;
122 m.read(std::string(), values);
123
124 auto findAssert =
James Feistfcd2d3a2020-05-28 10:38:15 -0700125 std::find_if(values.begin(), values.end(), [](const auto& pair) {
James Feist392786a2019-03-19 13:36:10 -0700126 return pair.first.find("Alarm") != std::string::npos;
127 });
128 if (findAssert != values.end())
129 {
130 auto ptr = std::get_if<bool>(&(findAssert->second));
131 if (ptr == nullptr)
132 {
133 phosphor::logging::log<phosphor::logging::level::ERR>(
134 "thresholdChanged: Assert non bool");
135 return;
136 }
137 if (*ptr)
138 {
139 phosphor::logging::log<phosphor::logging::level::INFO>(
140 "thresholdChanged: Assert",
141 phosphor::logging::entry("SENSOR=%s", m.get_path()));
142 thresholdDeassertMap[m.get_path()][findAssert->first] = *ptr;
143 }
144 else
145 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700146 auto& value =
James Feist392786a2019-03-19 13:36:10 -0700147 thresholdDeassertMap[m.get_path()][findAssert->first];
148 if (value)
149 {
150 phosphor::logging::log<phosphor::logging::level::INFO>(
151 "thresholdChanged: deassert",
152 phosphor::logging::entry("SENSOR=%s", m.get_path()));
153 value = *ptr;
154 }
155 }
156 }
157 });
158
James Feistfcd2d3a2020-05-28 10:38:15 -0700159static void getSensorMaxMin(const SensorMap& sensorMap, double& max,
160 double& min)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700161{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700162 max = 127;
163 min = -128;
164
James Feistaecaef72019-04-26 10:30:32 -0700165 auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
166 auto critical =
167 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
168 auto warning =
169 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
170
171 if (sensorObject != sensorMap.end())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700172 {
James Feistaecaef72019-04-26 10:30:32 -0700173 auto maxMap = sensorObject->second.find("MaxValue");
174 auto minMap = sensorObject->second.find("MinValue");
175
176 if (maxMap != sensorObject->second.end())
177 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700178 max = std::visit(VariantToDoubleVisitor(), maxMap->second);
James Feistaecaef72019-04-26 10:30:32 -0700179 }
180 if (minMap != sensorObject->second.end())
181 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700182 min = std::visit(VariantToDoubleVisitor(), minMap->second);
James Feistaecaef72019-04-26 10:30:32 -0700183 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700184 }
James Feistaecaef72019-04-26 10:30:32 -0700185 if (critical != sensorMap.end())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700186 {
James Feistaecaef72019-04-26 10:30:32 -0700187 auto lower = critical->second.find("CriticalLow");
188 auto upper = critical->second.find("CriticalHigh");
189 if (lower != critical->second.end())
190 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700191 double value = std::visit(VariantToDoubleVisitor(), lower->second);
James Feistaecaef72019-04-26 10:30:32 -0700192 min = std::min(value, min);
193 }
194 if (upper != critical->second.end())
195 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700196 double value = std::visit(VariantToDoubleVisitor(), upper->second);
James Feistaecaef72019-04-26 10:30:32 -0700197 max = std::max(value, max);
198 }
199 }
200 if (warning != sensorMap.end())
201 {
202
203 auto lower = warning->second.find("WarningLow");
204 auto upper = warning->second.find("WarningHigh");
205 if (lower != warning->second.end())
206 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700207 double value = std::visit(VariantToDoubleVisitor(), lower->second);
James Feistaecaef72019-04-26 10:30:32 -0700208 min = std::min(value, min);
209 }
210 if (upper != warning->second.end())
211 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700212 double value = std::visit(VariantToDoubleVisitor(), upper->second);
James Feistaecaef72019-04-26 10:30:32 -0700213 max = std::max(value, max);
214 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700215 }
216}
217
James Feist25690252019-12-23 12:25:49 -0800218static bool getSensorMap(boost::asio::yield_context yield,
219 std::string sensorConnection, std::string sensorPath,
Alex Qiu09701ef2020-07-15 17:56:21 -0700220 SensorMap& sensorMap,
221 int updatePeriod = sensorMapUpdatePeriod)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700222{
223 static boost::container::flat_map<
224 std::string, std::chrono::time_point<std::chrono::steady_clock>>
225 updateTimeMap;
226
227 auto updateFind = updateTimeMap.find(sensorConnection);
228 auto lastUpdate = std::chrono::time_point<std::chrono::steady_clock>();
229 if (updateFind != updateTimeMap.end())
230 {
231 lastUpdate = updateFind->second;
232 }
233
234 auto now = std::chrono::steady_clock::now();
235
236 if (std::chrono::duration_cast<std::chrono::seconds>(now - lastUpdate)
Alex Qiu09701ef2020-07-15 17:56:21 -0700237 .count() > updatePeriod)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700238 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700239 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
James Feist25690252019-12-23 12:25:49 -0800240 boost::system::error_code ec;
241 auto managedObjects = dbus->yield_method_call<ManagedObjectType>(
242 yield, ec, sensorConnection.c_str(), "/",
243 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
244 if (ec)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700245 {
246 phosphor::logging::log<phosphor::logging::level::ERR>(
James Feist25690252019-12-23 12:25:49 -0800247 "GetMangagedObjects for getSensorMap failed",
248 phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
249
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700250 return false;
251 }
252
253 SensorCache[sensorConnection] = managedObjects;
Alex Qiu09701ef2020-07-15 17:56:21 -0700254 // Update time after finish building the map which allow the
255 // data to be cached for updatePeriod plus the build time.
256 updateTimeMap[sensorConnection] = std::chrono::steady_clock::now();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700257 }
258 auto connection = SensorCache.find(sensorConnection);
259 if (connection == SensorCache.end())
260 {
261 return false;
262 }
263 auto path = connection->second.find(sensorPath);
264 if (path == connection->second.end())
265 {
266 return false;
267 }
268 sensorMap = path->second;
269
270 return true;
271}
272
273/* sensor commands */
James Feist7aaf3fe2019-06-25 11:52:11 -0700274namespace meHealth
275{
James Feistfcd2d3a2020-05-28 10:38:15 -0700276constexpr const char* busname = "xyz.openbmc_project.NodeManagerProxy";
277constexpr const char* path = "/xyz/openbmc_project/status/me";
278constexpr const char* interface = "xyz.openbmc_project.SetHealth";
279constexpr const char* method = "SetHealth";
280constexpr const char* critical = "critical";
281constexpr const char* warning = "warning";
282constexpr const char* ok = "ok";
James Feist7aaf3fe2019-06-25 11:52:11 -0700283} // namespace meHealth
284
285static void setMeStatus(uint8_t eventData2, uint8_t eventData3, bool disable)
286{
287 constexpr const std::array<uint8_t, 10> critical = {
288 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xD, 0xE};
289 constexpr const std::array<uint8_t, 5> warning = {0x3, 0xA, 0x13, 0x19,
290 0x1A};
291
292 std::string state;
293 if (std::find(critical.begin(), critical.end(), eventData2) !=
294 critical.end())
295 {
296 state = meHealth::critical;
297 }
298 // special case 0x3 as we only care about a few states
299 else if (eventData2 == 0x3)
300 {
301 if (eventData3 <= 0x2)
302 {
303 state = meHealth::warning;
304 }
305 else
306 {
307 return;
308 }
309 }
310 else if (std::find(warning.begin(), warning.end(), eventData2) !=
311 warning.end())
312 {
313 state = meHealth::warning;
314 }
315 else
316 {
317 return;
318 }
319 if (disable)
320 {
321 state = meHealth::ok;
322 }
323
324 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
325 auto setHealth =
326 dbus->new_method_call(meHealth::busname, meHealth::path,
327 meHealth::interface, meHealth::method);
328 setHealth.append(std::to_string(static_cast<size_t>(eventData2)), state);
329 try
330 {
331 dbus->call(setHealth);
332 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700333 catch (sdbusplus::exception_t&)
James Feist7aaf3fe2019-06-25 11:52:11 -0700334 {
335 phosphor::logging::log<phosphor::logging::level::ERR>(
336 "Failed to set ME Health");
337 }
338}
339
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000340ipmi::RspType<> ipmiSenPlatformEvent(ipmi::Context::ptr ctx,
341 ipmi::message::Payload& p)
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700342{
James Feist7aaf3fe2019-06-25 11:52:11 -0700343 constexpr const uint8_t meId = 0x2C;
344 constexpr const uint8_t meSensorNum = 0x17;
345 constexpr const uint8_t disabled = 0x80;
346
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700347 uint8_t generatorID = 0;
348 uint8_t evmRev = 0;
349 uint8_t sensorType = 0;
350 uint8_t sensorNum = 0;
351 uint8_t eventType = 0;
352 uint8_t eventData1 = 0;
353 std::optional<uint8_t> eventData2 = 0;
354 std::optional<uint8_t> eventData3 = 0;
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000355 ipmi::ChannelInfo chInfo;
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700356
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000357 if (ipmi::getChannelInfo(ctx->channel, chInfo) != ipmi::ccSuccess)
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700358 {
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000359 phosphor::logging::log<phosphor::logging::level::ERR>(
360 "Failed to get Channel Info",
361 phosphor::logging::entry("CHANNEL=%d", ctx->channel));
362 return ipmi::responseUnspecifiedError();
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700363 }
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000364
365 if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) ==
366 ipmi::EChannelMediumType::systemInterface)
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700367 {
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000368
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700369 p.unpack(generatorID, evmRev, sensorType, sensorNum, eventType,
370 eventData1, eventData2, eventData3);
371 }
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000372 else
373 {
374
375 p.unpack(evmRev, sensorType, sensorNum, eventType, eventData1,
376 eventData2, eventData3);
377 generatorID = ctx->rqSA;
378 }
379
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700380 if (!p.fullyUnpacked())
381 {
382 return ipmi::responseReqDataLenInvalid();
383 }
384
Chalapathi Venkataramashetty989a13b2021-06-20 19:50:33 +0000385 // Check for valid evmRev and Sensor Type(per Table 42 of spec)
386 if (evmRev != 0x04)
387 {
388 return ipmi::responseInvalidFieldRequest();
389 }
390 if ((sensorType > 0x2C) && (sensorType < 0xC0))
391 {
392 return ipmi::responseInvalidFieldRequest();
393 }
394
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700395 // Send this request to the Redfish hooks to log it as a Redfish message
396 // instead. There is no need to add it to the SEL, so just return success.
397 intel_oem::ipmi::sel::checkRedfishHooks(
398 generatorID, evmRev, sensorType, sensorNum, eventType, eventData1,
399 eventData2.value_or(0xFF), eventData3.value_or(0xFF));
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700400
James Feist7aaf3fe2019-06-25 11:52:11 -0700401 if (generatorID == meId && sensorNum == meSensorNum && eventData2 &&
402 eventData3)
403 {
404 setMeStatus(*eventData2, *eventData3, (eventType & disabled));
405 }
406
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700407 return ipmi::responseSuccess();
408}
409
James Feist0cd014a2019-04-08 15:04:33 -0700410ipmi::RspType<uint8_t, uint8_t, uint8_t, std::optional<uint8_t>>
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700411 ipmiSenGetSensorReading(ipmi::Context::ptr ctx, uint8_t sensnum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700412{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700413 std::string connection;
414 std::string path;
415
Chalapathi Venkataramashetty339fc562021-06-13 19:51:17 +0000416 if (sensnum == reservedSensorNumber)
417 {
418 return ipmi::responseInvalidFieldRequest();
419 }
420
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700421 auto status = getSensorConnection(ctx, sensnum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700422 if (status)
423 {
James Feist0cd014a2019-04-08 15:04:33 -0700424 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700425 }
426
427 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700428 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700429 {
James Feist0cd014a2019-04-08 15:04:33 -0700430 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700431 }
432 auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
433
434 if (sensorObject == sensorMap.end() ||
435 sensorObject->second.find("Value") == sensorObject->second.end())
436 {
James Feist0cd014a2019-04-08 15:04:33 -0700437 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700438 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700439 auto& valueVariant = sensorObject->second["Value"];
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700440 double reading = std::visit(VariantToDoubleVisitor(), valueVariant);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700441
Yong Li1f2eb5e2019-05-23 14:07:17 +0800442 double max = 0;
443 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700444 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700445
446 int16_t mValue = 0;
447 int16_t bValue = 0;
448 int8_t rExp = 0;
449 int8_t bExp = 0;
450 bool bSigned = false;
451
452 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
453 {
James Feist0cd014a2019-04-08 15:04:33 -0700454 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700455 }
456
James Feist0cd014a2019-04-08 15:04:33 -0700457 uint8_t value =
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700458 scaleIPMIValueFromDouble(reading, mValue, rExp, bValue, bExp, bSigned);
James Feist0cd014a2019-04-08 15:04:33 -0700459 uint8_t operation =
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700460 static_cast<uint8_t>(IPMISensorReadingByte2::sensorScanningEnable);
James Feist0cd014a2019-04-08 15:04:33 -0700461 operation |=
James Feist81a95c12019-03-01 15:08:28 -0800462 static_cast<uint8_t>(IPMISensorReadingByte2::eventMessagesEnable);
James Feist1ee6ed82020-06-17 16:16:50 -0700463 bool notReading = std::isnan(reading);
464
465 if (!notReading)
466 {
467 auto availableObject =
468 sensorMap.find("xyz.openbmc_project.State.Decorator.Availability");
469 if (availableObject != sensorMap.end())
470 {
471 auto findAvailable = availableObject->second.find("Available");
472 if (findAvailable != availableObject->second.end())
473 {
474 bool* available = std::get_if<bool>(&(findAvailable->second));
475 if (available && !(*available))
476 {
477 notReading = true;
478 }
479 }
480 }
481 }
482
483 if (notReading)
484 {
485 operation |= static_cast<uint8_t>(
486 IPMISensorReadingByte2::readingStateUnavailable);
487 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700488
Josh Lehan06aa21a2020-10-28 21:59:06 -0700489 int byteValue;
490 if (bSigned)
491 {
492 byteValue = static_cast<int>(static_cast<int8_t>(value));
493 }
494 else
495 {
496 byteValue = static_cast<int>(static_cast<uint8_t>(value));
497 }
498
499 // Keep stats on the reading just obtained, even if it is "NaN"
500 if (details::sdrStatsTable.updateReading(sensnum, reading, byteValue))
501 {
502 // This is the first reading, show the coefficients
503 double step = (max - min) / 255.0;
504 std::cerr << "IPMI sensor " << details::sdrStatsTable.getName(sensnum)
505 << ": Range min=" << min << " max=" << max
506 << ", step=" << step
507 << ", Coefficients mValue=" << static_cast<int>(mValue)
508 << " rExp=" << static_cast<int>(rExp)
509 << " bValue=" << static_cast<int>(bValue)
510 << " bExp=" << static_cast<int>(bExp)
511 << " bSigned=" << static_cast<int>(bSigned) << "\n";
512 };
513
James Feist0cd014a2019-04-08 15:04:33 -0700514 uint8_t thresholds = 0;
515
516 auto warningObject =
517 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
518 if (warningObject != sensorMap.end())
519 {
520 auto alarmHigh = warningObject->second.find("WarningAlarmHigh");
521 auto alarmLow = warningObject->second.find("WarningAlarmLow");
522 if (alarmHigh != warningObject->second.end())
523 {
524 if (std::get<bool>(alarmHigh->second))
525 {
526 thresholds |= static_cast<uint8_t>(
527 IPMISensorReadingByte3::upperNonCritical);
528 }
529 }
530 if (alarmLow != warningObject->second.end())
531 {
532 if (std::get<bool>(alarmLow->second))
533 {
534 thresholds |= static_cast<uint8_t>(
535 IPMISensorReadingByte3::lowerNonCritical);
536 }
537 }
538 }
539
540 auto criticalObject =
541 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
542 if (criticalObject != sensorMap.end())
543 {
544 auto alarmHigh = criticalObject->second.find("CriticalAlarmHigh");
545 auto alarmLow = criticalObject->second.find("CriticalAlarmLow");
546 if (alarmHigh != criticalObject->second.end())
547 {
548 if (std::get<bool>(alarmHigh->second))
549 {
550 thresholds |=
551 static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
552 }
553 }
554 if (alarmLow != criticalObject->second.end())
555 {
556 if (std::get<bool>(alarmLow->second))
557 {
558 thresholds |=
559 static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
560 }
561 }
562 }
563
564 // no discrete as of today so optional byte is never returned
565 return ipmi::responseSuccess(value, operation, thresholds, std::nullopt);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700566}
567
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000568/** @brief implements the Set Sensor threshold command
569 * @param sensorNumber - sensor number
570 * @param lowerNonCriticalThreshMask
571 * @param lowerCriticalThreshMask
572 * @param lowerNonRecovThreshMask
573 * @param upperNonCriticalThreshMask
574 * @param upperCriticalThreshMask
575 * @param upperNonRecovThreshMask
576 * @param reserved
577 * @param lowerNonCritical - lower non-critical threshold
578 * @param lowerCritical - Lower critical threshold
579 * @param lowerNonRecoverable - Lower non recovarable threshold
580 * @param upperNonCritical - Upper non-critical threshold
581 * @param upperCritical - Upper critical
582 * @param upperNonRecoverable - Upper Non-recoverable
583 *
584 * @returns IPMI completion code
585 */
586ipmi::RspType<> ipmiSenSetSensorThresholds(
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700587 ipmi::Context::ptr ctx, uint8_t sensorNum, bool lowerNonCriticalThreshMask,
588 bool lowerCriticalThreshMask, bool lowerNonRecovThreshMask,
589 bool upperNonCriticalThreshMask, bool upperCriticalThreshMask,
590 bool upperNonRecovThreshMask, uint2_t reserved, uint8_t lowerNonCritical,
591 uint8_t lowerCritical, uint8_t lowerNonRecoverable,
592 uint8_t upperNonCritical, uint8_t upperCritical,
593 uint8_t upperNonRecoverable)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700594{
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000595 constexpr uint8_t thresholdMask = 0xFF;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700596
Chalapathi Venkataramashetty339fc562021-06-13 19:51:17 +0000597 if (sensorNum == reservedSensorNumber)
598 {
599 return ipmi::responseInvalidFieldRequest();
600 }
601
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000602 if (reserved)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700603 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000604 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700605 }
606
607 // lower nc and upper nc not suppported on any sensor
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000608 if (lowerNonRecovThreshMask || upperNonRecovThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700609 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000610 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700611 }
612
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000613 // if none of the threshold mask are set, nothing to do
614 if (!(lowerNonCriticalThreshMask | lowerCriticalThreshMask |
615 lowerNonRecovThreshMask | upperNonCriticalThreshMask |
616 upperCriticalThreshMask | upperNonRecovThreshMask))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700617 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000618 return ipmi::responseSuccess();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700619 }
620
621 std::string connection;
622 std::string path;
623
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700624 ipmi::Cc status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700625 if (status)
626 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000627 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700628 }
629 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700630 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700631 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000632 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700633 }
634
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700635 double max = 0;
636 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700637 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700638
639 int16_t mValue = 0;
640 int16_t bValue = 0;
641 int8_t rExp = 0;
642 int8_t bExp = 0;
643 bool bSigned = false;
644
645 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
646 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000647 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700648 }
649
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700650 // store a vector of property name, value to set, and interface
651 std::vector<std::tuple<std::string, uint8_t, std::string>> thresholdsToSet;
652
653 // define the indexes of the tuple
654 constexpr uint8_t propertyName = 0;
655 constexpr uint8_t thresholdValue = 1;
656 constexpr uint8_t interface = 2;
657 // verifiy all needed fields are present
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000658 if (lowerCriticalThreshMask || upperCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700659 {
660 auto findThreshold =
661 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
662 if (findThreshold == sensorMap.end())
663 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000664 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700665 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000666 if (lowerCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700667 {
668 auto findLower = findThreshold->second.find("CriticalLow");
669 if (findLower == findThreshold->second.end())
670 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000671 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700672 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000673 thresholdsToSet.emplace_back("CriticalLow", lowerCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700674 findThreshold->first);
675 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000676 if (upperCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700677 {
678 auto findUpper = findThreshold->second.find("CriticalHigh");
679 if (findUpper == findThreshold->second.end())
680 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000681 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700682 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000683 thresholdsToSet.emplace_back("CriticalHigh", upperCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700684 findThreshold->first);
685 }
686 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000687 if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700688 {
689 auto findThreshold =
690 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
691 if (findThreshold == sensorMap.end())
692 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000693 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700694 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000695 if (lowerNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700696 {
697 auto findLower = findThreshold->second.find("WarningLow");
698 if (findLower == findThreshold->second.end())
699 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000700 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700701 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000702 thresholdsToSet.emplace_back("WarningLow", lowerNonCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700703 findThreshold->first);
704 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000705 if (upperNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700706 {
707 auto findUpper = findThreshold->second.find("WarningHigh");
708 if (findUpper == findThreshold->second.end())
709 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000710 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700711 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000712 thresholdsToSet.emplace_back("WarningHigh", upperNonCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700713 findThreshold->first);
714 }
715 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700716 for (const auto& property : thresholdsToSet)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700717 {
718 // from section 36.3 in the IPMI Spec, assume all linear
719 double valueToSet = ((mValue * std::get<thresholdValue>(property)) +
Josh Lehan86236a22019-11-18 17:53:33 -0800720 (bValue * std::pow(10.0, bExp))) *
721 std::pow(10.0, rExp);
Vernon Mauery15419dd2019-05-24 09:40:30 -0700722 setDbusProperty(
723 *getSdBus(), connection, path, std::get<interface>(property),
724 std::get<propertyName>(property), ipmi::Value(valueToSet));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700725 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000726 return ipmi::responseSuccess();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700727}
728
James Feistfcd2d3a2020-05-28 10:38:15 -0700729IPMIThresholds getIPMIThresholds(const SensorMap& sensorMap)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700730{
James Feist902c4c52019-04-16 14:51:31 -0700731 IPMIThresholds resp;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700732 auto warningInterface =
733 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
734 auto criticalInterface =
735 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
736
737 if ((warningInterface != sensorMap.end()) ||
738 (criticalInterface != sensorMap.end()))
739 {
740 auto sensorPair = sensorMap.find("xyz.openbmc_project.Sensor.Value");
741
742 if (sensorPair == sensorMap.end())
743 {
744 // should not have been able to find a sensor not implementing
745 // the sensor object
James Feist902c4c52019-04-16 14:51:31 -0700746 throw std::runtime_error("Invalid sensor map");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700747 }
748
Chen,Yugang606dd9f2019-07-01 10:37:30 +0800749 double max = 0;
750 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700751 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700752
753 int16_t mValue = 0;
754 int16_t bValue = 0;
755 int8_t rExp = 0;
756 int8_t bExp = 0;
757 bool bSigned = false;
758
759 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
760 {
James Feist902c4c52019-04-16 14:51:31 -0700761 throw std::runtime_error("Invalid sensor atrributes");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700762 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700763 if (warningInterface != sensorMap.end())
764 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700765 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700766
767 auto warningHigh = warningMap.find("WarningHigh");
768 auto warningLow = warningMap.find("WarningLow");
769
770 if (warningHigh != warningMap.end())
771 {
James Feist902c4c52019-04-16 14:51:31 -0700772
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700773 double value =
774 std::visit(VariantToDoubleVisitor(), warningHigh->second);
James Feist902c4c52019-04-16 14:51:31 -0700775 resp.warningHigh = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700776 value, mValue, rExp, bValue, bExp, bSigned);
777 }
778 if (warningLow != warningMap.end())
779 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700780 double value =
781 std::visit(VariantToDoubleVisitor(), warningLow->second);
James Feist902c4c52019-04-16 14:51:31 -0700782 resp.warningLow = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700783 value, mValue, rExp, bValue, bExp, bSigned);
784 }
785 }
786 if (criticalInterface != sensorMap.end())
787 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700788 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700789
790 auto criticalHigh = criticalMap.find("CriticalHigh");
791 auto criticalLow = criticalMap.find("CriticalLow");
792
793 if (criticalHigh != criticalMap.end())
794 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700795 double value =
796 std::visit(VariantToDoubleVisitor(), criticalHigh->second);
James Feist902c4c52019-04-16 14:51:31 -0700797 resp.criticalHigh = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700798 value, mValue, rExp, bValue, bExp, bSigned);
799 }
800 if (criticalLow != criticalMap.end())
801 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700802 double value =
803 std::visit(VariantToDoubleVisitor(), criticalLow->second);
James Feist902c4c52019-04-16 14:51:31 -0700804 resp.criticalLow = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700805 value, mValue, rExp, bValue, bExp, bSigned);
806 }
807 }
808 }
James Feist902c4c52019-04-16 14:51:31 -0700809 return resp;
810}
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700811
James Feist902c4c52019-04-16 14:51:31 -0700812ipmi::RspType<uint8_t, // readable
813 uint8_t, // lowerNCrit
814 uint8_t, // lowerCrit
815 uint8_t, // lowerNrecoverable
816 uint8_t, // upperNC
817 uint8_t, // upperCrit
818 uint8_t> // upperNRecoverable
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700819 ipmiSenGetSensorThresholds(ipmi::Context::ptr ctx, uint8_t sensorNumber)
James Feist902c4c52019-04-16 14:51:31 -0700820{
821 std::string connection;
822 std::string path;
823
Chalapathi Venkataramashetty339fc562021-06-13 19:51:17 +0000824 if (sensorNumber == reservedSensorNumber)
825 {
826 return ipmi::responseInvalidFieldRequest();
827 }
828
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700829 auto status = getSensorConnection(ctx, sensorNumber, connection, path);
James Feist902c4c52019-04-16 14:51:31 -0700830 if (status)
831 {
832 return ipmi::response(status);
833 }
834
835 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700836 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
James Feist902c4c52019-04-16 14:51:31 -0700837 {
838 return ipmi::responseResponseError();
839 }
840
841 IPMIThresholds thresholdData;
842 try
843 {
844 thresholdData = getIPMIThresholds(sensorMap);
845 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700846 catch (std::exception&)
James Feist902c4c52019-04-16 14:51:31 -0700847 {
848 return ipmi::responseResponseError();
849 }
850
851 uint8_t readable = 0;
852 uint8_t lowerNC = 0;
853 uint8_t lowerCritical = 0;
854 uint8_t lowerNonRecoverable = 0;
855 uint8_t upperNC = 0;
856 uint8_t upperCritical = 0;
857 uint8_t upperNonRecoverable = 0;
858
859 if (thresholdData.warningHigh)
860 {
861 readable |=
862 1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperNonCritical);
863 upperNC = *thresholdData.warningHigh;
864 }
865 if (thresholdData.warningLow)
866 {
867 readable |=
868 1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerNonCritical);
869 lowerNC = *thresholdData.warningLow;
870 }
871
872 if (thresholdData.criticalHigh)
873 {
874 readable |=
875 1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperCritical);
876 upperCritical = *thresholdData.criticalHigh;
877 }
878 if (thresholdData.criticalLow)
879 {
880 readable |=
881 1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerCritical);
882 lowerCritical = *thresholdData.criticalLow;
883 }
884
885 return ipmi::responseSuccess(readable, lowerNC, lowerCritical,
886 lowerNonRecoverable, upperNC, upperCritical,
887 upperNonRecoverable);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700888}
889
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000890/** @brief implements the get Sensor event enable command
891 * @param sensorNumber - sensor number
892 *
893 * @returns IPMI completion code plus response data
894 * - enabled - Sensor Event messages
895 * - assertionEnabledLsb - Assertion event messages
896 * - assertionEnabledMsb - Assertion event messages
897 * - deassertionEnabledLsb - Deassertion event messages
898 * - deassertionEnabledMsb - Deassertion event messages
899 */
900
901ipmi::RspType<uint8_t, // enabled
902 uint8_t, // assertionEnabledLsb
903 uint8_t, // assertionEnabledMsb
904 uint8_t, // deassertionEnabledLsb
905 uint8_t> // deassertionEnabledMsb
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700906 ipmiSenGetSensorEventEnable(ipmi::Context::ptr ctx, uint8_t sensorNum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700907{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700908 std::string connection;
909 std::string path;
910
Patrick Venturea41714c2019-09-25 16:59:41 -0700911 uint8_t enabled = 0;
912 uint8_t assertionEnabledLsb = 0;
913 uint8_t assertionEnabledMsb = 0;
914 uint8_t deassertionEnabledLsb = 0;
915 uint8_t deassertionEnabledMsb = 0;
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000916
Chalapathi Venkataramashetty339fc562021-06-13 19:51:17 +0000917 if (sensorNum == reservedSensorNumber)
918 {
919 return ipmi::responseInvalidFieldRequest();
920 }
921
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700922 auto status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700923 if (status)
924 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000925 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700926 }
927
928 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700929 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700930 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000931 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700932 }
933
934 auto warningInterface =
935 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
936 auto criticalInterface =
937 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700938 if ((warningInterface != sensorMap.end()) ||
939 (criticalInterface != sensorMap.end()))
940 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000941 enabled = static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700942 IPMISensorEventEnableByte2::sensorScanningEnable);
943 if (warningInterface != sensorMap.end())
944 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700945 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700946
947 auto warningHigh = warningMap.find("WarningHigh");
948 auto warningLow = warningMap.find("WarningLow");
949 if (warningHigh != warningMap.end())
950 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000951 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700952 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000953 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700954 IPMISensorEventEnableThresholds::upperNonCriticalGoingLow);
955 }
956 if (warningLow != warningMap.end())
957 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000958 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700959 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000960 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700961 IPMISensorEventEnableThresholds::lowerNonCriticalGoingHigh);
962 }
963 }
964 if (criticalInterface != sensorMap.end())
965 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700966 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700967
968 auto criticalHigh = criticalMap.find("CriticalHigh");
969 auto criticalLow = criticalMap.find("CriticalLow");
970
971 if (criticalHigh != criticalMap.end())
972 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000973 assertionEnabledMsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700974 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000975 deassertionEnabledMsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700976 IPMISensorEventEnableThresholds::upperCriticalGoingLow);
977 }
978 if (criticalLow != criticalMap.end())
979 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000980 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700981 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000982 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700983 IPMISensorEventEnableThresholds::lowerCriticalGoingHigh);
984 }
985 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700986 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000987
988 return ipmi::responseSuccess(enabled, assertionEnabledLsb,
989 assertionEnabledMsb, deassertionEnabledLsb,
990 deassertionEnabledMsb);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700991}
992
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000993/** @brief implements the get Sensor event status command
994 * @param sensorNumber - sensor number, FFh = reserved
995 *
996 * @returns IPMI completion code plus response data
997 * - sensorEventStatus - Sensor Event messages state
998 * - assertions - Assertion event messages
999 * - deassertions - Deassertion event messages
1000 */
1001ipmi::RspType<uint8_t, // sensorEventStatus
1002 std::bitset<16>, // assertions
1003 std::bitset<16> // deassertion
1004 >
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001005 ipmiSenGetSensorEventStatus(ipmi::Context::ptr ctx, uint8_t sensorNum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001006{
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001007 if (sensorNum == reservedSensorNumber)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001008 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001009 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001010 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001011
1012 std::string connection;
1013 std::string path;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001014 auto status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001015 if (status)
1016 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001017 phosphor::logging::log<phosphor::logging::level::ERR>(
1018 "ipmiSenGetSensorEventStatus: Sensor connection Error",
1019 phosphor::logging::entry("SENSOR=%d", sensorNum));
1020 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001021 }
1022
1023 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001024 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001025 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001026 phosphor::logging::log<phosphor::logging::level::ERR>(
1027 "ipmiSenGetSensorEventStatus: Sensor Mapping Error",
1028 phosphor::logging::entry("SENSOR=%s", path.c_str()));
1029 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001030 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001031 auto warningInterface =
1032 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
1033 auto criticalInterface =
1034 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
1035
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001036 uint8_t sensorEventStatus =
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001037 static_cast<uint8_t>(IPMISensorEventEnableByte2::sensorScanningEnable);
1038
James Feist392786a2019-03-19 13:36:10 -07001039 std::optional<bool> criticalDeassertHigh =
1040 thresholdDeassertMap[path]["CriticalAlarmHigh"];
1041 std::optional<bool> criticalDeassertLow =
1042 thresholdDeassertMap[path]["CriticalAlarmLow"];
1043 std::optional<bool> warningDeassertHigh =
1044 thresholdDeassertMap[path]["WarningAlarmHigh"];
1045 std::optional<bool> warningDeassertLow =
1046 thresholdDeassertMap[path]["WarningAlarmLow"];
1047
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001048 std::bitset<16> assertions = 0;
1049 std::bitset<16> deassertions = 0;
1050
James Feist392786a2019-03-19 13:36:10 -07001051 if (criticalDeassertHigh && !*criticalDeassertHigh)
1052 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001053 deassertions.set(static_cast<size_t>(
1054 IPMIGetSensorEventEnableThresholds::upperCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001055 }
1056 if (criticalDeassertLow && !*criticalDeassertLow)
1057 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001058 deassertions.set(static_cast<size_t>(
1059 IPMIGetSensorEventEnableThresholds::upperCriticalGoingLow));
James Feist392786a2019-03-19 13:36:10 -07001060 }
1061 if (warningDeassertHigh && !*warningDeassertHigh)
1062 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001063 deassertions.set(static_cast<size_t>(
1064 IPMIGetSensorEventEnableThresholds::upperNonCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001065 }
1066 if (warningDeassertLow && !*warningDeassertLow)
1067 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001068 deassertions.set(static_cast<size_t>(
1069 IPMIGetSensorEventEnableThresholds::lowerNonCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001070 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001071 if ((warningInterface != sensorMap.end()) ||
1072 (criticalInterface != sensorMap.end()))
1073 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001074 sensorEventStatus = static_cast<size_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001075 IPMISensorEventEnableByte2::eventMessagesEnable);
1076 if (warningInterface != sensorMap.end())
1077 {
James Feistfcd2d3a2020-05-28 10:38:15 -07001078 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001079
1080 auto warningHigh = warningMap.find("WarningAlarmHigh");
1081 auto warningLow = warningMap.find("WarningAlarmLow");
1082 auto warningHighAlarm = false;
1083 auto warningLowAlarm = false;
1084
1085 if (warningHigh != warningMap.end())
1086 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001087 warningHighAlarm = std::get<bool>(warningHigh->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001088 }
1089 if (warningLow != warningMap.end())
1090 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001091 warningLowAlarm = std::get<bool>(warningLow->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001092 }
1093 if (warningHighAlarm)
1094 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001095 assertions.set(
1096 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1097 upperNonCriticalGoingHigh));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001098 }
1099 if (warningLowAlarm)
1100 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001101 assertions.set(
1102 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1103 lowerNonCriticalGoingLow));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001104 }
1105 }
1106 if (criticalInterface != sensorMap.end())
1107 {
James Feistfcd2d3a2020-05-28 10:38:15 -07001108 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001109
1110 auto criticalHigh = criticalMap.find("CriticalAlarmHigh");
1111 auto criticalLow = criticalMap.find("CriticalAlarmLow");
1112 auto criticalHighAlarm = false;
1113 auto criticalLowAlarm = false;
1114
1115 if (criticalHigh != criticalMap.end())
1116 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001117 criticalHighAlarm = std::get<bool>(criticalHigh->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001118 }
1119 if (criticalLow != criticalMap.end())
1120 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001121 criticalLowAlarm = std::get<bool>(criticalLow->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001122 }
1123 if (criticalHighAlarm)
1124 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001125 assertions.set(
1126 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1127 upperCriticalGoingHigh));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001128 }
1129 if (criticalLowAlarm)
1130 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001131 assertions.set(static_cast<size_t>(
1132 IPMIGetSensorEventEnableThresholds::lowerCriticalGoingLow));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001133 }
1134 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001135 }
1136
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001137 return ipmi::responseSuccess(sensorEventStatus, assertions, deassertions);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001138}
1139
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001140static int getSensorDataRecord(ipmi::Context::ptr ctx,
1141 std::vector<uint8_t>& recordData,
1142 uint16_t recordID)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001143{
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001144 size_t fruCount = 0;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001145 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
1146 if (ret != ipmi::ccSuccess)
1147 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001148 phosphor::logging::log<phosphor::logging::level::ERR>(
1149 "getSensorDataRecord: getFruSdrCount error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001150 return GENERAL_ERROR;
1151 }
1152
1153 size_t lastRecord = sensorTree.size() + fruCount +
1154 ipmi::storage::type12Count +
1155 ipmi::storage::nmDiscoverySDRCount - 1;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001156 if (recordID == lastRecordIndex)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001157 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001158 recordID = lastRecord;
1159 }
1160 if (recordID > lastRecord)
1161 {
1162 phosphor::logging::log<phosphor::logging::level::ERR>(
1163 "getSensorDataRecord: recordID > lastRecord error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001164 return GENERAL_ERROR;
1165 }
1166
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001167 if (recordID >= sensorTree.size())
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001168 {
1169 size_t fruIndex = recordID - sensorTree.size();
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001170 size_t type12End = fruCount + ipmi::storage::type12Count;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001171
1172 if (fruIndex >= type12End)
1173 {
1174 // NM discovery SDR
1175 size_t nmDiscoveryIndex = fruIndex - type12End;
1176 if (nmDiscoveryIndex >= ipmi::storage::nmDiscoverySDRCount)
1177 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001178 phosphor::logging::log<phosphor::logging::level::ERR>(
1179 "getSensorDataRecord: NM DiscoveryIndex error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001180 return GENERAL_ERROR;
1181 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001182 recordData =
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001183 ipmi::storage::getNMDiscoverySDR(nmDiscoveryIndex, recordID);
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001184 }
1185 else if (fruIndex >= fruCount)
1186 {
1187 // handle type 12 hardcoded records
1188 size_t type12Index = fruIndex - fruCount;
1189 if (type12Index >= ipmi::storage::type12Count)
1190 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001191 phosphor::logging::log<phosphor::logging::level::ERR>(
1192 "getSensorDataRecord: type12Index error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001193 return GENERAL_ERROR;
1194 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001195 recordData = ipmi::storage::getType12SDRs(type12Index, recordID);
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001196 }
1197 else
1198 {
1199 // handle fru records
1200 get_sdr::SensorDataFruRecord data;
1201 ret = ipmi::storage::getFruSdrs(ctx, fruIndex, data);
1202 if (ret != IPMI_CC_OK)
1203 {
1204 return GENERAL_ERROR;
1205 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001206 data.header.record_id_msb = recordID >> 8;
1207 data.header.record_id_lsb = recordID & 0xFF;
1208 recordData.insert(recordData.end(), (uint8_t*)&data,
1209 ((uint8_t*)&data) + sizeof(data));
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001210 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001211
1212 return 0;
1213 }
1214
1215 std::string connection;
1216 std::string path;
1217 auto status = getSensorConnection(ctx, recordID, connection, path);
1218 if (status)
1219 {
1220 phosphor::logging::log<phosphor::logging::level::ERR>(
1221 "getSensorDataRecord: getSensorConnection error");
1222 return GENERAL_ERROR;
1223 }
1224 SensorMap sensorMap;
1225 if (!getSensorMap(ctx->yield, connection, path, sensorMap,
1226 sensorMapUpdatePeriod))
1227 {
1228 phosphor::logging::log<phosphor::logging::level::ERR>(
1229 "getSensorDataRecord: getSensorMap error");
1230 return GENERAL_ERROR;
1231 }
1232 uint16_t sensorNum = getSensorNumberFromPath(path);
1233 if (sensorNum == invalidSensorNumber)
1234 {
1235 phosphor::logging::log<phosphor::logging::level::ERR>(
1236 "getSensorDataRecord: invalidSensorNumber");
1237 return GENERAL_ERROR;
1238 }
1239 uint8_t sensornumber = static_cast<uint8_t>(sensorNum);
1240 uint8_t lun = static_cast<uint8_t>(sensorNum >> 8);
1241
1242 get_sdr::SensorDataFullRecord record = {0};
1243
1244 get_sdr::header::set_record_id(
1245 recordID, reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&record));
1246
1247 record.header.sdr_version = ipmiSdrVersion;
1248 record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD;
1249 record.header.record_length = sizeof(get_sdr::SensorDataFullRecord) -
1250 sizeof(get_sdr::SensorDataRecordHeader);
1251 record.key.owner_id = 0x20;
1252 record.key.owner_lun = lun;
1253 record.key.sensor_number = sensornumber;
1254
1255 record.body.sensor_capabilities = 0x68; // auto rearm - todo hysteresis
1256 record.body.sensor_type = getSensorTypeFromPath(path);
1257 std::string type = getSensorTypeStringFromPath(path);
1258 auto typeCstr = type.c_str();
1259 auto findUnits = sensorUnits.find(typeCstr);
1260 if (findUnits != sensorUnits.end())
1261 {
1262 record.body.sensor_units_2_base =
1263 static_cast<uint8_t>(findUnits->second);
1264 } // else default 0x0 unspecified
1265
1266 record.body.event_reading_type = getSensorEventTypeFromPath(path);
1267
1268 auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
1269 if (sensorObject == sensorMap.end())
1270 {
1271 phosphor::logging::log<phosphor::logging::level::ERR>(
1272 "getSensorDataRecord: sensorObject error");
1273 return GENERAL_ERROR;
1274 }
1275
1276 uint8_t entityId = 0;
1277 uint8_t entityInstance = 0x01;
1278
1279 // follow the association chain to get the parent board's entityid and
1280 // entityInstance
1281 updateIpmiFromAssociation(path, sensorMap, entityId, entityInstance);
1282
1283 record.body.entity_id = entityId;
1284 record.body.entity_instance = entityInstance;
1285
1286 auto maxObject = sensorObject->second.find("MaxValue");
1287 auto minObject = sensorObject->second.find("MinValue");
1288
1289 // If min and/or max are left unpopulated,
1290 // then default to what a signed byte would be, namely (-128,127) range.
1291 auto max = static_cast<double>(std::numeric_limits<int8_t>::max());
1292 auto min = static_cast<double>(std::numeric_limits<int8_t>::lowest());
1293 if (maxObject != sensorObject->second.end())
1294 {
1295 max = std::visit(VariantToDoubleVisitor(), maxObject->second);
1296 }
1297
1298 if (minObject != sensorObject->second.end())
1299 {
1300 min = std::visit(VariantToDoubleVisitor(), minObject->second);
1301 }
1302
1303 int16_t mValue = 0;
1304 int8_t rExp = 0;
1305 int16_t bValue = 0;
1306 int8_t bExp = 0;
1307 bool bSigned = false;
1308
1309 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
1310 {
1311 phosphor::logging::log<phosphor::logging::level::ERR>(
1312 "getSensorDataRecord: getSensorAttributes error");
1313 return GENERAL_ERROR;
1314 }
1315
1316 // The record.body is a struct SensorDataFullRecordBody
1317 // from sensorhandler.hpp in phosphor-ipmi-host.
1318 // The meaning of these bits appears to come from
1319 // table 43.1 of the IPMI spec.
1320 // The above 5 sensor attributes are stuffed in as follows:
1321 // Byte 21 = AA000000 = analog interpretation, 10 signed, 00 unsigned
1322 // Byte 22-24 are for other purposes
1323 // Byte 25 = MMMMMMMM = LSB of M
1324 // Byte 26 = MMTTTTTT = MSB of M (signed), and Tolerance
1325 // Byte 27 = BBBBBBBB = LSB of B
1326 // Byte 28 = BBAAAAAA = MSB of B (signed), and LSB of Accuracy
1327 // Byte 29 = AAAAEE00 = MSB of Accuracy, exponent of Accuracy
1328 // Byte 30 = RRRRBBBB = rExp (signed), bExp (signed)
1329
1330 // apply M, B, and exponents, M and B are 10 bit values, exponents are 4
1331 record.body.m_lsb = mValue & 0xFF;
1332
1333 uint8_t mBitSign = (mValue < 0) ? 1 : 0;
1334 uint8_t mBitNine = (mValue & 0x0100) >> 8;
1335
1336 // move the smallest bit of the MSB into place (bit 9)
1337 // the MSbs are bits 7:8 in m_msb_and_tolerance
1338 record.body.m_msb_and_tolerance = (mBitSign << 7) | (mBitNine << 6);
1339
1340 record.body.b_lsb = bValue & 0xFF;
1341
1342 uint8_t bBitSign = (bValue < 0) ? 1 : 0;
1343 uint8_t bBitNine = (bValue & 0x0100) >> 8;
1344
1345 // move the smallest bit of the MSB into place (bit 9)
1346 // the MSbs are bits 7:8 in b_msb_and_accuracy_lsb
1347 record.body.b_msb_and_accuracy_lsb = (bBitSign << 7) | (bBitNine << 6);
1348
1349 uint8_t rExpSign = (rExp < 0) ? 1 : 0;
1350 uint8_t rExpBits = rExp & 0x07;
1351
1352 uint8_t bExpSign = (bExp < 0) ? 1 : 0;
1353 uint8_t bExpBits = bExp & 0x07;
1354
1355 // move rExp and bExp into place
1356 record.body.r_b_exponents =
1357 (rExpSign << 7) | (rExpBits << 4) | (bExpSign << 3) | bExpBits;
1358
1359 // Set the analog reading byte interpretation accordingly
1360 record.body.sensor_units_1 = (bSigned ? 1 : 0) << 7;
1361
1362 // TODO(): Perhaps care about Tolerance, Accuracy, and so on
1363 // These seem redundant, but derivable from the above 5 attributes
1364 // Original comment said "todo fill out rest of units"
1365
1366 // populate sensor name from path
1367 std::string name;
1368 size_t nameStart = path.rfind("/");
1369 if (nameStart != std::string::npos)
1370 {
1371 name = path.substr(nameStart + 1, std::string::npos - nameStart);
1372 }
1373
1374 std::replace(name.begin(), name.end(), '_', ' ');
1375 if (name.size() > FULL_RECORD_ID_STR_MAX_LENGTH)
1376 {
1377 // try to not truncate by replacing common words
1378 constexpr std::array<std::pair<const char*, const char*>, 2>
1379 replaceWords = {std::make_pair("Output", "Out"),
1380 std::make_pair("Input", "In")};
1381 for (const auto& [find, replace] : replaceWords)
1382 {
1383 boost::replace_all(name, find, replace);
1384 }
1385
1386 name.resize(FULL_RECORD_ID_STR_MAX_LENGTH);
1387 }
1388 record.body.id_string_info = name.size();
1389 std::strncpy(record.body.id_string, name.c_str(),
1390 sizeof(record.body.id_string));
1391
Josh Lehan06aa21a2020-10-28 21:59:06 -07001392 // Remember the sensor name, as determined for this sensor number
1393 details::sdrStatsTable.updateName(sensornumber, name);
1394
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001395 IPMIThresholds thresholdData;
1396 try
1397 {
1398 thresholdData = getIPMIThresholds(sensorMap);
1399 }
1400 catch (std::exception&)
1401 {
1402 phosphor::logging::log<phosphor::logging::level::ERR>(
1403 "getSensorDataRecord: getIPMIThresholds error");
1404 return GENERAL_ERROR;
1405 }
1406
1407 if (thresholdData.criticalHigh)
1408 {
1409 record.body.upper_critical_threshold = *thresholdData.criticalHigh;
1410 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1411 IPMISensorEventEnableThresholds::criticalThreshold);
1412 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1413 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
1414 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1415 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
1416 record.body.discrete_reading_setting_mask[0] |=
1417 static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
1418 }
1419 if (thresholdData.warningHigh)
1420 {
1421 record.body.upper_noncritical_threshold = *thresholdData.warningHigh;
1422 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1423 IPMISensorEventEnableThresholds::nonCriticalThreshold);
1424 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1425 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
1426 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1427 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
1428 record.body.discrete_reading_setting_mask[0] |=
1429 static_cast<uint8_t>(IPMISensorReadingByte3::upperNonCritical);
1430 }
1431 if (thresholdData.criticalLow)
1432 {
1433 record.body.lower_critical_threshold = *thresholdData.criticalLow;
1434 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1435 IPMISensorEventEnableThresholds::criticalThreshold);
1436 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1437 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
1438 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1439 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
1440 record.body.discrete_reading_setting_mask[0] |=
1441 static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
1442 }
1443 if (thresholdData.warningLow)
1444 {
1445 record.body.lower_noncritical_threshold = *thresholdData.warningLow;
1446 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1447 IPMISensorEventEnableThresholds::nonCriticalThreshold);
1448 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1449 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
1450 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1451 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
1452 record.body.discrete_reading_setting_mask[0] |=
1453 static_cast<uint8_t>(IPMISensorReadingByte3::lowerNonCritical);
1454 }
1455
1456 // everything that is readable is setable
1457 record.body.discrete_reading_setting_mask[1] =
1458 record.body.discrete_reading_setting_mask[0];
1459 recordData.insert(recordData.end(), (uint8_t*)&record,
1460 ((uint8_t*)&record) + sizeof(record));
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001461 return 0;
1462}
1463
1464/** @brief implements the get SDR Info command
1465 * @param count - Operation
1466 *
1467 * @returns IPMI completion code plus response data
1468 * - sdrCount - sensor/SDR count
1469 * - lunsAndDynamicPopulation - static/Dynamic sensor population flag
1470 */
1471static ipmi::RspType<uint8_t, // respcount
1472 uint8_t, // dynamic population flags
1473 uint32_t // last time a sensor was added
1474 >
1475 ipmiSensorGetDeviceSdrInfo(ipmi::Context::ptr ctx,
1476 std::optional<uint8_t> count)
1477{
1478 uint8_t sdrCount = 0;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001479 uint16_t recordID = 0;
1480 std::vector<uint8_t> record;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001481 // Sensors are dynamically allocated, and there is at least one LUN
1482 uint8_t lunsAndDynamicPopulation = 0x80;
1483 constexpr uint8_t getSdrCount = 0x01;
1484 constexpr uint8_t getSensorCount = 0x00;
1485
1486 if (!getSensorSubtree(sensorTree) || sensorTree.empty())
1487 {
1488 return ipmi::responseResponseError();
1489 }
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001490 uint16_t numSensors = sensorTree.size();
1491 if (count.value_or(0) == getSdrCount)
1492 {
1493 // Count the number of Type 1 SDR entries assigned to the LUN
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001494 while (!getSensorDataRecord(ctx, record, recordID++))
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001495 {
1496 get_sdr::SensorDataRecordHeader* hdr =
1497 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001498 record.data());
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001499 if (hdr->record_type == get_sdr::SENSOR_DATA_FULL_RECORD)
1500 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001501 get_sdr::SensorDataFullRecord* recordData =
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001502 reinterpret_cast<get_sdr::SensorDataFullRecord*>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001503 record.data());
1504 if (ctx->lun == recordData->key.owner_lun)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001505 {
1506 sdrCount++;
1507 }
1508 }
1509 }
1510 }
1511 else if (count.value_or(0) == getSensorCount)
1512 {
1513 // Return the number of sensors attached to the LUN
1514 if ((ctx->lun == 0) && (numSensors > 0))
1515 {
1516 sdrCount =
1517 (numSensors > maxSensorsPerLUN) ? maxSensorsPerLUN : numSensors;
1518 }
1519 else if ((ctx->lun == 1) && (numSensors > maxSensorsPerLUN))
1520 {
1521 sdrCount = (numSensors > (2 * maxSensorsPerLUN))
1522 ? maxSensorsPerLUN
1523 : (numSensors - maxSensorsPerLUN) & maxSensorsPerLUN;
1524 }
1525 else if (ctx->lun == 3)
1526 {
1527 if (numSensors <= maxIPMISensors)
1528 {
1529 sdrCount =
1530 (numSensors - (2 * maxSensorsPerLUN)) & maxSensorsPerLUN;
1531 }
1532 else
1533 {
1534 // error
1535 throw std::out_of_range(
1536 "Maximum number of IPMI sensors exceeded.");
1537 }
1538 }
1539 }
1540 else
1541 {
1542 return ipmi::responseInvalidFieldRequest();
1543 }
1544
1545 // Get Sensor count. This returns the number of sensors
1546 if (numSensors > 0)
1547 {
1548 lunsAndDynamicPopulation |= 1;
1549 }
1550 if (numSensors > maxSensorsPerLUN)
1551 {
1552 lunsAndDynamicPopulation |= 2;
1553 }
1554 if (numSensors >= (maxSensorsPerLUN * 2))
1555 {
1556 lunsAndDynamicPopulation |= 8;
1557 }
1558 if (numSensors > maxIPMISensors)
1559 {
1560 // error
1561 throw std::out_of_range("Maximum number of IPMI sensors exceeded.");
1562 }
1563
1564 return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation,
1565 sdrLastAdd);
1566}
1567
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001568/* end sensor commands */
1569
1570/* storage commands */
1571
James Feist74c50c62019-08-14 14:18:41 -07001572ipmi::RspType<uint8_t, // sdr version
1573 uint16_t, // record count
1574 uint16_t, // free space
1575 uint32_t, // most recent addition
1576 uint32_t, // most recent erase
1577 uint8_t // operationSupport
1578 >
James Feist25690252019-12-23 12:25:49 -08001579 ipmiStorageGetSDRRepositoryInfo(ipmi::Context::ptr ctx)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001580{
James Feist74c50c62019-08-14 14:18:41 -07001581 constexpr const uint16_t unspecifiedFreeSpace = 0xFFFF;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001582 if (!getSensorSubtree(sensorTree) && sensorTree.empty())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001583 {
James Feist74c50c62019-08-14 14:18:41 -07001584 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001585 }
1586
James Feist74c50c62019-08-14 14:18:41 -07001587 size_t fruCount = 0;
James Feist25690252019-12-23 12:25:49 -08001588 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
James Feist74c50c62019-08-14 14:18:41 -07001589 if (ret != ipmi::ccSuccess)
1590 {
1591 return ipmi::response(ret);
1592 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001593
James Feist74c50c62019-08-14 14:18:41 -07001594 uint16_t recordCount =
1595 sensorTree.size() + fruCount + ipmi::storage::type12Count;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001596
James Feist74c50c62019-08-14 14:18:41 -07001597 uint8_t operationSupport = static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001598 SdrRepositoryInfoOps::overflow); // write not supported
James Feist74c50c62019-08-14 14:18:41 -07001599
1600 operationSupport |=
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001601 static_cast<uint8_t>(SdrRepositoryInfoOps::allocCommandSupported);
James Feist74c50c62019-08-14 14:18:41 -07001602 operationSupport |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001603 SdrRepositoryInfoOps::reserveSDRRepositoryCommandSupported);
James Feist74c50c62019-08-14 14:18:41 -07001604 return ipmi::responseSuccess(ipmiSdrVersion, recordCount,
1605 unspecifiedFreeSpace, sdrLastAdd,
1606 sdrLastRemove, operationSupport);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001607}
1608
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001609/** @brief implements the get SDR allocation info command
1610 *
1611 * @returns IPMI completion code plus response data
1612 * - allocUnits - Number of possible allocation units
1613 * - allocUnitSize - Allocation unit size in bytes.
1614 * - allocUnitFree - Number of free allocation units
1615 * - allocUnitLargestFree - Largest free block in allocation units
1616 * - maxRecordSize - Maximum record size in allocation units.
1617 */
1618ipmi::RspType<uint16_t, // allocUnits
1619 uint16_t, // allocUnitSize
1620 uint16_t, // allocUnitFree
1621 uint16_t, // allocUnitLargestFree
1622 uint8_t // maxRecordSize
1623 >
1624 ipmiStorageGetSDRAllocationInfo()
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001625{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001626 // 0000h unspecified number of alloc units
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001627 constexpr uint16_t allocUnits = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001628
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001629 constexpr uint16_t allocUnitFree = 0;
1630 constexpr uint16_t allocUnitLargestFree = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001631 // only allow one block at a time
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001632 constexpr uint8_t maxRecordSize = 1;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001633
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001634 return ipmi::responseSuccess(allocUnits, maxSDRTotalSize, allocUnitFree,
1635 allocUnitLargestFree, maxRecordSize);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001636}
1637
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001638/** @brief implements the reserve SDR command
1639 * @returns IPMI completion code plus response data
1640 * - sdrReservationID
1641 */
1642ipmi::RspType<uint16_t> ipmiStorageReserveSDR()
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001643{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001644 sdrReservationID++;
James Feista80cb902019-02-14 13:05:25 -08001645 if (sdrReservationID == 0)
1646 {
1647 sdrReservationID++;
1648 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001649
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001650 return ipmi::responseSuccess(sdrReservationID);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001651}
1652
James Feistb49a98a2019-04-16 13:48:09 -07001653ipmi::RspType<uint16_t, // next record ID
1654 std::vector<uint8_t> // payload
1655 >
James Feist25690252019-12-23 12:25:49 -08001656 ipmiStorageGetSDR(ipmi::Context::ptr ctx, uint16_t reservationID,
1657 uint16_t recordID, uint8_t offset, uint8_t bytesToRead)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001658{
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001659 size_t fruCount = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001660 // reservation required for partial reads with non zero offset into
1661 // record
James Feistb49a98a2019-04-16 13:48:09 -07001662 if ((sdrReservationID == 0 || reservationID != sdrReservationID) && offset)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001663 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001664 phosphor::logging::log<phosphor::logging::level::ERR>(
1665 "ipmiStorageGetSDR: responseInvalidReservationId");
James Feistb49a98a2019-04-16 13:48:09 -07001666 return ipmi::responseInvalidReservationId();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001667 }
James Feist25690252019-12-23 12:25:49 -08001668 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
James Feist74c50c62019-08-14 14:18:41 -07001669 if (ret != ipmi::ccSuccess)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001670 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001671 phosphor::logging::log<phosphor::logging::level::ERR>(
1672 "ipmiStorageGetSDR: getFruSdrCount error");
James Feistb49a98a2019-04-16 13:48:09 -07001673 return ipmi::response(ret);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001674 }
1675
Yong Lifee5e4c2020-01-17 19:36:29 +08001676 size_t lastRecord = sensorTree.size() + fruCount +
1677 ipmi::storage::type12Count +
1678 ipmi::storage::nmDiscoverySDRCount - 1;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001679 uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF;
1680
1681 if (!getSensorSubtree(sensorTree) && sensorTree.empty())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001682 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001683 phosphor::logging::log<phosphor::logging::level::ERR>(
1684 "ipmiStorageGetSDR: getSensorSubtree error");
1685 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001686 }
1687
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001688 std::vector<uint8_t> record;
1689 if (getSensorDataRecord(ctx, record, recordID))
1690 {
1691 phosphor::logging::log<phosphor::logging::level::ERR>(
1692 "ipmiStorageGetSDR: fail to get SDR");
1693 return ipmi::responseInvalidFieldRequest();
1694 }
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001695 get_sdr::SensorDataRecordHeader* hdr =
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001696 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(record.data());
Kuiying Wangb9109872021-01-15 15:54:59 +08001697 if (!hdr)
1698 {
1699 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001700 "ipmiStorageGetSDR: record header is null");
1701 return ipmi::responseSuccess(nextRecordId, record);
Kuiying Wangb9109872021-01-15 15:54:59 +08001702 }
1703
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001704 size_t sdrLength =
1705 sizeof(get_sdr::SensorDataRecordHeader) + hdr->record_length;
1706 if (sdrLength < (offset + bytesToRead))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001707 {
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001708 bytesToRead = sdrLength - offset;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001709 }
1710
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001711 uint8_t* respStart = reinterpret_cast<uint8_t*>(hdr) + offset;
Kuiying Wangb9109872021-01-15 15:54:59 +08001712 if (!respStart)
1713 {
1714 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001715 "ipmiStorageGetSDR: record is null");
1716 return ipmi::responseSuccess(nextRecordId, record);
Kuiying Wangb9109872021-01-15 15:54:59 +08001717 }
James Feistb49a98a2019-04-16 13:48:09 -07001718 std::vector<uint8_t> recordData(respStart, respStart + bytesToRead);
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001719
James Feistb49a98a2019-04-16 13:48:09 -07001720 return ipmi::responseSuccess(nextRecordId, recordData);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001721}
1722/* end storage commands */
1723
1724void registerSensorFunctions()
1725{
Jason M. Billsae6bdb12019-04-02 12:00:04 -07001726 // <Platform Event>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001727 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1728 ipmi::sensor_event::cmdPlatformEvent,
1729 ipmi::Privilege::Operator, ipmiSenPlatformEvent);
Jason M. Billsae6bdb12019-04-02 12:00:04 -07001730
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001731 // <Get Sensor Reading>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001732 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1733 ipmi::sensor_event::cmdGetSensorReading,
1734 ipmi::Privilege::User, ipmiSenGetSensorReading);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001735
1736 // <Get Sensor Threshold>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001737 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1738 ipmi::sensor_event::cmdGetSensorThreshold,
1739 ipmi::Privilege::User, ipmiSenGetSensorThresholds);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001740
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +00001741 // <Set Sensor Threshold>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001742 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1743 ipmi::sensor_event::cmdSetSensorThreshold,
1744 ipmi::Privilege::Operator,
1745 ipmiSenSetSensorThresholds);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001746
1747 // <Get Sensor Event Enable>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001748 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1749 ipmi::sensor_event::cmdGetSensorEventEnable,
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +00001750 ipmi::Privilege::User, ipmiSenGetSensorEventEnable);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001751
1752 // <Get Sensor Event Status>
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001753 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1754 ipmi::sensor_event::cmdGetSensorEventStatus,
1755 ipmi::Privilege::User, ipmiSenGetSensorEventStatus);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001756
1757 // register all storage commands for both Sensor and Storage command
1758 // versions
1759
1760 // <Get SDR Repository Info>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001761 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1762 ipmi::storage::cmdGetSdrRepositoryInfo,
1763 ipmi::Privilege::User,
1764 ipmiStorageGetSDRRepositoryInfo);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001765
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001766 // <Get Device SDR Info>
1767 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1768 ipmi::sensor_event::cmdGetDeviceSdrInfo,
1769 ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo);
1770
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001771 // <Get SDR Allocation Info>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001772 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1773 ipmi::storage::cmdGetSdrRepositoryAllocInfo,
1774 ipmi::Privilege::User,
1775 ipmiStorageGetSDRAllocationInfo);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001776
1777 // <Reserve SDR Repo>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001778 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1779 ipmi::sensor_event::cmdReserveDeviceSdrRepository,
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001780 ipmi::Privilege::User, ipmiStorageReserveSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001781
Vernon Mauery98bbf692019-09-16 11:14:59 -07001782 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1783 ipmi::storage::cmdReserveSdrRepository,
1784 ipmi::Privilege::User, ipmiStorageReserveSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001785
1786 // <Get Sdr>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001787 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1788 ipmi::sensor_event::cmdGetDeviceSdr,
1789 ipmi::Privilege::User, ipmiStorageGetSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001790
Vernon Mauery98bbf692019-09-16 11:14:59 -07001791 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1792 ipmi::storage::cmdGetSdr, ipmi::Privilege::User,
1793 ipmiStorageGetSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001794}
1795} // namespace ipmi