blob: ff429b69ebb2b419fbb45b81edbc1e13729fd2c6 [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
James Feistfcd2d3a2020-05-28 10:38:15 -0700340ipmi::RspType<> ipmiSenPlatformEvent(ipmi::message::Payload& p)
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700341{
James Feist7aaf3fe2019-06-25 11:52:11 -0700342 constexpr const uint8_t meId = 0x2C;
343 constexpr const uint8_t meSensorNum = 0x17;
344 constexpr const uint8_t disabled = 0x80;
345
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700346 uint8_t generatorID = 0;
347 uint8_t evmRev = 0;
348 uint8_t sensorType = 0;
349 uint8_t sensorNum = 0;
350 uint8_t eventType = 0;
351 uint8_t eventData1 = 0;
352 std::optional<uint8_t> eventData2 = 0;
353 std::optional<uint8_t> eventData3 = 0;
354
355 // todo: This check is supposed to be based on the incoming channel.
356 // e.g. system channel will provide upto 8 bytes including generator
357 // ID, but ipmb channel will provide only up to 7 bytes without the
358 // generator ID.
359 // Support for this check is coming in future patches, so for now just base
360 // it on if the first byte is the EvMRev (0x04).
361 if (p.size() && p.data()[0] == 0x04)
362 {
363 p.unpack(evmRev, sensorType, sensorNum, eventType, eventData1,
364 eventData2, eventData3);
365 // todo: the generator ID for this channel is supposed to come from the
366 // IPMB requesters slave address. Support for this is coming in future
367 // patches, so for now just assume it is coming from the ME (0x2C).
368 generatorID = 0x2C;
369 }
370 else
371 {
372 p.unpack(generatorID, evmRev, sensorType, sensorNum, eventType,
373 eventData1, eventData2, eventData3);
374 }
375 if (!p.fullyUnpacked())
376 {
377 return ipmi::responseReqDataLenInvalid();
378 }
379
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700380 // Send this request to the Redfish hooks to log it as a Redfish message
381 // instead. There is no need to add it to the SEL, so just return success.
382 intel_oem::ipmi::sel::checkRedfishHooks(
383 generatorID, evmRev, sensorType, sensorNum, eventType, eventData1,
384 eventData2.value_or(0xFF), eventData3.value_or(0xFF));
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700385
James Feist7aaf3fe2019-06-25 11:52:11 -0700386 if (generatorID == meId && sensorNum == meSensorNum && eventData2 &&
387 eventData3)
388 {
389 setMeStatus(*eventData2, *eventData3, (eventType & disabled));
390 }
391
Jason M. Billsae6bdb12019-04-02 12:00:04 -0700392 return ipmi::responseSuccess();
393}
394
James Feist0cd014a2019-04-08 15:04:33 -0700395ipmi::RspType<uint8_t, uint8_t, uint8_t, std::optional<uint8_t>>
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700396 ipmiSenGetSensorReading(ipmi::Context::ptr ctx, uint8_t sensnum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700397{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700398 std::string connection;
399 std::string path;
400
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700401 auto status = getSensorConnection(ctx, sensnum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700402 if (status)
403 {
James Feist0cd014a2019-04-08 15:04:33 -0700404 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700405 }
406
407 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700408 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700409 {
James Feist0cd014a2019-04-08 15:04:33 -0700410 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700411 }
412 auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
413
414 if (sensorObject == sensorMap.end() ||
415 sensorObject->second.find("Value") == sensorObject->second.end())
416 {
James Feist0cd014a2019-04-08 15:04:33 -0700417 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700418 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700419 auto& valueVariant = sensorObject->second["Value"];
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700420 double reading = std::visit(VariantToDoubleVisitor(), valueVariant);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700421
Yong Li1f2eb5e2019-05-23 14:07:17 +0800422 double max = 0;
423 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700424 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700425
426 int16_t mValue = 0;
427 int16_t bValue = 0;
428 int8_t rExp = 0;
429 int8_t bExp = 0;
430 bool bSigned = false;
431
432 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
433 {
James Feist0cd014a2019-04-08 15:04:33 -0700434 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700435 }
436
James Feist0cd014a2019-04-08 15:04:33 -0700437 uint8_t value =
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700438 scaleIPMIValueFromDouble(reading, mValue, rExp, bValue, bExp, bSigned);
James Feist0cd014a2019-04-08 15:04:33 -0700439 uint8_t operation =
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700440 static_cast<uint8_t>(IPMISensorReadingByte2::sensorScanningEnable);
James Feist0cd014a2019-04-08 15:04:33 -0700441 operation |=
James Feist81a95c12019-03-01 15:08:28 -0800442 static_cast<uint8_t>(IPMISensorReadingByte2::eventMessagesEnable);
James Feist1ee6ed82020-06-17 16:16:50 -0700443 bool notReading = std::isnan(reading);
444
445 if (!notReading)
446 {
447 auto availableObject =
448 sensorMap.find("xyz.openbmc_project.State.Decorator.Availability");
449 if (availableObject != sensorMap.end())
450 {
451 auto findAvailable = availableObject->second.find("Available");
452 if (findAvailable != availableObject->second.end())
453 {
454 bool* available = std::get_if<bool>(&(findAvailable->second));
455 if (available && !(*available))
456 {
457 notReading = true;
458 }
459 }
460 }
461 }
462
463 if (notReading)
464 {
465 operation |= static_cast<uint8_t>(
466 IPMISensorReadingByte2::readingStateUnavailable);
467 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700468
Josh Lehan06aa21a2020-10-28 21:59:06 -0700469 int byteValue;
470 if (bSigned)
471 {
472 byteValue = static_cast<int>(static_cast<int8_t>(value));
473 }
474 else
475 {
476 byteValue = static_cast<int>(static_cast<uint8_t>(value));
477 }
478
479 // Keep stats on the reading just obtained, even if it is "NaN"
480 if (details::sdrStatsTable.updateReading(sensnum, reading, byteValue))
481 {
482 // This is the first reading, show the coefficients
483 double step = (max - min) / 255.0;
484 std::cerr << "IPMI sensor " << details::sdrStatsTable.getName(sensnum)
485 << ": Range min=" << min << " max=" << max
486 << ", step=" << step
487 << ", Coefficients mValue=" << static_cast<int>(mValue)
488 << " rExp=" << static_cast<int>(rExp)
489 << " bValue=" << static_cast<int>(bValue)
490 << " bExp=" << static_cast<int>(bExp)
491 << " bSigned=" << static_cast<int>(bSigned) << "\n";
492 };
493
James Feist0cd014a2019-04-08 15:04:33 -0700494 uint8_t thresholds = 0;
495
496 auto warningObject =
497 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
498 if (warningObject != sensorMap.end())
499 {
500 auto alarmHigh = warningObject->second.find("WarningAlarmHigh");
501 auto alarmLow = warningObject->second.find("WarningAlarmLow");
502 if (alarmHigh != warningObject->second.end())
503 {
504 if (std::get<bool>(alarmHigh->second))
505 {
506 thresholds |= static_cast<uint8_t>(
507 IPMISensorReadingByte3::upperNonCritical);
508 }
509 }
510 if (alarmLow != warningObject->second.end())
511 {
512 if (std::get<bool>(alarmLow->second))
513 {
514 thresholds |= static_cast<uint8_t>(
515 IPMISensorReadingByte3::lowerNonCritical);
516 }
517 }
518 }
519
520 auto criticalObject =
521 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
522 if (criticalObject != sensorMap.end())
523 {
524 auto alarmHigh = criticalObject->second.find("CriticalAlarmHigh");
525 auto alarmLow = criticalObject->second.find("CriticalAlarmLow");
526 if (alarmHigh != criticalObject->second.end())
527 {
528 if (std::get<bool>(alarmHigh->second))
529 {
530 thresholds |=
531 static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
532 }
533 }
534 if (alarmLow != criticalObject->second.end())
535 {
536 if (std::get<bool>(alarmLow->second))
537 {
538 thresholds |=
539 static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
540 }
541 }
542 }
543
544 // no discrete as of today so optional byte is never returned
545 return ipmi::responseSuccess(value, operation, thresholds, std::nullopt);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700546}
547
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000548/** @brief implements the Set Sensor threshold command
549 * @param sensorNumber - sensor number
550 * @param lowerNonCriticalThreshMask
551 * @param lowerCriticalThreshMask
552 * @param lowerNonRecovThreshMask
553 * @param upperNonCriticalThreshMask
554 * @param upperCriticalThreshMask
555 * @param upperNonRecovThreshMask
556 * @param reserved
557 * @param lowerNonCritical - lower non-critical threshold
558 * @param lowerCritical - Lower critical threshold
559 * @param lowerNonRecoverable - Lower non recovarable threshold
560 * @param upperNonCritical - Upper non-critical threshold
561 * @param upperCritical - Upper critical
562 * @param upperNonRecoverable - Upper Non-recoverable
563 *
564 * @returns IPMI completion code
565 */
566ipmi::RspType<> ipmiSenSetSensorThresholds(
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700567 ipmi::Context::ptr ctx, uint8_t sensorNum, bool lowerNonCriticalThreshMask,
568 bool lowerCriticalThreshMask, bool lowerNonRecovThreshMask,
569 bool upperNonCriticalThreshMask, bool upperCriticalThreshMask,
570 bool upperNonRecovThreshMask, uint2_t reserved, uint8_t lowerNonCritical,
571 uint8_t lowerCritical, uint8_t lowerNonRecoverable,
572 uint8_t upperNonCritical, uint8_t upperCritical,
573 uint8_t upperNonRecoverable)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700574{
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000575 constexpr uint8_t thresholdMask = 0xFF;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700576
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000577 if (reserved)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700578 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000579 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700580 }
581
582 // lower nc and upper nc not suppported on any sensor
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000583 if (lowerNonRecovThreshMask || upperNonRecovThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700584 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000585 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700586 }
587
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000588 // if none of the threshold mask are set, nothing to do
589 if (!(lowerNonCriticalThreshMask | lowerCriticalThreshMask |
590 lowerNonRecovThreshMask | upperNonCriticalThreshMask |
591 upperCriticalThreshMask | upperNonRecovThreshMask))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700592 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000593 return ipmi::responseSuccess();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700594 }
595
596 std::string connection;
597 std::string path;
598
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700599 ipmi::Cc status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700600 if (status)
601 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000602 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700603 }
604 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700605 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700606 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000607 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700608 }
609
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700610 double max = 0;
611 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700612 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700613
614 int16_t mValue = 0;
615 int16_t bValue = 0;
616 int8_t rExp = 0;
617 int8_t bExp = 0;
618 bool bSigned = false;
619
620 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
621 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000622 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700623 }
624
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700625 // store a vector of property name, value to set, and interface
626 std::vector<std::tuple<std::string, uint8_t, std::string>> thresholdsToSet;
627
628 // define the indexes of the tuple
629 constexpr uint8_t propertyName = 0;
630 constexpr uint8_t thresholdValue = 1;
631 constexpr uint8_t interface = 2;
632 // verifiy all needed fields are present
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000633 if (lowerCriticalThreshMask || upperCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700634 {
635 auto findThreshold =
636 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
637 if (findThreshold == sensorMap.end())
638 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000639 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700640 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000641 if (lowerCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700642 {
643 auto findLower = findThreshold->second.find("CriticalLow");
644 if (findLower == findThreshold->second.end())
645 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000646 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700647 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000648 thresholdsToSet.emplace_back("CriticalLow", lowerCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700649 findThreshold->first);
650 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000651 if (upperCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700652 {
653 auto findUpper = findThreshold->second.find("CriticalHigh");
654 if (findUpper == findThreshold->second.end())
655 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000656 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700657 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000658 thresholdsToSet.emplace_back("CriticalHigh", upperCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700659 findThreshold->first);
660 }
661 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000662 if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700663 {
664 auto findThreshold =
665 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
666 if (findThreshold == sensorMap.end())
667 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000668 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700669 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000670 if (lowerNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700671 {
672 auto findLower = findThreshold->second.find("WarningLow");
673 if (findLower == findThreshold->second.end())
674 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000675 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700676 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000677 thresholdsToSet.emplace_back("WarningLow", lowerNonCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700678 findThreshold->first);
679 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000680 if (upperNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700681 {
682 auto findUpper = findThreshold->second.find("WarningHigh");
683 if (findUpper == findThreshold->second.end())
684 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000685 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700686 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000687 thresholdsToSet.emplace_back("WarningHigh", upperNonCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700688 findThreshold->first);
689 }
690 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700691 for (const auto& property : thresholdsToSet)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700692 {
693 // from section 36.3 in the IPMI Spec, assume all linear
694 double valueToSet = ((mValue * std::get<thresholdValue>(property)) +
Josh Lehan86236a22019-11-18 17:53:33 -0800695 (bValue * std::pow(10.0, bExp))) *
696 std::pow(10.0, rExp);
Vernon Mauery15419dd2019-05-24 09:40:30 -0700697 setDbusProperty(
698 *getSdBus(), connection, path, std::get<interface>(property),
699 std::get<propertyName>(property), ipmi::Value(valueToSet));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700700 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000701 return ipmi::responseSuccess();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700702}
703
James Feistfcd2d3a2020-05-28 10:38:15 -0700704IPMIThresholds getIPMIThresholds(const SensorMap& sensorMap)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700705{
James Feist902c4c52019-04-16 14:51:31 -0700706 IPMIThresholds resp;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700707 auto warningInterface =
708 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
709 auto criticalInterface =
710 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
711
712 if ((warningInterface != sensorMap.end()) ||
713 (criticalInterface != sensorMap.end()))
714 {
715 auto sensorPair = sensorMap.find("xyz.openbmc_project.Sensor.Value");
716
717 if (sensorPair == sensorMap.end())
718 {
719 // should not have been able to find a sensor not implementing
720 // the sensor object
James Feist902c4c52019-04-16 14:51:31 -0700721 throw std::runtime_error("Invalid sensor map");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700722 }
723
Chen,Yugang606dd9f2019-07-01 10:37:30 +0800724 double max = 0;
725 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700726 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700727
728 int16_t mValue = 0;
729 int16_t bValue = 0;
730 int8_t rExp = 0;
731 int8_t bExp = 0;
732 bool bSigned = false;
733
734 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
735 {
James Feist902c4c52019-04-16 14:51:31 -0700736 throw std::runtime_error("Invalid sensor atrributes");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700737 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700738 if (warningInterface != sensorMap.end())
739 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700740 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700741
742 auto warningHigh = warningMap.find("WarningHigh");
743 auto warningLow = warningMap.find("WarningLow");
744
745 if (warningHigh != warningMap.end())
746 {
James Feist902c4c52019-04-16 14:51:31 -0700747
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700748 double value =
749 std::visit(VariantToDoubleVisitor(), warningHigh->second);
James Feist902c4c52019-04-16 14:51:31 -0700750 resp.warningHigh = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700751 value, mValue, rExp, bValue, bExp, bSigned);
752 }
753 if (warningLow != warningMap.end())
754 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700755 double value =
756 std::visit(VariantToDoubleVisitor(), warningLow->second);
James Feist902c4c52019-04-16 14:51:31 -0700757 resp.warningLow = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700758 value, mValue, rExp, bValue, bExp, bSigned);
759 }
760 }
761 if (criticalInterface != sensorMap.end())
762 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700763 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700764
765 auto criticalHigh = criticalMap.find("CriticalHigh");
766 auto criticalLow = criticalMap.find("CriticalLow");
767
768 if (criticalHigh != criticalMap.end())
769 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700770 double value =
771 std::visit(VariantToDoubleVisitor(), criticalHigh->second);
James Feist902c4c52019-04-16 14:51:31 -0700772 resp.criticalHigh = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700773 value, mValue, rExp, bValue, bExp, bSigned);
774 }
775 if (criticalLow != criticalMap.end())
776 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700777 double value =
778 std::visit(VariantToDoubleVisitor(), criticalLow->second);
James Feist902c4c52019-04-16 14:51:31 -0700779 resp.criticalLow = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700780 value, mValue, rExp, bValue, bExp, bSigned);
781 }
782 }
783 }
James Feist902c4c52019-04-16 14:51:31 -0700784 return resp;
785}
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700786
James Feist902c4c52019-04-16 14:51:31 -0700787ipmi::RspType<uint8_t, // readable
788 uint8_t, // lowerNCrit
789 uint8_t, // lowerCrit
790 uint8_t, // lowerNrecoverable
791 uint8_t, // upperNC
792 uint8_t, // upperCrit
793 uint8_t> // upperNRecoverable
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700794 ipmiSenGetSensorThresholds(ipmi::Context::ptr ctx, uint8_t sensorNumber)
James Feist902c4c52019-04-16 14:51:31 -0700795{
796 std::string connection;
797 std::string path;
798
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700799 auto status = getSensorConnection(ctx, sensorNumber, connection, path);
James Feist902c4c52019-04-16 14:51:31 -0700800 if (status)
801 {
802 return ipmi::response(status);
803 }
804
805 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700806 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
James Feist902c4c52019-04-16 14:51:31 -0700807 {
808 return ipmi::responseResponseError();
809 }
810
811 IPMIThresholds thresholdData;
812 try
813 {
814 thresholdData = getIPMIThresholds(sensorMap);
815 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700816 catch (std::exception&)
James Feist902c4c52019-04-16 14:51:31 -0700817 {
818 return ipmi::responseResponseError();
819 }
820
821 uint8_t readable = 0;
822 uint8_t lowerNC = 0;
823 uint8_t lowerCritical = 0;
824 uint8_t lowerNonRecoverable = 0;
825 uint8_t upperNC = 0;
826 uint8_t upperCritical = 0;
827 uint8_t upperNonRecoverable = 0;
828
829 if (thresholdData.warningHigh)
830 {
831 readable |=
832 1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperNonCritical);
833 upperNC = *thresholdData.warningHigh;
834 }
835 if (thresholdData.warningLow)
836 {
837 readable |=
838 1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerNonCritical);
839 lowerNC = *thresholdData.warningLow;
840 }
841
842 if (thresholdData.criticalHigh)
843 {
844 readable |=
845 1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperCritical);
846 upperCritical = *thresholdData.criticalHigh;
847 }
848 if (thresholdData.criticalLow)
849 {
850 readable |=
851 1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerCritical);
852 lowerCritical = *thresholdData.criticalLow;
853 }
854
855 return ipmi::responseSuccess(readable, lowerNC, lowerCritical,
856 lowerNonRecoverable, upperNC, upperCritical,
857 upperNonRecoverable);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700858}
859
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000860/** @brief implements the get Sensor event enable command
861 * @param sensorNumber - sensor number
862 *
863 * @returns IPMI completion code plus response data
864 * - enabled - Sensor Event messages
865 * - assertionEnabledLsb - Assertion event messages
866 * - assertionEnabledMsb - Assertion event messages
867 * - deassertionEnabledLsb - Deassertion event messages
868 * - deassertionEnabledMsb - Deassertion event messages
869 */
870
871ipmi::RspType<uint8_t, // enabled
872 uint8_t, // assertionEnabledLsb
873 uint8_t, // assertionEnabledMsb
874 uint8_t, // deassertionEnabledLsb
875 uint8_t> // deassertionEnabledMsb
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700876 ipmiSenGetSensorEventEnable(ipmi::Context::ptr ctx, uint8_t sensorNum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700877{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700878 std::string connection;
879 std::string path;
880
Patrick Venturea41714c2019-09-25 16:59:41 -0700881 uint8_t enabled = 0;
882 uint8_t assertionEnabledLsb = 0;
883 uint8_t assertionEnabledMsb = 0;
884 uint8_t deassertionEnabledLsb = 0;
885 uint8_t deassertionEnabledMsb = 0;
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000886
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700887 auto status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700888 if (status)
889 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000890 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700891 }
892
893 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700894 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700895 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000896 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700897 }
898
899 auto warningInterface =
900 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
901 auto criticalInterface =
902 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700903 if ((warningInterface != sensorMap.end()) ||
904 (criticalInterface != sensorMap.end()))
905 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000906 enabled = static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700907 IPMISensorEventEnableByte2::sensorScanningEnable);
908 if (warningInterface != sensorMap.end())
909 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700910 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700911
912 auto warningHigh = warningMap.find("WarningHigh");
913 auto warningLow = warningMap.find("WarningLow");
914 if (warningHigh != warningMap.end())
915 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000916 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700917 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000918 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700919 IPMISensorEventEnableThresholds::upperNonCriticalGoingLow);
920 }
921 if (warningLow != warningMap.end())
922 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000923 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700924 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000925 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700926 IPMISensorEventEnableThresholds::lowerNonCriticalGoingHigh);
927 }
928 }
929 if (criticalInterface != sensorMap.end())
930 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700931 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700932
933 auto criticalHigh = criticalMap.find("CriticalHigh");
934 auto criticalLow = criticalMap.find("CriticalLow");
935
936 if (criticalHigh != criticalMap.end())
937 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000938 assertionEnabledMsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700939 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000940 deassertionEnabledMsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700941 IPMISensorEventEnableThresholds::upperCriticalGoingLow);
942 }
943 if (criticalLow != criticalMap.end())
944 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000945 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700946 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000947 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700948 IPMISensorEventEnableThresholds::lowerCriticalGoingHigh);
949 }
950 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700951 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000952
953 return ipmi::responseSuccess(enabled, assertionEnabledLsb,
954 assertionEnabledMsb, deassertionEnabledLsb,
955 deassertionEnabledMsb);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700956}
957
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000958/** @brief implements the get Sensor event status command
959 * @param sensorNumber - sensor number, FFh = reserved
960 *
961 * @returns IPMI completion code plus response data
962 * - sensorEventStatus - Sensor Event messages state
963 * - assertions - Assertion event messages
964 * - deassertions - Deassertion event messages
965 */
966ipmi::RspType<uint8_t, // sensorEventStatus
967 std::bitset<16>, // assertions
968 std::bitset<16> // deassertion
969 >
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700970 ipmiSenGetSensorEventStatus(ipmi::Context::ptr ctx, uint8_t sensorNum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700971{
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700972 if (sensorNum == reservedSensorNumber)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700973 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000974 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700975 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700976
977 std::string connection;
978 std::string path;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700979 auto status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700980 if (status)
981 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000982 phosphor::logging::log<phosphor::logging::level::ERR>(
983 "ipmiSenGetSensorEventStatus: Sensor connection Error",
984 phosphor::logging::entry("SENSOR=%d", sensorNum));
985 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700986 }
987
988 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700989 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700990 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000991 phosphor::logging::log<phosphor::logging::level::ERR>(
992 "ipmiSenGetSensorEventStatus: Sensor Mapping Error",
993 phosphor::logging::entry("SENSOR=%s", path.c_str()));
994 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700995 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700996 auto warningInterface =
997 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
998 auto criticalInterface =
999 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
1000
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001001 uint8_t sensorEventStatus =
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001002 static_cast<uint8_t>(IPMISensorEventEnableByte2::sensorScanningEnable);
1003
James Feist392786a2019-03-19 13:36:10 -07001004 std::optional<bool> criticalDeassertHigh =
1005 thresholdDeassertMap[path]["CriticalAlarmHigh"];
1006 std::optional<bool> criticalDeassertLow =
1007 thresholdDeassertMap[path]["CriticalAlarmLow"];
1008 std::optional<bool> warningDeassertHigh =
1009 thresholdDeassertMap[path]["WarningAlarmHigh"];
1010 std::optional<bool> warningDeassertLow =
1011 thresholdDeassertMap[path]["WarningAlarmLow"];
1012
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001013 std::bitset<16> assertions = 0;
1014 std::bitset<16> deassertions = 0;
1015
James Feist392786a2019-03-19 13:36:10 -07001016 if (criticalDeassertHigh && !*criticalDeassertHigh)
1017 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001018 deassertions.set(static_cast<size_t>(
1019 IPMIGetSensorEventEnableThresholds::upperCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001020 }
1021 if (criticalDeassertLow && !*criticalDeassertLow)
1022 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001023 deassertions.set(static_cast<size_t>(
1024 IPMIGetSensorEventEnableThresholds::upperCriticalGoingLow));
James Feist392786a2019-03-19 13:36:10 -07001025 }
1026 if (warningDeassertHigh && !*warningDeassertHigh)
1027 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001028 deassertions.set(static_cast<size_t>(
1029 IPMIGetSensorEventEnableThresholds::upperNonCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001030 }
1031 if (warningDeassertLow && !*warningDeassertLow)
1032 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001033 deassertions.set(static_cast<size_t>(
1034 IPMIGetSensorEventEnableThresholds::lowerNonCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001035 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001036 if ((warningInterface != sensorMap.end()) ||
1037 (criticalInterface != sensorMap.end()))
1038 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001039 sensorEventStatus = static_cast<size_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001040 IPMISensorEventEnableByte2::eventMessagesEnable);
1041 if (warningInterface != sensorMap.end())
1042 {
James Feistfcd2d3a2020-05-28 10:38:15 -07001043 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001044
1045 auto warningHigh = warningMap.find("WarningAlarmHigh");
1046 auto warningLow = warningMap.find("WarningAlarmLow");
1047 auto warningHighAlarm = false;
1048 auto warningLowAlarm = false;
1049
1050 if (warningHigh != warningMap.end())
1051 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001052 warningHighAlarm = std::get<bool>(warningHigh->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001053 }
1054 if (warningLow != warningMap.end())
1055 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001056 warningLowAlarm = std::get<bool>(warningLow->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001057 }
1058 if (warningHighAlarm)
1059 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001060 assertions.set(
1061 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1062 upperNonCriticalGoingHigh));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001063 }
1064 if (warningLowAlarm)
1065 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001066 assertions.set(
1067 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1068 lowerNonCriticalGoingLow));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001069 }
1070 }
1071 if (criticalInterface != sensorMap.end())
1072 {
James Feistfcd2d3a2020-05-28 10:38:15 -07001073 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001074
1075 auto criticalHigh = criticalMap.find("CriticalAlarmHigh");
1076 auto criticalLow = criticalMap.find("CriticalAlarmLow");
1077 auto criticalHighAlarm = false;
1078 auto criticalLowAlarm = false;
1079
1080 if (criticalHigh != criticalMap.end())
1081 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001082 criticalHighAlarm = std::get<bool>(criticalHigh->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001083 }
1084 if (criticalLow != criticalMap.end())
1085 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001086 criticalLowAlarm = std::get<bool>(criticalLow->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001087 }
1088 if (criticalHighAlarm)
1089 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001090 assertions.set(
1091 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1092 upperCriticalGoingHigh));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001093 }
1094 if (criticalLowAlarm)
1095 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001096 assertions.set(static_cast<size_t>(
1097 IPMIGetSensorEventEnableThresholds::lowerCriticalGoingLow));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001098 }
1099 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001100 }
1101
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001102 return ipmi::responseSuccess(sensorEventStatus, assertions, deassertions);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001103}
1104
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001105static int getSensorDataRecord(ipmi::Context::ptr ctx,
1106 std::vector<uint8_t>& recordData,
1107 uint16_t recordID)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001108{
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001109 size_t fruCount = 0;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001110 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
1111 if (ret != ipmi::ccSuccess)
1112 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001113 phosphor::logging::log<phosphor::logging::level::ERR>(
1114 "getSensorDataRecord: getFruSdrCount error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001115 return GENERAL_ERROR;
1116 }
1117
1118 size_t lastRecord = sensorTree.size() + fruCount +
1119 ipmi::storage::type12Count +
1120 ipmi::storage::nmDiscoverySDRCount - 1;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001121 if (recordID == lastRecordIndex)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001122 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001123 recordID = lastRecord;
1124 }
1125 if (recordID > lastRecord)
1126 {
1127 phosphor::logging::log<phosphor::logging::level::ERR>(
1128 "getSensorDataRecord: recordID > lastRecord error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001129 return GENERAL_ERROR;
1130 }
1131
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001132 if (recordID >= sensorTree.size())
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001133 {
1134 size_t fruIndex = recordID - sensorTree.size();
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001135 size_t type12End = fruCount + ipmi::storage::type12Count;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001136
1137 if (fruIndex >= type12End)
1138 {
1139 // NM discovery SDR
1140 size_t nmDiscoveryIndex = fruIndex - type12End;
1141 if (nmDiscoveryIndex >= ipmi::storage::nmDiscoverySDRCount)
1142 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001143 phosphor::logging::log<phosphor::logging::level::ERR>(
1144 "getSensorDataRecord: NM DiscoveryIndex error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001145 return GENERAL_ERROR;
1146 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001147 recordData =
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001148 ipmi::storage::getNMDiscoverySDR(nmDiscoveryIndex, recordID);
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001149 }
1150 else if (fruIndex >= fruCount)
1151 {
1152 // handle type 12 hardcoded records
1153 size_t type12Index = fruIndex - fruCount;
1154 if (type12Index >= ipmi::storage::type12Count)
1155 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001156 phosphor::logging::log<phosphor::logging::level::ERR>(
1157 "getSensorDataRecord: type12Index error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001158 return GENERAL_ERROR;
1159 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001160 recordData = ipmi::storage::getType12SDRs(type12Index, recordID);
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001161 }
1162 else
1163 {
1164 // handle fru records
1165 get_sdr::SensorDataFruRecord data;
1166 ret = ipmi::storage::getFruSdrs(ctx, fruIndex, data);
1167 if (ret != IPMI_CC_OK)
1168 {
1169 return GENERAL_ERROR;
1170 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001171 data.header.record_id_msb = recordID >> 8;
1172 data.header.record_id_lsb = recordID & 0xFF;
1173 recordData.insert(recordData.end(), (uint8_t*)&data,
1174 ((uint8_t*)&data) + sizeof(data));
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001175 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001176
1177 return 0;
1178 }
1179
1180 std::string connection;
1181 std::string path;
1182 auto status = getSensorConnection(ctx, recordID, connection, path);
1183 if (status)
1184 {
1185 phosphor::logging::log<phosphor::logging::level::ERR>(
1186 "getSensorDataRecord: getSensorConnection error");
1187 return GENERAL_ERROR;
1188 }
1189 SensorMap sensorMap;
1190 if (!getSensorMap(ctx->yield, connection, path, sensorMap,
1191 sensorMapUpdatePeriod))
1192 {
1193 phosphor::logging::log<phosphor::logging::level::ERR>(
1194 "getSensorDataRecord: getSensorMap error");
1195 return GENERAL_ERROR;
1196 }
1197 uint16_t sensorNum = getSensorNumberFromPath(path);
1198 if (sensorNum == invalidSensorNumber)
1199 {
1200 phosphor::logging::log<phosphor::logging::level::ERR>(
1201 "getSensorDataRecord: invalidSensorNumber");
1202 return GENERAL_ERROR;
1203 }
1204 uint8_t sensornumber = static_cast<uint8_t>(sensorNum);
1205 uint8_t lun = static_cast<uint8_t>(sensorNum >> 8);
1206
1207 get_sdr::SensorDataFullRecord record = {0};
1208
1209 get_sdr::header::set_record_id(
1210 recordID, reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&record));
1211
1212 record.header.sdr_version = ipmiSdrVersion;
1213 record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD;
1214 record.header.record_length = sizeof(get_sdr::SensorDataFullRecord) -
1215 sizeof(get_sdr::SensorDataRecordHeader);
1216 record.key.owner_id = 0x20;
1217 record.key.owner_lun = lun;
1218 record.key.sensor_number = sensornumber;
1219
1220 record.body.sensor_capabilities = 0x68; // auto rearm - todo hysteresis
1221 record.body.sensor_type = getSensorTypeFromPath(path);
1222 std::string type = getSensorTypeStringFromPath(path);
1223 auto typeCstr = type.c_str();
1224 auto findUnits = sensorUnits.find(typeCstr);
1225 if (findUnits != sensorUnits.end())
1226 {
1227 record.body.sensor_units_2_base =
1228 static_cast<uint8_t>(findUnits->second);
1229 } // else default 0x0 unspecified
1230
1231 record.body.event_reading_type = getSensorEventTypeFromPath(path);
1232
1233 auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
1234 if (sensorObject == sensorMap.end())
1235 {
1236 phosphor::logging::log<phosphor::logging::level::ERR>(
1237 "getSensorDataRecord: sensorObject error");
1238 return GENERAL_ERROR;
1239 }
1240
1241 uint8_t entityId = 0;
1242 uint8_t entityInstance = 0x01;
1243
1244 // follow the association chain to get the parent board's entityid and
1245 // entityInstance
1246 updateIpmiFromAssociation(path, sensorMap, entityId, entityInstance);
1247
1248 record.body.entity_id = entityId;
1249 record.body.entity_instance = entityInstance;
1250
1251 auto maxObject = sensorObject->second.find("MaxValue");
1252 auto minObject = sensorObject->second.find("MinValue");
1253
1254 // If min and/or max are left unpopulated,
1255 // then default to what a signed byte would be, namely (-128,127) range.
1256 auto max = static_cast<double>(std::numeric_limits<int8_t>::max());
1257 auto min = static_cast<double>(std::numeric_limits<int8_t>::lowest());
1258 if (maxObject != sensorObject->second.end())
1259 {
1260 max = std::visit(VariantToDoubleVisitor(), maxObject->second);
1261 }
1262
1263 if (minObject != sensorObject->second.end())
1264 {
1265 min = std::visit(VariantToDoubleVisitor(), minObject->second);
1266 }
1267
1268 int16_t mValue = 0;
1269 int8_t rExp = 0;
1270 int16_t bValue = 0;
1271 int8_t bExp = 0;
1272 bool bSigned = false;
1273
1274 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
1275 {
1276 phosphor::logging::log<phosphor::logging::level::ERR>(
1277 "getSensorDataRecord: getSensorAttributes error");
1278 return GENERAL_ERROR;
1279 }
1280
1281 // The record.body is a struct SensorDataFullRecordBody
1282 // from sensorhandler.hpp in phosphor-ipmi-host.
1283 // The meaning of these bits appears to come from
1284 // table 43.1 of the IPMI spec.
1285 // The above 5 sensor attributes are stuffed in as follows:
1286 // Byte 21 = AA000000 = analog interpretation, 10 signed, 00 unsigned
1287 // Byte 22-24 are for other purposes
1288 // Byte 25 = MMMMMMMM = LSB of M
1289 // Byte 26 = MMTTTTTT = MSB of M (signed), and Tolerance
1290 // Byte 27 = BBBBBBBB = LSB of B
1291 // Byte 28 = BBAAAAAA = MSB of B (signed), and LSB of Accuracy
1292 // Byte 29 = AAAAEE00 = MSB of Accuracy, exponent of Accuracy
1293 // Byte 30 = RRRRBBBB = rExp (signed), bExp (signed)
1294
1295 // apply M, B, and exponents, M and B are 10 bit values, exponents are 4
1296 record.body.m_lsb = mValue & 0xFF;
1297
1298 uint8_t mBitSign = (mValue < 0) ? 1 : 0;
1299 uint8_t mBitNine = (mValue & 0x0100) >> 8;
1300
1301 // move the smallest bit of the MSB into place (bit 9)
1302 // the MSbs are bits 7:8 in m_msb_and_tolerance
1303 record.body.m_msb_and_tolerance = (mBitSign << 7) | (mBitNine << 6);
1304
1305 record.body.b_lsb = bValue & 0xFF;
1306
1307 uint8_t bBitSign = (bValue < 0) ? 1 : 0;
1308 uint8_t bBitNine = (bValue & 0x0100) >> 8;
1309
1310 // move the smallest bit of the MSB into place (bit 9)
1311 // the MSbs are bits 7:8 in b_msb_and_accuracy_lsb
1312 record.body.b_msb_and_accuracy_lsb = (bBitSign << 7) | (bBitNine << 6);
1313
1314 uint8_t rExpSign = (rExp < 0) ? 1 : 0;
1315 uint8_t rExpBits = rExp & 0x07;
1316
1317 uint8_t bExpSign = (bExp < 0) ? 1 : 0;
1318 uint8_t bExpBits = bExp & 0x07;
1319
1320 // move rExp and bExp into place
1321 record.body.r_b_exponents =
1322 (rExpSign << 7) | (rExpBits << 4) | (bExpSign << 3) | bExpBits;
1323
1324 // Set the analog reading byte interpretation accordingly
1325 record.body.sensor_units_1 = (bSigned ? 1 : 0) << 7;
1326
1327 // TODO(): Perhaps care about Tolerance, Accuracy, and so on
1328 // These seem redundant, but derivable from the above 5 attributes
1329 // Original comment said "todo fill out rest of units"
1330
1331 // populate sensor name from path
1332 std::string name;
1333 size_t nameStart = path.rfind("/");
1334 if (nameStart != std::string::npos)
1335 {
1336 name = path.substr(nameStart + 1, std::string::npos - nameStart);
1337 }
1338
1339 std::replace(name.begin(), name.end(), '_', ' ');
1340 if (name.size() > FULL_RECORD_ID_STR_MAX_LENGTH)
1341 {
1342 // try to not truncate by replacing common words
1343 constexpr std::array<std::pair<const char*, const char*>, 2>
1344 replaceWords = {std::make_pair("Output", "Out"),
1345 std::make_pair("Input", "In")};
1346 for (const auto& [find, replace] : replaceWords)
1347 {
1348 boost::replace_all(name, find, replace);
1349 }
1350
1351 name.resize(FULL_RECORD_ID_STR_MAX_LENGTH);
1352 }
1353 record.body.id_string_info = name.size();
1354 std::strncpy(record.body.id_string, name.c_str(),
1355 sizeof(record.body.id_string));
1356
Josh Lehan06aa21a2020-10-28 21:59:06 -07001357 // Remember the sensor name, as determined for this sensor number
1358 details::sdrStatsTable.updateName(sensornumber, name);
1359
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001360 IPMIThresholds thresholdData;
1361 try
1362 {
1363 thresholdData = getIPMIThresholds(sensorMap);
1364 }
1365 catch (std::exception&)
1366 {
1367 phosphor::logging::log<phosphor::logging::level::ERR>(
1368 "getSensorDataRecord: getIPMIThresholds error");
1369 return GENERAL_ERROR;
1370 }
1371
1372 if (thresholdData.criticalHigh)
1373 {
1374 record.body.upper_critical_threshold = *thresholdData.criticalHigh;
1375 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1376 IPMISensorEventEnableThresholds::criticalThreshold);
1377 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1378 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
1379 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1380 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
1381 record.body.discrete_reading_setting_mask[0] |=
1382 static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
1383 }
1384 if (thresholdData.warningHigh)
1385 {
1386 record.body.upper_noncritical_threshold = *thresholdData.warningHigh;
1387 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1388 IPMISensorEventEnableThresholds::nonCriticalThreshold);
1389 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1390 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
1391 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1392 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
1393 record.body.discrete_reading_setting_mask[0] |=
1394 static_cast<uint8_t>(IPMISensorReadingByte3::upperNonCritical);
1395 }
1396 if (thresholdData.criticalLow)
1397 {
1398 record.body.lower_critical_threshold = *thresholdData.criticalLow;
1399 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1400 IPMISensorEventEnableThresholds::criticalThreshold);
1401 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1402 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
1403 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1404 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
1405 record.body.discrete_reading_setting_mask[0] |=
1406 static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
1407 }
1408 if (thresholdData.warningLow)
1409 {
1410 record.body.lower_noncritical_threshold = *thresholdData.warningLow;
1411 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1412 IPMISensorEventEnableThresholds::nonCriticalThreshold);
1413 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1414 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
1415 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1416 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
1417 record.body.discrete_reading_setting_mask[0] |=
1418 static_cast<uint8_t>(IPMISensorReadingByte3::lowerNonCritical);
1419 }
1420
1421 // everything that is readable is setable
1422 record.body.discrete_reading_setting_mask[1] =
1423 record.body.discrete_reading_setting_mask[0];
1424 recordData.insert(recordData.end(), (uint8_t*)&record,
1425 ((uint8_t*)&record) + sizeof(record));
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001426 return 0;
1427}
1428
1429/** @brief implements the get SDR Info command
1430 * @param count - Operation
1431 *
1432 * @returns IPMI completion code plus response data
1433 * - sdrCount - sensor/SDR count
1434 * - lunsAndDynamicPopulation - static/Dynamic sensor population flag
1435 */
1436static ipmi::RspType<uint8_t, // respcount
1437 uint8_t, // dynamic population flags
1438 uint32_t // last time a sensor was added
1439 >
1440 ipmiSensorGetDeviceSdrInfo(ipmi::Context::ptr ctx,
1441 std::optional<uint8_t> count)
1442{
1443 uint8_t sdrCount = 0;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001444 uint16_t recordID = 0;
1445 std::vector<uint8_t> record;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001446 // Sensors are dynamically allocated, and there is at least one LUN
1447 uint8_t lunsAndDynamicPopulation = 0x80;
1448 constexpr uint8_t getSdrCount = 0x01;
1449 constexpr uint8_t getSensorCount = 0x00;
1450
1451 if (!getSensorSubtree(sensorTree) || sensorTree.empty())
1452 {
1453 return ipmi::responseResponseError();
1454 }
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001455 uint16_t numSensors = sensorTree.size();
1456 if (count.value_or(0) == getSdrCount)
1457 {
1458 // Count the number of Type 1 SDR entries assigned to the LUN
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001459 while (!getSensorDataRecord(ctx, record, recordID++))
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001460 {
1461 get_sdr::SensorDataRecordHeader* hdr =
1462 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001463 record.data());
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001464 if (hdr->record_type == get_sdr::SENSOR_DATA_FULL_RECORD)
1465 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001466 get_sdr::SensorDataFullRecord* recordData =
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001467 reinterpret_cast<get_sdr::SensorDataFullRecord*>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001468 record.data());
1469 if (ctx->lun == recordData->key.owner_lun)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001470 {
1471 sdrCount++;
1472 }
1473 }
1474 }
1475 }
1476 else if (count.value_or(0) == getSensorCount)
1477 {
1478 // Return the number of sensors attached to the LUN
1479 if ((ctx->lun == 0) && (numSensors > 0))
1480 {
1481 sdrCount =
1482 (numSensors > maxSensorsPerLUN) ? maxSensorsPerLUN : numSensors;
1483 }
1484 else if ((ctx->lun == 1) && (numSensors > maxSensorsPerLUN))
1485 {
1486 sdrCount = (numSensors > (2 * maxSensorsPerLUN))
1487 ? maxSensorsPerLUN
1488 : (numSensors - maxSensorsPerLUN) & maxSensorsPerLUN;
1489 }
1490 else if (ctx->lun == 3)
1491 {
1492 if (numSensors <= maxIPMISensors)
1493 {
1494 sdrCount =
1495 (numSensors - (2 * maxSensorsPerLUN)) & maxSensorsPerLUN;
1496 }
1497 else
1498 {
1499 // error
1500 throw std::out_of_range(
1501 "Maximum number of IPMI sensors exceeded.");
1502 }
1503 }
1504 }
1505 else
1506 {
1507 return ipmi::responseInvalidFieldRequest();
1508 }
1509
1510 // Get Sensor count. This returns the number of sensors
1511 if (numSensors > 0)
1512 {
1513 lunsAndDynamicPopulation |= 1;
1514 }
1515 if (numSensors > maxSensorsPerLUN)
1516 {
1517 lunsAndDynamicPopulation |= 2;
1518 }
1519 if (numSensors >= (maxSensorsPerLUN * 2))
1520 {
1521 lunsAndDynamicPopulation |= 8;
1522 }
1523 if (numSensors > maxIPMISensors)
1524 {
1525 // error
1526 throw std::out_of_range("Maximum number of IPMI sensors exceeded.");
1527 }
1528
1529 return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation,
1530 sdrLastAdd);
1531}
1532
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001533/* end sensor commands */
1534
1535/* storage commands */
1536
James Feist74c50c62019-08-14 14:18:41 -07001537ipmi::RspType<uint8_t, // sdr version
1538 uint16_t, // record count
1539 uint16_t, // free space
1540 uint32_t, // most recent addition
1541 uint32_t, // most recent erase
1542 uint8_t // operationSupport
1543 >
James Feist25690252019-12-23 12:25:49 -08001544 ipmiStorageGetSDRRepositoryInfo(ipmi::Context::ptr ctx)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001545{
James Feist74c50c62019-08-14 14:18:41 -07001546 constexpr const uint16_t unspecifiedFreeSpace = 0xFFFF;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001547 if (!getSensorSubtree(sensorTree) && sensorTree.empty())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001548 {
James Feist74c50c62019-08-14 14:18:41 -07001549 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001550 }
1551
James Feist74c50c62019-08-14 14:18:41 -07001552 size_t fruCount = 0;
James Feist25690252019-12-23 12:25:49 -08001553 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
James Feist74c50c62019-08-14 14:18:41 -07001554 if (ret != ipmi::ccSuccess)
1555 {
1556 return ipmi::response(ret);
1557 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001558
James Feist74c50c62019-08-14 14:18:41 -07001559 uint16_t recordCount =
1560 sensorTree.size() + fruCount + ipmi::storage::type12Count;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001561
James Feist74c50c62019-08-14 14:18:41 -07001562 uint8_t operationSupport = static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001563 SdrRepositoryInfoOps::overflow); // write not supported
James Feist74c50c62019-08-14 14:18:41 -07001564
1565 operationSupport |=
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001566 static_cast<uint8_t>(SdrRepositoryInfoOps::allocCommandSupported);
James Feist74c50c62019-08-14 14:18:41 -07001567 operationSupport |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001568 SdrRepositoryInfoOps::reserveSDRRepositoryCommandSupported);
James Feist74c50c62019-08-14 14:18:41 -07001569 return ipmi::responseSuccess(ipmiSdrVersion, recordCount,
1570 unspecifiedFreeSpace, sdrLastAdd,
1571 sdrLastRemove, operationSupport);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001572}
1573
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001574/** @brief implements the get SDR allocation info command
1575 *
1576 * @returns IPMI completion code plus response data
1577 * - allocUnits - Number of possible allocation units
1578 * - allocUnitSize - Allocation unit size in bytes.
1579 * - allocUnitFree - Number of free allocation units
1580 * - allocUnitLargestFree - Largest free block in allocation units
1581 * - maxRecordSize - Maximum record size in allocation units.
1582 */
1583ipmi::RspType<uint16_t, // allocUnits
1584 uint16_t, // allocUnitSize
1585 uint16_t, // allocUnitFree
1586 uint16_t, // allocUnitLargestFree
1587 uint8_t // maxRecordSize
1588 >
1589 ipmiStorageGetSDRAllocationInfo()
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001590{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001591 // 0000h unspecified number of alloc units
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001592 constexpr uint16_t allocUnits = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001593
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001594 constexpr uint16_t allocUnitFree = 0;
1595 constexpr uint16_t allocUnitLargestFree = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001596 // only allow one block at a time
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001597 constexpr uint8_t maxRecordSize = 1;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001598
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001599 return ipmi::responseSuccess(allocUnits, maxSDRTotalSize, allocUnitFree,
1600 allocUnitLargestFree, maxRecordSize);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001601}
1602
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001603/** @brief implements the reserve SDR command
1604 * @returns IPMI completion code plus response data
1605 * - sdrReservationID
1606 */
1607ipmi::RspType<uint16_t> ipmiStorageReserveSDR()
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001608{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001609 sdrReservationID++;
James Feista80cb902019-02-14 13:05:25 -08001610 if (sdrReservationID == 0)
1611 {
1612 sdrReservationID++;
1613 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001614
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001615 return ipmi::responseSuccess(sdrReservationID);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001616}
1617
James Feistb49a98a2019-04-16 13:48:09 -07001618ipmi::RspType<uint16_t, // next record ID
1619 std::vector<uint8_t> // payload
1620 >
James Feist25690252019-12-23 12:25:49 -08001621 ipmiStorageGetSDR(ipmi::Context::ptr ctx, uint16_t reservationID,
1622 uint16_t recordID, uint8_t offset, uint8_t bytesToRead)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001623{
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001624 size_t fruCount = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001625 // reservation required for partial reads with non zero offset into
1626 // record
James Feistb49a98a2019-04-16 13:48:09 -07001627 if ((sdrReservationID == 0 || reservationID != sdrReservationID) && offset)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001628 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001629 phosphor::logging::log<phosphor::logging::level::ERR>(
1630 "ipmiStorageGetSDR: responseInvalidReservationId");
James Feistb49a98a2019-04-16 13:48:09 -07001631 return ipmi::responseInvalidReservationId();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001632 }
James Feist25690252019-12-23 12:25:49 -08001633 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
James Feist74c50c62019-08-14 14:18:41 -07001634 if (ret != ipmi::ccSuccess)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001635 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001636 phosphor::logging::log<phosphor::logging::level::ERR>(
1637 "ipmiStorageGetSDR: getFruSdrCount error");
James Feistb49a98a2019-04-16 13:48:09 -07001638 return ipmi::response(ret);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001639 }
1640
Yong Lifee5e4c2020-01-17 19:36:29 +08001641 size_t lastRecord = sensorTree.size() + fruCount +
1642 ipmi::storage::type12Count +
1643 ipmi::storage::nmDiscoverySDRCount - 1;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001644 uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF;
1645
1646 if (!getSensorSubtree(sensorTree) && sensorTree.empty())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001647 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001648 phosphor::logging::log<phosphor::logging::level::ERR>(
1649 "ipmiStorageGetSDR: getSensorSubtree error");
1650 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001651 }
1652
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001653 std::vector<uint8_t> record;
1654 if (getSensorDataRecord(ctx, record, recordID))
1655 {
1656 phosphor::logging::log<phosphor::logging::level::ERR>(
1657 "ipmiStorageGetSDR: fail to get SDR");
1658 return ipmi::responseInvalidFieldRequest();
1659 }
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001660 get_sdr::SensorDataRecordHeader* hdr =
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001661 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(record.data());
Kuiying Wangb9109872021-01-15 15:54:59 +08001662 if (!hdr)
1663 {
1664 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001665 "ipmiStorageGetSDR: record header is null");
1666 return ipmi::responseSuccess(nextRecordId, record);
Kuiying Wangb9109872021-01-15 15:54:59 +08001667 }
1668
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001669 size_t sdrLength =
1670 sizeof(get_sdr::SensorDataRecordHeader) + hdr->record_length;
1671 if (sdrLength < (offset + bytesToRead))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001672 {
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001673 bytesToRead = sdrLength - offset;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001674 }
1675
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001676 uint8_t* respStart = reinterpret_cast<uint8_t*>(hdr) + offset;
Kuiying Wangb9109872021-01-15 15:54:59 +08001677 if (!respStart)
1678 {
1679 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001680 "ipmiStorageGetSDR: record is null");
1681 return ipmi::responseSuccess(nextRecordId, record);
Kuiying Wangb9109872021-01-15 15:54:59 +08001682 }
James Feistb49a98a2019-04-16 13:48:09 -07001683 std::vector<uint8_t> recordData(respStart, respStart + bytesToRead);
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001684
James Feistb49a98a2019-04-16 13:48:09 -07001685 return ipmi::responseSuccess(nextRecordId, recordData);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001686}
1687/* end storage commands */
1688
1689void registerSensorFunctions()
1690{
Jason M. Billsae6bdb12019-04-02 12:00:04 -07001691 // <Platform Event>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001692 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1693 ipmi::sensor_event::cmdPlatformEvent,
1694 ipmi::Privilege::Operator, ipmiSenPlatformEvent);
Jason M. Billsae6bdb12019-04-02 12:00:04 -07001695
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001696 // <Get Sensor Reading>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001697 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1698 ipmi::sensor_event::cmdGetSensorReading,
1699 ipmi::Privilege::User, ipmiSenGetSensorReading);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001700
1701 // <Get Sensor Threshold>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001702 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1703 ipmi::sensor_event::cmdGetSensorThreshold,
1704 ipmi::Privilege::User, ipmiSenGetSensorThresholds);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001705
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +00001706 // <Set Sensor Threshold>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001707 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1708 ipmi::sensor_event::cmdSetSensorThreshold,
1709 ipmi::Privilege::Operator,
1710 ipmiSenSetSensorThresholds);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001711
1712 // <Get Sensor Event Enable>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001713 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1714 ipmi::sensor_event::cmdGetSensorEventEnable,
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +00001715 ipmi::Privilege::User, ipmiSenGetSensorEventEnable);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001716
1717 // <Get Sensor Event Status>
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001718 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1719 ipmi::sensor_event::cmdGetSensorEventStatus,
1720 ipmi::Privilege::User, ipmiSenGetSensorEventStatus);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001721
1722 // register all storage commands for both Sensor and Storage command
1723 // versions
1724
1725 // <Get SDR Repository Info>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001726 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1727 ipmi::storage::cmdGetSdrRepositoryInfo,
1728 ipmi::Privilege::User,
1729 ipmiStorageGetSDRRepositoryInfo);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001730
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001731 // <Get Device SDR Info>
1732 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1733 ipmi::sensor_event::cmdGetDeviceSdrInfo,
1734 ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo);
1735
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001736 // <Get SDR Allocation Info>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001737 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1738 ipmi::storage::cmdGetSdrRepositoryAllocInfo,
1739 ipmi::Privilege::User,
1740 ipmiStorageGetSDRAllocationInfo);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001741
1742 // <Reserve SDR Repo>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001743 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1744 ipmi::sensor_event::cmdReserveDeviceSdrRepository,
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001745 ipmi::Privilege::User, ipmiStorageReserveSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001746
Vernon Mauery98bbf692019-09-16 11:14:59 -07001747 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1748 ipmi::storage::cmdReserveSdrRepository,
1749 ipmi::Privilege::User, ipmiStorageReserveSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001750
1751 // <Get Sdr>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001752 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1753 ipmi::sensor_event::cmdGetDeviceSdr,
1754 ipmi::Privilege::User, ipmiStorageGetSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001755
Vernon Mauery98bbf692019-09-16 11:14:59 -07001756 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1757 ipmi::storage::cmdGetSdr, ipmi::Privilege::User,
1758 ipmiStorageGetSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001759}
1760} // namespace ipmi