blob: bcc922094b0d9fcc7c35316784755d201c8ec1f2 [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
James Feist0cd014a2019-04-08 15:04:33 -0700469 uint8_t thresholds = 0;
470
471 auto warningObject =
472 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
473 if (warningObject != sensorMap.end())
474 {
475 auto alarmHigh = warningObject->second.find("WarningAlarmHigh");
476 auto alarmLow = warningObject->second.find("WarningAlarmLow");
477 if (alarmHigh != warningObject->second.end())
478 {
479 if (std::get<bool>(alarmHigh->second))
480 {
481 thresholds |= static_cast<uint8_t>(
482 IPMISensorReadingByte3::upperNonCritical);
483 }
484 }
485 if (alarmLow != warningObject->second.end())
486 {
487 if (std::get<bool>(alarmLow->second))
488 {
489 thresholds |= static_cast<uint8_t>(
490 IPMISensorReadingByte3::lowerNonCritical);
491 }
492 }
493 }
494
495 auto criticalObject =
496 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
497 if (criticalObject != sensorMap.end())
498 {
499 auto alarmHigh = criticalObject->second.find("CriticalAlarmHigh");
500 auto alarmLow = criticalObject->second.find("CriticalAlarmLow");
501 if (alarmHigh != criticalObject->second.end())
502 {
503 if (std::get<bool>(alarmHigh->second))
504 {
505 thresholds |=
506 static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
507 }
508 }
509 if (alarmLow != criticalObject->second.end())
510 {
511 if (std::get<bool>(alarmLow->second))
512 {
513 thresholds |=
514 static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
515 }
516 }
517 }
518
519 // no discrete as of today so optional byte is never returned
520 return ipmi::responseSuccess(value, operation, thresholds, std::nullopt);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700521}
522
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000523/** @brief implements the Set Sensor threshold command
524 * @param sensorNumber - sensor number
525 * @param lowerNonCriticalThreshMask
526 * @param lowerCriticalThreshMask
527 * @param lowerNonRecovThreshMask
528 * @param upperNonCriticalThreshMask
529 * @param upperCriticalThreshMask
530 * @param upperNonRecovThreshMask
531 * @param reserved
532 * @param lowerNonCritical - lower non-critical threshold
533 * @param lowerCritical - Lower critical threshold
534 * @param lowerNonRecoverable - Lower non recovarable threshold
535 * @param upperNonCritical - Upper non-critical threshold
536 * @param upperCritical - Upper critical
537 * @param upperNonRecoverable - Upper Non-recoverable
538 *
539 * @returns IPMI completion code
540 */
541ipmi::RspType<> ipmiSenSetSensorThresholds(
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700542 ipmi::Context::ptr ctx, uint8_t sensorNum, bool lowerNonCriticalThreshMask,
543 bool lowerCriticalThreshMask, bool lowerNonRecovThreshMask,
544 bool upperNonCriticalThreshMask, bool upperCriticalThreshMask,
545 bool upperNonRecovThreshMask, uint2_t reserved, uint8_t lowerNonCritical,
546 uint8_t lowerCritical, uint8_t lowerNonRecoverable,
547 uint8_t upperNonCritical, uint8_t upperCritical,
548 uint8_t upperNonRecoverable)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700549{
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000550 constexpr uint8_t thresholdMask = 0xFF;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700551
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000552 if (reserved)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700553 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000554 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700555 }
556
557 // lower nc and upper nc not suppported on any sensor
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000558 if (lowerNonRecovThreshMask || upperNonRecovThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700559 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000560 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700561 }
562
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000563 // if none of the threshold mask are set, nothing to do
564 if (!(lowerNonCriticalThreshMask | lowerCriticalThreshMask |
565 lowerNonRecovThreshMask | upperNonCriticalThreshMask |
566 upperCriticalThreshMask | upperNonRecovThreshMask))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700567 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000568 return ipmi::responseSuccess();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700569 }
570
571 std::string connection;
572 std::string path;
573
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700574 ipmi::Cc status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700575 if (status)
576 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000577 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700578 }
579 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700580 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700581 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000582 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700583 }
584
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700585 double max = 0;
586 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700587 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700588
589 int16_t mValue = 0;
590 int16_t bValue = 0;
591 int8_t rExp = 0;
592 int8_t bExp = 0;
593 bool bSigned = false;
594
595 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
596 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000597 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700598 }
599
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700600 // store a vector of property name, value to set, and interface
601 std::vector<std::tuple<std::string, uint8_t, std::string>> thresholdsToSet;
602
603 // define the indexes of the tuple
604 constexpr uint8_t propertyName = 0;
605 constexpr uint8_t thresholdValue = 1;
606 constexpr uint8_t interface = 2;
607 // verifiy all needed fields are present
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000608 if (lowerCriticalThreshMask || upperCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700609 {
610 auto findThreshold =
611 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
612 if (findThreshold == sensorMap.end())
613 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000614 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700615 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000616 if (lowerCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700617 {
618 auto findLower = findThreshold->second.find("CriticalLow");
619 if (findLower == findThreshold->second.end())
620 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000621 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700622 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000623 thresholdsToSet.emplace_back("CriticalLow", lowerCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700624 findThreshold->first);
625 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000626 if (upperCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700627 {
628 auto findUpper = findThreshold->second.find("CriticalHigh");
629 if (findUpper == findThreshold->second.end())
630 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000631 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700632 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000633 thresholdsToSet.emplace_back("CriticalHigh", upperCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700634 findThreshold->first);
635 }
636 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000637 if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700638 {
639 auto findThreshold =
640 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
641 if (findThreshold == sensorMap.end())
642 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000643 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700644 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000645 if (lowerNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700646 {
647 auto findLower = findThreshold->second.find("WarningLow");
648 if (findLower == findThreshold->second.end())
649 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000650 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700651 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000652 thresholdsToSet.emplace_back("WarningLow", lowerNonCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700653 findThreshold->first);
654 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000655 if (upperNonCriticalThreshMask)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700656 {
657 auto findUpper = findThreshold->second.find("WarningHigh");
658 if (findUpper == findThreshold->second.end())
659 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000660 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700661 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000662 thresholdsToSet.emplace_back("WarningHigh", upperNonCritical,
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700663 findThreshold->first);
664 }
665 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700666 for (const auto& property : thresholdsToSet)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700667 {
668 // from section 36.3 in the IPMI Spec, assume all linear
669 double valueToSet = ((mValue * std::get<thresholdValue>(property)) +
Josh Lehan86236a22019-11-18 17:53:33 -0800670 (bValue * std::pow(10.0, bExp))) *
671 std::pow(10.0, rExp);
Vernon Mauery15419dd2019-05-24 09:40:30 -0700672 setDbusProperty(
673 *getSdBus(), connection, path, std::get<interface>(property),
674 std::get<propertyName>(property), ipmi::Value(valueToSet));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700675 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000676 return ipmi::responseSuccess();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700677}
678
James Feistfcd2d3a2020-05-28 10:38:15 -0700679IPMIThresholds getIPMIThresholds(const SensorMap& sensorMap)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700680{
James Feist902c4c52019-04-16 14:51:31 -0700681 IPMIThresholds resp;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700682 auto warningInterface =
683 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
684 auto criticalInterface =
685 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
686
687 if ((warningInterface != sensorMap.end()) ||
688 (criticalInterface != sensorMap.end()))
689 {
690 auto sensorPair = sensorMap.find("xyz.openbmc_project.Sensor.Value");
691
692 if (sensorPair == sensorMap.end())
693 {
694 // should not have been able to find a sensor not implementing
695 // the sensor object
James Feist902c4c52019-04-16 14:51:31 -0700696 throw std::runtime_error("Invalid sensor map");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700697 }
698
Chen,Yugang606dd9f2019-07-01 10:37:30 +0800699 double max = 0;
700 double min = 0;
James Feistaecaef72019-04-26 10:30:32 -0700701 getSensorMaxMin(sensorMap, max, min);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700702
703 int16_t mValue = 0;
704 int16_t bValue = 0;
705 int8_t rExp = 0;
706 int8_t bExp = 0;
707 bool bSigned = false;
708
709 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
710 {
James Feist902c4c52019-04-16 14:51:31 -0700711 throw std::runtime_error("Invalid sensor atrributes");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700712 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700713 if (warningInterface != sensorMap.end())
714 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700715 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700716
717 auto warningHigh = warningMap.find("WarningHigh");
718 auto warningLow = warningMap.find("WarningLow");
719
720 if (warningHigh != warningMap.end())
721 {
James Feist902c4c52019-04-16 14:51:31 -0700722
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700723 double value =
724 std::visit(VariantToDoubleVisitor(), warningHigh->second);
James Feist902c4c52019-04-16 14:51:31 -0700725 resp.warningHigh = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700726 value, mValue, rExp, bValue, bExp, bSigned);
727 }
728 if (warningLow != warningMap.end())
729 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700730 double value =
731 std::visit(VariantToDoubleVisitor(), warningLow->second);
James Feist902c4c52019-04-16 14:51:31 -0700732 resp.warningLow = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700733 value, mValue, rExp, bValue, bExp, bSigned);
734 }
735 }
736 if (criticalInterface != sensorMap.end())
737 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700738 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700739
740 auto criticalHigh = criticalMap.find("CriticalHigh");
741 auto criticalLow = criticalMap.find("CriticalLow");
742
743 if (criticalHigh != criticalMap.end())
744 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700745 double value =
746 std::visit(VariantToDoubleVisitor(), criticalHigh->second);
James Feist902c4c52019-04-16 14:51:31 -0700747 resp.criticalHigh = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700748 value, mValue, rExp, bValue, bExp, bSigned);
749 }
750 if (criticalLow != criticalMap.end())
751 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700752 double value =
753 std::visit(VariantToDoubleVisitor(), criticalLow->second);
James Feist902c4c52019-04-16 14:51:31 -0700754 resp.criticalLow = scaleIPMIValueFromDouble(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700755 value, mValue, rExp, bValue, bExp, bSigned);
756 }
757 }
758 }
James Feist902c4c52019-04-16 14:51:31 -0700759 return resp;
760}
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700761
James Feist902c4c52019-04-16 14:51:31 -0700762ipmi::RspType<uint8_t, // readable
763 uint8_t, // lowerNCrit
764 uint8_t, // lowerCrit
765 uint8_t, // lowerNrecoverable
766 uint8_t, // upperNC
767 uint8_t, // upperCrit
768 uint8_t> // upperNRecoverable
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700769 ipmiSenGetSensorThresholds(ipmi::Context::ptr ctx, uint8_t sensorNumber)
James Feist902c4c52019-04-16 14:51:31 -0700770{
771 std::string connection;
772 std::string path;
773
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700774 auto status = getSensorConnection(ctx, sensorNumber, connection, path);
James Feist902c4c52019-04-16 14:51:31 -0700775 if (status)
776 {
777 return ipmi::response(status);
778 }
779
780 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700781 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
James Feist902c4c52019-04-16 14:51:31 -0700782 {
783 return ipmi::responseResponseError();
784 }
785
786 IPMIThresholds thresholdData;
787 try
788 {
789 thresholdData = getIPMIThresholds(sensorMap);
790 }
James Feistfcd2d3a2020-05-28 10:38:15 -0700791 catch (std::exception&)
James Feist902c4c52019-04-16 14:51:31 -0700792 {
793 return ipmi::responseResponseError();
794 }
795
796 uint8_t readable = 0;
797 uint8_t lowerNC = 0;
798 uint8_t lowerCritical = 0;
799 uint8_t lowerNonRecoverable = 0;
800 uint8_t upperNC = 0;
801 uint8_t upperCritical = 0;
802 uint8_t upperNonRecoverable = 0;
803
804 if (thresholdData.warningHigh)
805 {
806 readable |=
807 1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperNonCritical);
808 upperNC = *thresholdData.warningHigh;
809 }
810 if (thresholdData.warningLow)
811 {
812 readable |=
813 1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerNonCritical);
814 lowerNC = *thresholdData.warningLow;
815 }
816
817 if (thresholdData.criticalHigh)
818 {
819 readable |=
820 1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperCritical);
821 upperCritical = *thresholdData.criticalHigh;
822 }
823 if (thresholdData.criticalLow)
824 {
825 readable |=
826 1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerCritical);
827 lowerCritical = *thresholdData.criticalLow;
828 }
829
830 return ipmi::responseSuccess(readable, lowerNC, lowerCritical,
831 lowerNonRecoverable, upperNC, upperCritical,
832 upperNonRecoverable);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700833}
834
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000835/** @brief implements the get Sensor event enable command
836 * @param sensorNumber - sensor number
837 *
838 * @returns IPMI completion code plus response data
839 * - enabled - Sensor Event messages
840 * - assertionEnabledLsb - Assertion event messages
841 * - assertionEnabledMsb - Assertion event messages
842 * - deassertionEnabledLsb - Deassertion event messages
843 * - deassertionEnabledMsb - Deassertion event messages
844 */
845
846ipmi::RspType<uint8_t, // enabled
847 uint8_t, // assertionEnabledLsb
848 uint8_t, // assertionEnabledMsb
849 uint8_t, // deassertionEnabledLsb
850 uint8_t> // deassertionEnabledMsb
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700851 ipmiSenGetSensorEventEnable(ipmi::Context::ptr ctx, uint8_t sensorNum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700852{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700853 std::string connection;
854 std::string path;
855
Patrick Venturea41714c2019-09-25 16:59:41 -0700856 uint8_t enabled = 0;
857 uint8_t assertionEnabledLsb = 0;
858 uint8_t assertionEnabledMsb = 0;
859 uint8_t deassertionEnabledLsb = 0;
860 uint8_t deassertionEnabledMsb = 0;
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000861
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700862 auto status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700863 if (status)
864 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000865 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700866 }
867
868 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700869 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700870 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000871 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700872 }
873
874 auto warningInterface =
875 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
876 auto criticalInterface =
877 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700878 if ((warningInterface != sensorMap.end()) ||
879 (criticalInterface != sensorMap.end()))
880 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000881 enabled = static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700882 IPMISensorEventEnableByte2::sensorScanningEnable);
883 if (warningInterface != sensorMap.end())
884 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700885 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700886
887 auto warningHigh = warningMap.find("WarningHigh");
888 auto warningLow = warningMap.find("WarningLow");
889 if (warningHigh != warningMap.end())
890 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000891 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700892 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000893 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700894 IPMISensorEventEnableThresholds::upperNonCriticalGoingLow);
895 }
896 if (warningLow != warningMap.end())
897 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000898 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700899 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000900 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700901 IPMISensorEventEnableThresholds::lowerNonCriticalGoingHigh);
902 }
903 }
904 if (criticalInterface != sensorMap.end())
905 {
James Feistfcd2d3a2020-05-28 10:38:15 -0700906 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700907
908 auto criticalHigh = criticalMap.find("CriticalHigh");
909 auto criticalLow = criticalMap.find("CriticalLow");
910
911 if (criticalHigh != criticalMap.end())
912 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000913 assertionEnabledMsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700914 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000915 deassertionEnabledMsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700916 IPMISensorEventEnableThresholds::upperCriticalGoingLow);
917 }
918 if (criticalLow != criticalMap.end())
919 {
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000920 assertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700921 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000922 deassertionEnabledLsb |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700923 IPMISensorEventEnableThresholds::lowerCriticalGoingHigh);
924 }
925 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700926 }
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +0000927
928 return ipmi::responseSuccess(enabled, assertionEnabledLsb,
929 assertionEnabledMsb, deassertionEnabledLsb,
930 deassertionEnabledMsb);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700931}
932
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000933/** @brief implements the get Sensor event status command
934 * @param sensorNumber - sensor number, FFh = reserved
935 *
936 * @returns IPMI completion code plus response data
937 * - sensorEventStatus - Sensor Event messages state
938 * - assertions - Assertion event messages
939 * - deassertions - Deassertion event messages
940 */
941ipmi::RspType<uint8_t, // sensorEventStatus
942 std::bitset<16>, // assertions
943 std::bitset<16> // deassertion
944 >
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700945 ipmiSenGetSensorEventStatus(ipmi::Context::ptr ctx, uint8_t sensorNum)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700946{
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700947 if (sensorNum == reservedSensorNumber)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700948 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000949 return ipmi::responseInvalidFieldRequest();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700950 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700951
952 std::string connection;
953 std::string path;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700954 auto status = getSensorConnection(ctx, sensorNum, connection, path);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700955 if (status)
956 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000957 phosphor::logging::log<phosphor::logging::level::ERR>(
958 "ipmiSenGetSensorEventStatus: Sensor connection Error",
959 phosphor::logging::entry("SENSOR=%d", sensorNum));
960 return ipmi::response(status);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700961 }
962
963 SensorMap sensorMap;
Johnathan Mantey308c3a82020-07-22 11:50:54 -0700964 if (!getSensorMap(ctx->yield, connection, path, sensorMap))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700965 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000966 phosphor::logging::log<phosphor::logging::level::ERR>(
967 "ipmiSenGetSensorEventStatus: Sensor Mapping Error",
968 phosphor::logging::entry("SENSOR=%s", path.c_str()));
969 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700970 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700971 auto warningInterface =
972 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
973 auto criticalInterface =
974 sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
975
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000976 uint8_t sensorEventStatus =
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700977 static_cast<uint8_t>(IPMISensorEventEnableByte2::sensorScanningEnable);
978
James Feist392786a2019-03-19 13:36:10 -0700979 std::optional<bool> criticalDeassertHigh =
980 thresholdDeassertMap[path]["CriticalAlarmHigh"];
981 std::optional<bool> criticalDeassertLow =
982 thresholdDeassertMap[path]["CriticalAlarmLow"];
983 std::optional<bool> warningDeassertHigh =
984 thresholdDeassertMap[path]["WarningAlarmHigh"];
985 std::optional<bool> warningDeassertLow =
986 thresholdDeassertMap[path]["WarningAlarmLow"];
987
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000988 std::bitset<16> assertions = 0;
989 std::bitset<16> deassertions = 0;
990
James Feist392786a2019-03-19 13:36:10 -0700991 if (criticalDeassertHigh && !*criticalDeassertHigh)
992 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000993 deassertions.set(static_cast<size_t>(
994 IPMIGetSensorEventEnableThresholds::upperCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -0700995 }
996 if (criticalDeassertLow && !*criticalDeassertLow)
997 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +0000998 deassertions.set(static_cast<size_t>(
999 IPMIGetSensorEventEnableThresholds::upperCriticalGoingLow));
James Feist392786a2019-03-19 13:36:10 -07001000 }
1001 if (warningDeassertHigh && !*warningDeassertHigh)
1002 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001003 deassertions.set(static_cast<size_t>(
1004 IPMIGetSensorEventEnableThresholds::upperNonCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001005 }
1006 if (warningDeassertLow && !*warningDeassertLow)
1007 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001008 deassertions.set(static_cast<size_t>(
1009 IPMIGetSensorEventEnableThresholds::lowerNonCriticalGoingHigh));
James Feist392786a2019-03-19 13:36:10 -07001010 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001011 if ((warningInterface != sensorMap.end()) ||
1012 (criticalInterface != sensorMap.end()))
1013 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001014 sensorEventStatus = static_cast<size_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001015 IPMISensorEventEnableByte2::eventMessagesEnable);
1016 if (warningInterface != sensorMap.end())
1017 {
James Feistfcd2d3a2020-05-28 10:38:15 -07001018 auto& warningMap = warningInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001019
1020 auto warningHigh = warningMap.find("WarningAlarmHigh");
1021 auto warningLow = warningMap.find("WarningAlarmLow");
1022 auto warningHighAlarm = false;
1023 auto warningLowAlarm = false;
1024
1025 if (warningHigh != warningMap.end())
1026 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001027 warningHighAlarm = std::get<bool>(warningHigh->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001028 }
1029 if (warningLow != warningMap.end())
1030 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001031 warningLowAlarm = std::get<bool>(warningLow->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001032 }
1033 if (warningHighAlarm)
1034 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001035 assertions.set(
1036 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1037 upperNonCriticalGoingHigh));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001038 }
1039 if (warningLowAlarm)
1040 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001041 assertions.set(
1042 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1043 lowerNonCriticalGoingLow));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001044 }
1045 }
1046 if (criticalInterface != sensorMap.end())
1047 {
James Feistfcd2d3a2020-05-28 10:38:15 -07001048 auto& criticalMap = criticalInterface->second;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001049
1050 auto criticalHigh = criticalMap.find("CriticalAlarmHigh");
1051 auto criticalLow = criticalMap.find("CriticalAlarmLow");
1052 auto criticalHighAlarm = false;
1053 auto criticalLowAlarm = false;
1054
1055 if (criticalHigh != criticalMap.end())
1056 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001057 criticalHighAlarm = std::get<bool>(criticalHigh->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001058 }
1059 if (criticalLow != criticalMap.end())
1060 {
Vernon Mauery8166c8d2019-05-23 11:22:30 -07001061 criticalLowAlarm = std::get<bool>(criticalLow->second);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001062 }
1063 if (criticalHighAlarm)
1064 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001065 assertions.set(
1066 static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
1067 upperCriticalGoingHigh));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001068 }
1069 if (criticalLowAlarm)
1070 {
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001071 assertions.set(static_cast<size_t>(
1072 IPMIGetSensorEventEnableThresholds::lowerCriticalGoingLow));
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001073 }
1074 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001075 }
1076
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001077 return ipmi::responseSuccess(sensorEventStatus, assertions, deassertions);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001078}
1079
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001080static int getSensorDataRecord(ipmi::Context::ptr ctx,
1081 std::vector<uint8_t>& recordData,
1082 uint16_t recordID)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001083{
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001084 size_t fruCount = 0;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001085 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
1086 if (ret != ipmi::ccSuccess)
1087 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001088 phosphor::logging::log<phosphor::logging::level::ERR>(
1089 "getSensorDataRecord: getFruSdrCount error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001090 return GENERAL_ERROR;
1091 }
1092
1093 size_t lastRecord = sensorTree.size() + fruCount +
1094 ipmi::storage::type12Count +
1095 ipmi::storage::nmDiscoverySDRCount - 1;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001096 if (recordID == lastRecordIndex)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001097 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001098 recordID = lastRecord;
1099 }
1100 if (recordID > lastRecord)
1101 {
1102 phosphor::logging::log<phosphor::logging::level::ERR>(
1103 "getSensorDataRecord: recordID > lastRecord error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001104 return GENERAL_ERROR;
1105 }
1106
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001107 if (recordID >= sensorTree.size())
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001108 {
1109 size_t fruIndex = recordID - sensorTree.size();
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001110 size_t type12End = fruCount + ipmi::storage::type12Count;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001111
1112 if (fruIndex >= type12End)
1113 {
1114 // NM discovery SDR
1115 size_t nmDiscoveryIndex = fruIndex - type12End;
1116 if (nmDiscoveryIndex >= ipmi::storage::nmDiscoverySDRCount)
1117 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001118 phosphor::logging::log<phosphor::logging::level::ERR>(
1119 "getSensorDataRecord: NM DiscoveryIndex error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001120 return GENERAL_ERROR;
1121 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001122 recordData =
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001123 ipmi::storage::getNMDiscoverySDR(nmDiscoveryIndex, recordID);
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001124 }
1125 else if (fruIndex >= fruCount)
1126 {
1127 // handle type 12 hardcoded records
1128 size_t type12Index = fruIndex - fruCount;
1129 if (type12Index >= ipmi::storage::type12Count)
1130 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001131 phosphor::logging::log<phosphor::logging::level::ERR>(
1132 "getSensorDataRecord: type12Index error");
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001133 return GENERAL_ERROR;
1134 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001135 recordData = ipmi::storage::getType12SDRs(type12Index, recordID);
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001136 }
1137 else
1138 {
1139 // handle fru records
1140 get_sdr::SensorDataFruRecord data;
1141 ret = ipmi::storage::getFruSdrs(ctx, fruIndex, data);
1142 if (ret != IPMI_CC_OK)
1143 {
1144 return GENERAL_ERROR;
1145 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001146 data.header.record_id_msb = recordID >> 8;
1147 data.header.record_id_lsb = recordID & 0xFF;
1148 recordData.insert(recordData.end(), (uint8_t*)&data,
1149 ((uint8_t*)&data) + sizeof(data));
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001150 }
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001151
1152 return 0;
1153 }
1154
1155 std::string connection;
1156 std::string path;
1157 auto status = getSensorConnection(ctx, recordID, connection, path);
1158 if (status)
1159 {
1160 phosphor::logging::log<phosphor::logging::level::ERR>(
1161 "getSensorDataRecord: getSensorConnection error");
1162 return GENERAL_ERROR;
1163 }
1164 SensorMap sensorMap;
1165 if (!getSensorMap(ctx->yield, connection, path, sensorMap,
1166 sensorMapUpdatePeriod))
1167 {
1168 phosphor::logging::log<phosphor::logging::level::ERR>(
1169 "getSensorDataRecord: getSensorMap error");
1170 return GENERAL_ERROR;
1171 }
1172 uint16_t sensorNum = getSensorNumberFromPath(path);
1173 if (sensorNum == invalidSensorNumber)
1174 {
1175 phosphor::logging::log<phosphor::logging::level::ERR>(
1176 "getSensorDataRecord: invalidSensorNumber");
1177 return GENERAL_ERROR;
1178 }
1179 uint8_t sensornumber = static_cast<uint8_t>(sensorNum);
1180 uint8_t lun = static_cast<uint8_t>(sensorNum >> 8);
1181
1182 get_sdr::SensorDataFullRecord record = {0};
1183
1184 get_sdr::header::set_record_id(
1185 recordID, reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&record));
1186
1187 record.header.sdr_version = ipmiSdrVersion;
1188 record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD;
1189 record.header.record_length = sizeof(get_sdr::SensorDataFullRecord) -
1190 sizeof(get_sdr::SensorDataRecordHeader);
1191 record.key.owner_id = 0x20;
1192 record.key.owner_lun = lun;
1193 record.key.sensor_number = sensornumber;
1194
1195 record.body.sensor_capabilities = 0x68; // auto rearm - todo hysteresis
1196 record.body.sensor_type = getSensorTypeFromPath(path);
1197 std::string type = getSensorTypeStringFromPath(path);
1198 auto typeCstr = type.c_str();
1199 auto findUnits = sensorUnits.find(typeCstr);
1200 if (findUnits != sensorUnits.end())
1201 {
1202 record.body.sensor_units_2_base =
1203 static_cast<uint8_t>(findUnits->second);
1204 } // else default 0x0 unspecified
1205
1206 record.body.event_reading_type = getSensorEventTypeFromPath(path);
1207
1208 auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
1209 if (sensorObject == sensorMap.end())
1210 {
1211 phosphor::logging::log<phosphor::logging::level::ERR>(
1212 "getSensorDataRecord: sensorObject error");
1213 return GENERAL_ERROR;
1214 }
1215
1216 uint8_t entityId = 0;
1217 uint8_t entityInstance = 0x01;
1218
1219 // follow the association chain to get the parent board's entityid and
1220 // entityInstance
1221 updateIpmiFromAssociation(path, sensorMap, entityId, entityInstance);
1222
1223 record.body.entity_id = entityId;
1224 record.body.entity_instance = entityInstance;
1225
1226 auto maxObject = sensorObject->second.find("MaxValue");
1227 auto minObject = sensorObject->second.find("MinValue");
1228
1229 // If min and/or max are left unpopulated,
1230 // then default to what a signed byte would be, namely (-128,127) range.
1231 auto max = static_cast<double>(std::numeric_limits<int8_t>::max());
1232 auto min = static_cast<double>(std::numeric_limits<int8_t>::lowest());
1233 if (maxObject != sensorObject->second.end())
1234 {
1235 max = std::visit(VariantToDoubleVisitor(), maxObject->second);
1236 }
1237
1238 if (minObject != sensorObject->second.end())
1239 {
1240 min = std::visit(VariantToDoubleVisitor(), minObject->second);
1241 }
1242
1243 int16_t mValue = 0;
1244 int8_t rExp = 0;
1245 int16_t bValue = 0;
1246 int8_t bExp = 0;
1247 bool bSigned = false;
1248
1249 if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
1250 {
1251 phosphor::logging::log<phosphor::logging::level::ERR>(
1252 "getSensorDataRecord: getSensorAttributes error");
1253 return GENERAL_ERROR;
1254 }
1255
1256 // The record.body is a struct SensorDataFullRecordBody
1257 // from sensorhandler.hpp in phosphor-ipmi-host.
1258 // The meaning of these bits appears to come from
1259 // table 43.1 of the IPMI spec.
1260 // The above 5 sensor attributes are stuffed in as follows:
1261 // Byte 21 = AA000000 = analog interpretation, 10 signed, 00 unsigned
1262 // Byte 22-24 are for other purposes
1263 // Byte 25 = MMMMMMMM = LSB of M
1264 // Byte 26 = MMTTTTTT = MSB of M (signed), and Tolerance
1265 // Byte 27 = BBBBBBBB = LSB of B
1266 // Byte 28 = BBAAAAAA = MSB of B (signed), and LSB of Accuracy
1267 // Byte 29 = AAAAEE00 = MSB of Accuracy, exponent of Accuracy
1268 // Byte 30 = RRRRBBBB = rExp (signed), bExp (signed)
1269
1270 // apply M, B, and exponents, M and B are 10 bit values, exponents are 4
1271 record.body.m_lsb = mValue & 0xFF;
1272
1273 uint8_t mBitSign = (mValue < 0) ? 1 : 0;
1274 uint8_t mBitNine = (mValue & 0x0100) >> 8;
1275
1276 // move the smallest bit of the MSB into place (bit 9)
1277 // the MSbs are bits 7:8 in m_msb_and_tolerance
1278 record.body.m_msb_and_tolerance = (mBitSign << 7) | (mBitNine << 6);
1279
1280 record.body.b_lsb = bValue & 0xFF;
1281
1282 uint8_t bBitSign = (bValue < 0) ? 1 : 0;
1283 uint8_t bBitNine = (bValue & 0x0100) >> 8;
1284
1285 // move the smallest bit of the MSB into place (bit 9)
1286 // the MSbs are bits 7:8 in b_msb_and_accuracy_lsb
1287 record.body.b_msb_and_accuracy_lsb = (bBitSign << 7) | (bBitNine << 6);
1288
1289 uint8_t rExpSign = (rExp < 0) ? 1 : 0;
1290 uint8_t rExpBits = rExp & 0x07;
1291
1292 uint8_t bExpSign = (bExp < 0) ? 1 : 0;
1293 uint8_t bExpBits = bExp & 0x07;
1294
1295 // move rExp and bExp into place
1296 record.body.r_b_exponents =
1297 (rExpSign << 7) | (rExpBits << 4) | (bExpSign << 3) | bExpBits;
1298
1299 // Set the analog reading byte interpretation accordingly
1300 record.body.sensor_units_1 = (bSigned ? 1 : 0) << 7;
1301
1302 // TODO(): Perhaps care about Tolerance, Accuracy, and so on
1303 // These seem redundant, but derivable from the above 5 attributes
1304 // Original comment said "todo fill out rest of units"
1305
1306 // populate sensor name from path
1307 std::string name;
1308 size_t nameStart = path.rfind("/");
1309 if (nameStart != std::string::npos)
1310 {
1311 name = path.substr(nameStart + 1, std::string::npos - nameStart);
1312 }
1313
1314 std::replace(name.begin(), name.end(), '_', ' ');
1315 if (name.size() > FULL_RECORD_ID_STR_MAX_LENGTH)
1316 {
1317 // try to not truncate by replacing common words
1318 constexpr std::array<std::pair<const char*, const char*>, 2>
1319 replaceWords = {std::make_pair("Output", "Out"),
1320 std::make_pair("Input", "In")};
1321 for (const auto& [find, replace] : replaceWords)
1322 {
1323 boost::replace_all(name, find, replace);
1324 }
1325
1326 name.resize(FULL_RECORD_ID_STR_MAX_LENGTH);
1327 }
1328 record.body.id_string_info = name.size();
1329 std::strncpy(record.body.id_string, name.c_str(),
1330 sizeof(record.body.id_string));
1331
1332 IPMIThresholds thresholdData;
1333 try
1334 {
1335 thresholdData = getIPMIThresholds(sensorMap);
1336 }
1337 catch (std::exception&)
1338 {
1339 phosphor::logging::log<phosphor::logging::level::ERR>(
1340 "getSensorDataRecord: getIPMIThresholds error");
1341 return GENERAL_ERROR;
1342 }
1343
1344 if (thresholdData.criticalHigh)
1345 {
1346 record.body.upper_critical_threshold = *thresholdData.criticalHigh;
1347 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1348 IPMISensorEventEnableThresholds::criticalThreshold);
1349 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1350 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
1351 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1352 IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
1353 record.body.discrete_reading_setting_mask[0] |=
1354 static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
1355 }
1356 if (thresholdData.warningHigh)
1357 {
1358 record.body.upper_noncritical_threshold = *thresholdData.warningHigh;
1359 record.body.supported_deassertions[1] |= static_cast<uint8_t>(
1360 IPMISensorEventEnableThresholds::nonCriticalThreshold);
1361 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1362 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
1363 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1364 IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
1365 record.body.discrete_reading_setting_mask[0] |=
1366 static_cast<uint8_t>(IPMISensorReadingByte3::upperNonCritical);
1367 }
1368 if (thresholdData.criticalLow)
1369 {
1370 record.body.lower_critical_threshold = *thresholdData.criticalLow;
1371 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1372 IPMISensorEventEnableThresholds::criticalThreshold);
1373 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1374 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
1375 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1376 IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
1377 record.body.discrete_reading_setting_mask[0] |=
1378 static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
1379 }
1380 if (thresholdData.warningLow)
1381 {
1382 record.body.lower_noncritical_threshold = *thresholdData.warningLow;
1383 record.body.supported_assertions[1] |= static_cast<uint8_t>(
1384 IPMISensorEventEnableThresholds::nonCriticalThreshold);
1385 record.body.supported_deassertions[0] |= static_cast<uint8_t>(
1386 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
1387 record.body.supported_assertions[0] |= static_cast<uint8_t>(
1388 IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
1389 record.body.discrete_reading_setting_mask[0] |=
1390 static_cast<uint8_t>(IPMISensorReadingByte3::lowerNonCritical);
1391 }
1392
1393 // everything that is readable is setable
1394 record.body.discrete_reading_setting_mask[1] =
1395 record.body.discrete_reading_setting_mask[0];
1396 recordData.insert(recordData.end(), (uint8_t*)&record,
1397 ((uint8_t*)&record) + sizeof(record));
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001398 return 0;
1399}
1400
1401/** @brief implements the get SDR Info command
1402 * @param count - Operation
1403 *
1404 * @returns IPMI completion code plus response data
1405 * - sdrCount - sensor/SDR count
1406 * - lunsAndDynamicPopulation - static/Dynamic sensor population flag
1407 */
1408static ipmi::RspType<uint8_t, // respcount
1409 uint8_t, // dynamic population flags
1410 uint32_t // last time a sensor was added
1411 >
1412 ipmiSensorGetDeviceSdrInfo(ipmi::Context::ptr ctx,
1413 std::optional<uint8_t> count)
1414{
1415 uint8_t sdrCount = 0;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001416 uint16_t recordID = 0;
1417 std::vector<uint8_t> record;
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001418 // Sensors are dynamically allocated, and there is at least one LUN
1419 uint8_t lunsAndDynamicPopulation = 0x80;
1420 constexpr uint8_t getSdrCount = 0x01;
1421 constexpr uint8_t getSensorCount = 0x00;
1422
1423 if (!getSensorSubtree(sensorTree) || sensorTree.empty())
1424 {
1425 return ipmi::responseResponseError();
1426 }
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001427 uint16_t numSensors = sensorTree.size();
1428 if (count.value_or(0) == getSdrCount)
1429 {
1430 // Count the number of Type 1 SDR entries assigned to the LUN
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001431 while (!getSensorDataRecord(ctx, record, recordID++))
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001432 {
1433 get_sdr::SensorDataRecordHeader* hdr =
1434 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001435 record.data());
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001436 if (hdr->record_type == get_sdr::SENSOR_DATA_FULL_RECORD)
1437 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001438 get_sdr::SensorDataFullRecord* recordData =
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001439 reinterpret_cast<get_sdr::SensorDataFullRecord*>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001440 record.data());
1441 if (ctx->lun == recordData->key.owner_lun)
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001442 {
1443 sdrCount++;
1444 }
1445 }
1446 }
1447 }
1448 else if (count.value_or(0) == getSensorCount)
1449 {
1450 // Return the number of sensors attached to the LUN
1451 if ((ctx->lun == 0) && (numSensors > 0))
1452 {
1453 sdrCount =
1454 (numSensors > maxSensorsPerLUN) ? maxSensorsPerLUN : numSensors;
1455 }
1456 else if ((ctx->lun == 1) && (numSensors > maxSensorsPerLUN))
1457 {
1458 sdrCount = (numSensors > (2 * maxSensorsPerLUN))
1459 ? maxSensorsPerLUN
1460 : (numSensors - maxSensorsPerLUN) & maxSensorsPerLUN;
1461 }
1462 else if (ctx->lun == 3)
1463 {
1464 if (numSensors <= maxIPMISensors)
1465 {
1466 sdrCount =
1467 (numSensors - (2 * maxSensorsPerLUN)) & maxSensorsPerLUN;
1468 }
1469 else
1470 {
1471 // error
1472 throw std::out_of_range(
1473 "Maximum number of IPMI sensors exceeded.");
1474 }
1475 }
1476 }
1477 else
1478 {
1479 return ipmi::responseInvalidFieldRequest();
1480 }
1481
1482 // Get Sensor count. This returns the number of sensors
1483 if (numSensors > 0)
1484 {
1485 lunsAndDynamicPopulation |= 1;
1486 }
1487 if (numSensors > maxSensorsPerLUN)
1488 {
1489 lunsAndDynamicPopulation |= 2;
1490 }
1491 if (numSensors >= (maxSensorsPerLUN * 2))
1492 {
1493 lunsAndDynamicPopulation |= 8;
1494 }
1495 if (numSensors > maxIPMISensors)
1496 {
1497 // error
1498 throw std::out_of_range("Maximum number of IPMI sensors exceeded.");
1499 }
1500
1501 return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation,
1502 sdrLastAdd);
1503}
1504
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001505/* end sensor commands */
1506
1507/* storage commands */
1508
James Feist74c50c62019-08-14 14:18:41 -07001509ipmi::RspType<uint8_t, // sdr version
1510 uint16_t, // record count
1511 uint16_t, // free space
1512 uint32_t, // most recent addition
1513 uint32_t, // most recent erase
1514 uint8_t // operationSupport
1515 >
James Feist25690252019-12-23 12:25:49 -08001516 ipmiStorageGetSDRRepositoryInfo(ipmi::Context::ptr ctx)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001517{
James Feist74c50c62019-08-14 14:18:41 -07001518 constexpr const uint16_t unspecifiedFreeSpace = 0xFFFF;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001519 if (!getSensorSubtree(sensorTree) && sensorTree.empty())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001520 {
James Feist74c50c62019-08-14 14:18:41 -07001521 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001522 }
1523
James Feist74c50c62019-08-14 14:18:41 -07001524 size_t fruCount = 0;
James Feist25690252019-12-23 12:25:49 -08001525 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
James Feist74c50c62019-08-14 14:18:41 -07001526 if (ret != ipmi::ccSuccess)
1527 {
1528 return ipmi::response(ret);
1529 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001530
James Feist74c50c62019-08-14 14:18:41 -07001531 uint16_t recordCount =
1532 sensorTree.size() + fruCount + ipmi::storage::type12Count;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001533
James Feist74c50c62019-08-14 14:18:41 -07001534 uint8_t operationSupport = static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001535 SdrRepositoryInfoOps::overflow); // write not supported
James Feist74c50c62019-08-14 14:18:41 -07001536
1537 operationSupport |=
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001538 static_cast<uint8_t>(SdrRepositoryInfoOps::allocCommandSupported);
James Feist74c50c62019-08-14 14:18:41 -07001539 operationSupport |= static_cast<uint8_t>(
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001540 SdrRepositoryInfoOps::reserveSDRRepositoryCommandSupported);
James Feist74c50c62019-08-14 14:18:41 -07001541 return ipmi::responseSuccess(ipmiSdrVersion, recordCount,
1542 unspecifiedFreeSpace, sdrLastAdd,
1543 sdrLastRemove, operationSupport);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001544}
1545
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001546/** @brief implements the get SDR allocation info command
1547 *
1548 * @returns IPMI completion code plus response data
1549 * - allocUnits - Number of possible allocation units
1550 * - allocUnitSize - Allocation unit size in bytes.
1551 * - allocUnitFree - Number of free allocation units
1552 * - allocUnitLargestFree - Largest free block in allocation units
1553 * - maxRecordSize - Maximum record size in allocation units.
1554 */
1555ipmi::RspType<uint16_t, // allocUnits
1556 uint16_t, // allocUnitSize
1557 uint16_t, // allocUnitFree
1558 uint16_t, // allocUnitLargestFree
1559 uint8_t // maxRecordSize
1560 >
1561 ipmiStorageGetSDRAllocationInfo()
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001562{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001563 // 0000h unspecified number of alloc units
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001564 constexpr uint16_t allocUnits = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001565
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001566 constexpr uint16_t allocUnitFree = 0;
1567 constexpr uint16_t allocUnitLargestFree = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001568 // only allow one block at a time
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001569 constexpr uint8_t maxRecordSize = 1;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001570
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001571 return ipmi::responseSuccess(allocUnits, maxSDRTotalSize, allocUnitFree,
1572 allocUnitLargestFree, maxRecordSize);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001573}
1574
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001575/** @brief implements the reserve SDR command
1576 * @returns IPMI completion code plus response data
1577 * - sdrReservationID
1578 */
1579ipmi::RspType<uint16_t> ipmiStorageReserveSDR()
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001580{
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001581 sdrReservationID++;
James Feista80cb902019-02-14 13:05:25 -08001582 if (sdrReservationID == 0)
1583 {
1584 sdrReservationID++;
1585 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001586
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001587 return ipmi::responseSuccess(sdrReservationID);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001588}
1589
James Feistb49a98a2019-04-16 13:48:09 -07001590ipmi::RspType<uint16_t, // next record ID
1591 std::vector<uint8_t> // payload
1592 >
James Feist25690252019-12-23 12:25:49 -08001593 ipmiStorageGetSDR(ipmi::Context::ptr ctx, uint16_t reservationID,
1594 uint16_t recordID, uint8_t offset, uint8_t bytesToRead)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001595{
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001596 size_t fruCount = 0;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001597 // reservation required for partial reads with non zero offset into
1598 // record
James Feistb49a98a2019-04-16 13:48:09 -07001599 if ((sdrReservationID == 0 || reservationID != sdrReservationID) && offset)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001600 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001601 phosphor::logging::log<phosphor::logging::level::ERR>(
1602 "ipmiStorageGetSDR: responseInvalidReservationId");
James Feistb49a98a2019-04-16 13:48:09 -07001603 return ipmi::responseInvalidReservationId();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001604 }
James Feist25690252019-12-23 12:25:49 -08001605 ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
James Feist74c50c62019-08-14 14:18:41 -07001606 if (ret != ipmi::ccSuccess)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001607 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001608 phosphor::logging::log<phosphor::logging::level::ERR>(
1609 "ipmiStorageGetSDR: getFruSdrCount error");
James Feistb49a98a2019-04-16 13:48:09 -07001610 return ipmi::response(ret);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001611 }
1612
Yong Lifee5e4c2020-01-17 19:36:29 +08001613 size_t lastRecord = sensorTree.size() + fruCount +
1614 ipmi::storage::type12Count +
1615 ipmi::storage::nmDiscoverySDRCount - 1;
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001616 uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF;
1617
1618 if (!getSensorSubtree(sensorTree) && sensorTree.empty())
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001619 {
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001620 phosphor::logging::log<phosphor::logging::level::ERR>(
1621 "ipmiStorageGetSDR: getSensorSubtree error");
1622 return ipmi::responseResponseError();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001623 }
1624
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001625 std::vector<uint8_t> record;
1626 if (getSensorDataRecord(ctx, record, recordID))
1627 {
1628 phosphor::logging::log<phosphor::logging::level::ERR>(
1629 "ipmiStorageGetSDR: fail to get SDR");
1630 return ipmi::responseInvalidFieldRequest();
1631 }
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001632 get_sdr::SensorDataRecordHeader* hdr =
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001633 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(record.data());
Kuiying Wangb9109872021-01-15 15:54:59 +08001634 if (!hdr)
1635 {
1636 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001637 "ipmiStorageGetSDR: record header is null");
1638 return ipmi::responseSuccess(nextRecordId, record);
Kuiying Wangb9109872021-01-15 15:54:59 +08001639 }
1640
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001641 size_t sdrLength =
1642 sizeof(get_sdr::SensorDataRecordHeader) + hdr->record_length;
1643 if (sdrLength < (offset + bytesToRead))
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001644 {
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001645 bytesToRead = sdrLength - offset;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001646 }
1647
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001648 uint8_t* respStart = reinterpret_cast<uint8_t*>(hdr) + offset;
Kuiying Wangb9109872021-01-15 15:54:59 +08001649 if (!respStart)
1650 {
1651 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001652 "ipmiStorageGetSDR: record is null");
1653 return ipmi::responseSuccess(nextRecordId, record);
Kuiying Wangb9109872021-01-15 15:54:59 +08001654 }
James Feistb49a98a2019-04-16 13:48:09 -07001655 std::vector<uint8_t> recordData(respStart, respStart + bytesToRead);
Kuiying Wang17eadbf2021-02-06 23:38:22 +08001656
James Feistb49a98a2019-04-16 13:48:09 -07001657 return ipmi::responseSuccess(nextRecordId, recordData);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001658}
1659/* end storage commands */
1660
1661void registerSensorFunctions()
1662{
Jason M. Billsae6bdb12019-04-02 12:00:04 -07001663 // <Platform Event>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001664 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1665 ipmi::sensor_event::cmdPlatformEvent,
1666 ipmi::Privilege::Operator, ipmiSenPlatformEvent);
Jason M. Billsae6bdb12019-04-02 12:00:04 -07001667
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001668 // <Get Sensor Reading>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001669 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1670 ipmi::sensor_event::cmdGetSensorReading,
1671 ipmi::Privilege::User, ipmiSenGetSensorReading);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001672
1673 // <Get Sensor Threshold>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001674 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1675 ipmi::sensor_event::cmdGetSensorThreshold,
1676 ipmi::Privilege::User, ipmiSenGetSensorThresholds);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001677
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +00001678 // <Set Sensor Threshold>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001679 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1680 ipmi::sensor_event::cmdSetSensorThreshold,
1681 ipmi::Privilege::Operator,
1682 ipmiSenSetSensorThresholds);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001683
1684 // <Get Sensor Event Enable>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001685 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1686 ipmi::sensor_event::cmdGetSensorEventEnable,
jayaprakash Mutyala39fa93f2019-05-13 12:16:30 +00001687 ipmi::Privilege::User, ipmiSenGetSensorEventEnable);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001688
1689 // <Get Sensor Event Status>
jayaprakash Mutyalaccf88f62019-05-13 16:57:16 +00001690 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1691 ipmi::sensor_event::cmdGetSensorEventStatus,
1692 ipmi::Privilege::User, ipmiSenGetSensorEventStatus);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001693
1694 // register all storage commands for both Sensor and Storage command
1695 // versions
1696
1697 // <Get SDR Repository Info>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001698 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1699 ipmi::storage::cmdGetSdrRepositoryInfo,
1700 ipmi::Privilege::User,
1701 ipmiStorageGetSDRRepositoryInfo);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001702
Johnathan Mantey308c3a82020-07-22 11:50:54 -07001703 // <Get Device SDR Info>
1704 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1705 ipmi::sensor_event::cmdGetDeviceSdrInfo,
1706 ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo);
1707
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001708 // <Get SDR Allocation Info>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001709 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1710 ipmi::storage::cmdGetSdrRepositoryAllocInfo,
1711 ipmi::Privilege::User,
1712 ipmiStorageGetSDRAllocationInfo);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001713
1714 // <Reserve SDR Repo>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001715 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1716 ipmi::sensor_event::cmdReserveDeviceSdrRepository,
jayaprakash Mutyala6ae08182019-05-13 18:56:11 +00001717 ipmi::Privilege::User, ipmiStorageReserveSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001718
Vernon Mauery98bbf692019-09-16 11:14:59 -07001719 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1720 ipmi::storage::cmdReserveSdrRepository,
1721 ipmi::Privilege::User, ipmiStorageReserveSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001722
1723 // <Get Sdr>
Vernon Mauery98bbf692019-09-16 11:14:59 -07001724 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnSensor,
1725 ipmi::sensor_event::cmdGetDeviceSdr,
1726 ipmi::Privilege::User, ipmiStorageGetSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001727
Vernon Mauery98bbf692019-09-16 11:14:59 -07001728 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
1729 ipmi::storage::cmdGetSdr, ipmi::Privilege::User,
1730 ipmiStorageGetSDR);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001731}
1732} // namespace ipmi