blob: 143982d93408f4f13e30b4eafde0e84901ef5a31 [file] [log] [blame]
Brandon Kim9cf85622019-06-19 12:05:08 -07001#include "config.h"
2
Patrick Venture46470a32018-09-07 19:26:25 -07003#include "sensorhandler.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07004
Patrick Venture99bf1c42019-08-23 09:02:13 -07005#include "entity_map_json.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07006#include "fruread.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07007
Tomd700e762016-09-20 18:24:13 +05308#include <mapper.h>
Chris Austen10ccc0f2015-12-10 18:27:04 -06009#include <systemd/sd-bus.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070010
11#include <bitset>
Patrick Venture586d35b2018-09-07 19:56:18 -070012#include <cmath>
Patrick Ventureb51bf9c2018-09-10 15:53:14 -070013#include <cstring>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070014#include <ipmid/api.hpp>
Vernon Mauery33250242019-03-12 16:49:26 -070015#include <ipmid/types.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070016#include <ipmid/utils.hpp>
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050017#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070018#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070019#include <sdbusplus/message/types.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070020#include <set>
21#include <xyz/openbmc_project/Common/error.hpp>
22#include <xyz/openbmc_project/Sensor/Value/server.hpp>
23
Ratan Guptae0cc8552018-01-22 14:23:04 +053024static constexpr uint8_t fruInventoryDevice = 0x10;
25static constexpr uint8_t IPMIFruInventory = 0x02;
26static constexpr uint8_t BMCSlaveAddress = 0x20;
27
Patrick Venture0b02be92018-08-31 11:55:55 -070028extern int updateSensorRecordFromSSRAESC(const void*);
29extern sd_bus* bus;
Patrick Venturedb0cbe62019-09-09 14:47:22 -070030
31namespace ipmi
32{
33namespace sensor
34{
35extern const IdInfoMap sensors;
36} // namespace sensor
37} // namespace ipmi
38
Ratan Guptae0cc8552018-01-22 14:23:04 +053039extern const FruMap frus;
40
Tom Josephbe703f72017-03-09 12:34:35 +053041using namespace phosphor::logging;
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050042using InternalFailure =
43 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Chris Austenac4604a2015-10-13 12:43:27 -050044
Patrick Venture0b02be92018-08-31 11:55:55 -070045void register_netfn_sen_functions() __attribute__((constructor));
Chris Austenac4604a2015-10-13 12:43:27 -050046
Patrick Venture0b02be92018-08-31 11:55:55 -070047struct sensorTypemap_t
48{
Chris Austen0012e9b2015-10-22 01:37:46 -050049 uint8_t number;
Chris Austend7cf0e42015-11-07 14:27:12 -060050 uint8_t typecode;
Chris Austen0012e9b2015-10-22 01:37:46 -050051 char dbusname[32];
Patrick Venture0b02be92018-08-31 11:55:55 -070052};
Chris Austen0012e9b2015-10-22 01:37:46 -050053
Chris Austen0012e9b2015-10-22 01:37:46 -050054sensorTypemap_t g_SensorTypeMap[] = {
55
Chris Austend7cf0e42015-11-07 14:27:12 -060056 {0x01, 0x6F, "Temp"},
57 {0x0C, 0x6F, "DIMM"},
58 {0x0C, 0x6F, "MEMORY_BUFFER"},
59 {0x07, 0x6F, "PROC"},
60 {0x07, 0x6F, "CORE"},
61 {0x07, 0x6F, "CPU"},
62 {0x0F, 0x6F, "BootProgress"},
Patrick Venture0b02be92018-08-31 11:55:55 -070063 {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor
64 // type code os 0x09
Chris Austend7cf0e42015-11-07 14:27:12 -060065 {0xC3, 0x6F, "BootCount"},
66 {0x1F, 0x6F, "OperatingSystemStatus"},
Chris Austen800ba712015-12-03 15:31:00 -060067 {0x12, 0x6F, "SYSTEM_EVENT"},
68 {0xC7, 0x03, "SYSTEM"},
69 {0xC7, 0x03, "MAIN_PLANAR"},
Chris Austen10ccc0f2015-12-10 18:27:04 -060070 {0xC2, 0x6F, "PowerCap"},
Tom Joseph558184e2017-09-01 13:45:05 +053071 {0x0b, 0xCA, "PowerSupplyRedundancy"},
Jayanth Othayoth0661beb2017-03-22 06:00:58 -050072 {0xDA, 0x03, "TurboAllowed"},
Tom Joseph558184e2017-09-01 13:45:05 +053073 {0xD8, 0xC8, "PowerSupplyDerating"},
Chris Austend7cf0e42015-11-07 14:27:12 -060074 {0xFF, 0x00, ""},
Chris Austen0012e9b2015-10-22 01:37:46 -050075};
76
Patrick Venture0b02be92018-08-31 11:55:55 -070077struct sensor_data_t
78{
Chris Austenac4604a2015-10-13 12:43:27 -050079 uint8_t sennum;
Patrick Venture0b02be92018-08-31 11:55:55 -070080} __attribute__((packed));
Chris Austenac4604a2015-10-13 12:43:27 -050081
Lei YU14a47812021-09-17 15:58:04 +080082using SDRCacheMap = std::unordered_map<uint8_t, get_sdr::SensorDataFullRecord>;
83SDRCacheMap sdrCacheMap __attribute__((init_priority(101)));
84
85using SensorThresholdMap =
86 std::unordered_map<uint8_t, get_sdr::GetSensorThresholdsResponse>;
87SensorThresholdMap sensorThresholdMap __attribute__((init_priority(101)));
88
Patrick Venture0b02be92018-08-31 11:55:55 -070089int get_bus_for_path(const char* path, char** busname)
90{
Emily Shaffer2ae09b92017-04-05 15:09:41 -070091 return mapper_get_service(bus, path, busname);
92}
Tomd700e762016-09-20 18:24:13 +053093
Emily Shaffer2ae09b92017-04-05 15:09:41 -070094// Use a lookup table to find the interface name of a specific sensor
95// This will be used until an alternative is found. this is the first
96// step for mapping IPMI
Patrick Venture0b02be92018-08-31 11:55:55 -070097int find_openbmc_path(uint8_t num, dbus_interface_t* interface)
98{
Emily Shaffer2ae09b92017-04-05 15:09:41 -070099 int rc;
100
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700101 const auto& sensor_it = ipmi::sensor::sensors.find(num);
102 if (sensor_it == ipmi::sensor::sensors.end())
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700103 {
Adriana Kobylakba23ff72018-09-12 12:58:43 -0500104 // The sensor map does not contain the sensor requested
105 return -EINVAL;
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700106 }
107
108 const auto& info = sensor_it->second;
109
Patrick Williams8451edf2017-06-13 09:01:06 -0500110 char* busname = nullptr;
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700111 rc = get_bus_for_path(info.sensorPath.c_str(), &busname);
Patrick Venture0b02be92018-08-31 11:55:55 -0700112 if (rc < 0)
113 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700114 std::fprintf(stderr, "Failed to get %s busname: %s\n",
115 info.sensorPath.c_str(), busname);
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700116 goto final;
117 }
118
119 interface->sensortype = info.sensorType;
120 strcpy(interface->bus, busname);
121 strcpy(interface->path, info.sensorPath.c_str());
122 // Take the interface name from the beginning of the DbusInterfaceMap. This
123 // works for the Value interface but may not suffice for more complex
124 // sensors.
125 // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103
Patrick Venture0b02be92018-08-31 11:55:55 -0700126 strcpy(interface->interface,
127 info.propertyInterfaces.begin()->first.c_str());
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700128 interface->sensornumber = num;
129
130final:
131 free(busname);
132 return rc;
133}
134
Tomd700e762016-09-20 18:24:13 +0530135/////////////////////////////////////////////////////////////////////
136//
137// Routines used by ipmi commands wanting to interact on the dbus
138//
139/////////////////////////////////////////////////////////////////////
Patrick Venture0b02be92018-08-31 11:55:55 -0700140int set_sensor_dbus_state_s(uint8_t number, const char* method,
141 const char* value)
142{
Tomd700e762016-09-20 18:24:13 +0530143
144 dbus_interface_t a;
145 int r;
146 sd_bus_error error = SD_BUS_ERROR_NULL;
Patrick Venture0b02be92018-08-31 11:55:55 -0700147 sd_bus_message* m = NULL;
Tomd700e762016-09-20 18:24:13 +0530148
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700149 r = find_openbmc_path(number, &a);
Tomd700e762016-09-20 18:24:13 +0530150
Patrick Venture0b02be92018-08-31 11:55:55 -0700151 if (r < 0)
152 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700153 std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
Tomd700e762016-09-20 18:24:13 +0530154 return 0;
155 }
156
Patrick Venture0b02be92018-08-31 11:55:55 -0700157 r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface,
158 method);
159 if (r < 0)
160 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700161 std::fprintf(stderr, "Failed to create a method call: %s",
162 strerror(-r));
Tomd700e762016-09-20 18:24:13 +0530163 goto final;
164 }
165
166 r = sd_bus_message_append(m, "v", "s", value);
Patrick Venture0b02be92018-08-31 11:55:55 -0700167 if (r < 0)
168 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700169 std::fprintf(stderr, "Failed to create a input parameter: %s",
170 strerror(-r));
Tomd700e762016-09-20 18:24:13 +0530171 goto final;
172 }
173
Tomd700e762016-09-20 18:24:13 +0530174 r = sd_bus_call(bus, m, 0, &error, NULL);
Patrick Venture0b02be92018-08-31 11:55:55 -0700175 if (r < 0)
176 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700177 std::fprintf(stderr, "Failed to call the method: %s", strerror(-r));
Tomd700e762016-09-20 18:24:13 +0530178 }
179
180final:
181 sd_bus_error_free(&error);
182 m = sd_bus_message_unref(m);
183
184 return 0;
185}
Patrick Venture0b02be92018-08-31 11:55:55 -0700186int set_sensor_dbus_state_y(uint8_t number, const char* method,
187 const uint8_t value)
188{
Tomd700e762016-09-20 18:24:13 +0530189
190 dbus_interface_t a;
191 int r;
192 sd_bus_error error = SD_BUS_ERROR_NULL;
Patrick Venture0b02be92018-08-31 11:55:55 -0700193 sd_bus_message* m = NULL;
Tomd700e762016-09-20 18:24:13 +0530194
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700195 r = find_openbmc_path(number, &a);
Tomd700e762016-09-20 18:24:13 +0530196
Patrick Venture0b02be92018-08-31 11:55:55 -0700197 if (r < 0)
198 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700199 std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
Tomd700e762016-09-20 18:24:13 +0530200 return 0;
201 }
202
Patrick Venture0b02be92018-08-31 11:55:55 -0700203 r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface,
204 method);
205 if (r < 0)
206 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700207 std::fprintf(stderr, "Failed to create a method call: %s",
208 strerror(-r));
Tomd700e762016-09-20 18:24:13 +0530209 goto final;
210 }
211
212 r = sd_bus_message_append(m, "v", "i", value);
Patrick Venture0b02be92018-08-31 11:55:55 -0700213 if (r < 0)
214 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700215 std::fprintf(stderr, "Failed to create a input parameter: %s",
216 strerror(-r));
Tomd700e762016-09-20 18:24:13 +0530217 goto final;
218 }
219
Tomd700e762016-09-20 18:24:13 +0530220 r = sd_bus_call(bus, m, 0, &error, NULL);
Patrick Venture0b02be92018-08-31 11:55:55 -0700221 if (r < 0)
222 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700223 std::fprintf(stderr, "12 Failed to call the method: %s", strerror(-r));
Tomd700e762016-09-20 18:24:13 +0530224 }
225
226final:
227 sd_bus_error_free(&error);
228 m = sd_bus_message_unref(m);
229
230 return 0;
231}
232
Patrick Venture0b02be92018-08-31 11:55:55 -0700233uint8_t dbus_to_sensor_type(char* p)
234{
Chris Austenac4604a2015-10-13 12:43:27 -0500235
Patrick Venture0b02be92018-08-31 11:55:55 -0700236 sensorTypemap_t* s = g_SensorTypeMap;
237 char r = 0;
238 while (s->number != 0xFF)
239 {
240 if (!strcmp(s->dbusname, p))
241 {
Tom Joseph558184e2017-09-01 13:45:05 +0530242 r = s->typecode;
Patrick Venture0b02be92018-08-31 11:55:55 -0700243 break;
Chris Austenac4604a2015-10-13 12:43:27 -0500244 }
Chris Austen0012e9b2015-10-22 01:37:46 -0500245 s++;
Chris Austenac4604a2015-10-13 12:43:27 -0500246 }
247
Chris Austen0012e9b2015-10-22 01:37:46 -0500248 if (s->number == 0xFF)
249 printf("Failed to find Sensor Type %s\n", p);
Chris Austenac4604a2015-10-13 12:43:27 -0500250
Chris Austen0012e9b2015-10-22 01:37:46 -0500251 return r;
Chris Austenac4604a2015-10-13 12:43:27 -0500252}
253
Patrick Venture0b02be92018-08-31 11:55:55 -0700254uint8_t get_type_from_interface(dbus_interface_t dbus_if)
255{
Chris Austen0012e9b2015-10-22 01:37:46 -0500256
Brad Bishop56003452016-10-05 21:49:19 -0400257 uint8_t type;
Chris Austen0012e9b2015-10-22 01:37:46 -0500258
Chris Austen0012e9b2015-10-22 01:37:46 -0500259 // This is where sensors that do not exist in dbus but do
260 // exist in the host code stop. This should indicate it
261 // is not a supported sensor
Patrick Venture0b02be92018-08-31 11:55:55 -0700262 if (dbus_if.interface[0] == 0)
263 {
264 return 0;
265 }
Chris Austen0012e9b2015-10-22 01:37:46 -0500266
Emily Shaffer71174412017-04-05 15:10:40 -0700267 // Fetch type from interface itself.
268 if (dbus_if.sensortype != 0)
269 {
270 type = dbus_if.sensortype;
Patrick Venture0b02be92018-08-31 11:55:55 -0700271 }
272 else
273 {
Chris Austen0012e9b2015-10-22 01:37:46 -0500274 // Non InventoryItems
Patrick Venture4491a462018-10-13 13:00:42 -0700275 char* p = strrchr(dbus_if.path, '/');
Patrick Venture0b02be92018-08-31 11:55:55 -0700276 type = dbus_to_sensor_type(p + 1);
Chris Austen0012e9b2015-10-22 01:37:46 -0500277 }
278
Brad Bishop56003452016-10-05 21:49:19 -0400279 return type;
Patrick Venture0b02be92018-08-31 11:55:55 -0700280}
Chris Austen0012e9b2015-10-22 01:37:46 -0500281
Emily Shaffer391f3302017-04-03 10:27:08 -0700282// Replaces find_sensor
Patrick Venture0b02be92018-08-31 11:55:55 -0700283uint8_t find_type_for_sensor_number(uint8_t num)
284{
Emily Shaffer391f3302017-04-03 10:27:08 -0700285 int r;
286 dbus_interface_t dbus_if;
Emily Shaffer2ae09b92017-04-05 15:09:41 -0700287 r = find_openbmc_path(num, &dbus_if);
Patrick Venture0b02be92018-08-31 11:55:55 -0700288 if (r < 0)
289 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700290 std::fprintf(stderr, "Could not find sensor %d\n", num);
Lei YU91875f72018-04-03 15:14:49 +0800291 return 0;
Emily Shaffer391f3302017-04-03 10:27:08 -0700292 }
293 return get_type_from_interface(dbus_if);
294}
295
Deepak Kumar Sahua8be7dc2019-05-07 14:26:53 +0000296/**
297 * @brief implements the get sensor type command.
298 * @param - sensorNumber
299 *
300 * @return IPMI completion code plus response data on success.
301 * - sensorType
302 * - eventType
303 **/
304
305ipmi::RspType<uint8_t, // sensorType
306 uint8_t // eventType
307 >
308 ipmiGetSensorType(uint8_t sensorNumber)
Chris Austenac4604a2015-10-13 12:43:27 -0500309{
Deepak Kumar Sahua8be7dc2019-05-07 14:26:53 +0000310 uint8_t sensorType = find_type_for_sensor_number(sensorNumber);
Chris Austenac4604a2015-10-13 12:43:27 -0500311
Deepak Kumar Sahua8be7dc2019-05-07 14:26:53 +0000312 if (sensorType == 0)
Patrick Venture0b02be92018-08-31 11:55:55 -0700313 {
Deepak Kumar Sahua8be7dc2019-05-07 14:26:53 +0000314 return ipmi::responseSensorInvalid();
Chris Austen0012e9b2015-10-22 01:37:46 -0500315 }
316
Deepak Kumar Sahua8be7dc2019-05-07 14:26:53 +0000317 constexpr uint8_t eventType = 0x6F;
318 return ipmi::responseSuccess(sensorType, eventType);
Chris Austenac4604a2015-10-13 12:43:27 -0500319}
320
Patrick Venture0b02be92018-08-31 11:55:55 -0700321const std::set<std::string> analogSensorInterfaces = {
Emily Shaffercc941e12017-06-14 13:06:26 -0700322 "xyz.openbmc_project.Sensor.Value",
Patrick Venturee9a64052017-08-18 19:17:27 -0700323 "xyz.openbmc_project.Control.FanPwm",
Emily Shaffercc941e12017-06-14 13:06:26 -0700324};
325
326bool isAnalogSensor(const std::string& interface)
327{
328 return (analogSensorInterfaces.count(interface));
329}
330
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000331/**
332@brief This command is used to set sensorReading.
333
334@param
335 - sensorNumber
336 - operation
337 - reading
338 - assertOffset0_7
339 - assertOffset8_14
340 - deassertOffset0_7
341 - deassertOffset8_14
342 - eventData1
343 - eventData2
344 - eventData3
345
346@return completion code on success.
347**/
348
349ipmi::RspType<> ipmiSetSensorReading(uint8_t sensorNumber, uint8_t operation,
350 uint8_t reading, uint8_t assertOffset0_7,
351 uint8_t assertOffset8_14,
352 uint8_t deassertOffset0_7,
353 uint8_t deassertOffset8_14,
354 uint8_t eventData1, uint8_t eventData2,
355 uint8_t eventData3)
Tom Josephbe703f72017-03-09 12:34:35 +0530356{
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000357 log<level::DEBUG>("IPMI SET_SENSOR",
358 entry("SENSOR_NUM=0x%02x", sensorNumber));
359
Arun P. Mohanan0634e982021-08-30 15:21:33 +0530360 if (sensorNumber == 0xFF)
361 {
362 return ipmi::responseInvalidFieldRequest();
363 }
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000364 ipmi::sensor::SetSensorReadingReq cmdData;
365
366 cmdData.number = sensorNumber;
367 cmdData.operation = operation;
368 cmdData.reading = reading;
369 cmdData.assertOffset0_7 = assertOffset0_7;
370 cmdData.assertOffset8_14 = assertOffset8_14;
371 cmdData.deassertOffset0_7 = deassertOffset0_7;
372 cmdData.deassertOffset8_14 = deassertOffset8_14;
373 cmdData.eventData1 = eventData1;
374 cmdData.eventData2 = eventData2;
375 cmdData.eventData3 = eventData3;
Tom Josephbe703f72017-03-09 12:34:35 +0530376
377 // Check if the Sensor Number is present
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700378 const auto iter = ipmi::sensor::sensors.find(sensorNumber);
379 if (iter == ipmi::sensor::sensors.end())
Tom Josephbe703f72017-03-09 12:34:35 +0530380 {
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000381 updateSensorRecordFromSSRAESC(&sensorNumber);
382 return ipmi::responseSuccess();
Tom Josephbe703f72017-03-09 12:34:35 +0530383 }
384
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -0500385 try
386 {
Jayanth Othayoth0922bde2018-04-02 07:59:34 -0500387 if (ipmi::sensor::Mutability::Write !=
Patrick Venture0b02be92018-08-31 11:55:55 -0700388 (iter->second.mutability & ipmi::sensor::Mutability::Write))
Jayanth Othayoth0922bde2018-04-02 07:59:34 -0500389 {
390 log<level::ERR>("Sensor Set operation is not allowed",
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000391 entry("SENSOR_NUM=%d", sensorNumber));
392 return ipmi::responseIllegalCommand();
Jayanth Othayoth0922bde2018-04-02 07:59:34 -0500393 }
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000394 auto ipmiRC = iter->second.updateFunc(cmdData, iter->second);
395 return ipmi::response(ipmiRC);
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -0500396 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500397 catch (const InternalFailure& e)
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -0500398 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700399 log<level::ERR>("Set sensor failed",
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000400 entry("SENSOR_NUM=%d", sensorNumber));
Patrick Venture0b02be92018-08-31 11:55:55 -0700401 commit<InternalFailure>();
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000402 return ipmi::responseUnspecifiedError();
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -0500403 }
Tom Joseph82024322017-09-28 20:07:29 +0530404 catch (const std::runtime_error& e)
405 {
406 log<level::ERR>(e.what());
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +0000407 return ipmi::responseUnspecifiedError();
Tom Joseph82024322017-09-28 20:07:29 +0530408 }
Chris Austenac4604a2015-10-13 12:43:27 -0500409}
410
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000411/** @brief implements the get sensor reading command
412 * @param sensorNum - sensor number
413 *
414 * @returns IPMI completion code plus response data
415 * - senReading - sensor reading
416 * - reserved
417 * - readState - sensor reading state enabled
418 * - senScanState - sensor scan state disabled
419 * - allEventMessageState - all Event message state disabled
420 * - assertionStatesLsb - threshold levels states
421 * - assertionStatesMsb - discrete reading sensor states
422 */
423ipmi::RspType<uint8_t, // sensor reading
Tom Joseph3ee668f2018-03-02 19:49:17 +0530424
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000425 uint5_t, // reserved
426 bool, // reading state
Sui Chen4cc42552019-09-11 10:28:35 -0700427 bool, // 0 = sensor scanning state disabled
428 bool, // 0 = all event messages disabled
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000429
430 uint8_t, // threshold levels states
431 uint8_t // discrete reading sensor states
432 >
433 ipmiSensorGetSensorReading(uint8_t sensorNum)
434{
435 if (sensorNum == 0xFF)
436 {
437 return ipmi::responseInvalidFieldRequest();
438 }
439
440 const auto iter = ipmi::sensor::sensors.find(sensorNum);
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700441 if (iter == ipmi::sensor::sensors.end())
Tom Joseph3ee668f2018-03-02 19:49:17 +0530442 {
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000443 return ipmi::responseSensorInvalid();
Tom Joseph3ee668f2018-03-02 19:49:17 +0530444 }
445 if (ipmi::sensor::Mutability::Read !=
Patrick Venture0b02be92018-08-31 11:55:55 -0700446 (iter->second.mutability & ipmi::sensor::Mutability::Read))
Tom Joseph3ee668f2018-03-02 19:49:17 +0530447 {
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000448 return ipmi::responseIllegalCommand();
Tom Joseph3ee668f2018-03-02 19:49:17 +0530449 }
450
451 try
452 {
Sui Chen4cc42552019-09-11 10:28:35 -0700453 ipmi::sensor::GetSensorResponse getResponse =
454 iter->second.getFunc(iter->second);
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000455
Sui Chen4cc42552019-09-11 10:28:35 -0700456 return ipmi::responseSuccess(getResponse.reading, uint5_t(0),
457 getResponse.readingOrStateUnavailable,
458 getResponse.scanningEnabled,
459 getResponse.allEventMessagesEnabled,
460 getResponse.thresholdLevelsStates,
461 getResponse.discreteReadingSensorStates);
Tom Joseph3ee668f2018-03-02 19:49:17 +0530462 }
Brandon Kim9cf85622019-06-19 12:05:08 -0700463#ifdef UPDATE_FUNCTIONAL_ON_FAIL
464 catch (const SensorFunctionalError& e)
465 {
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000466 return ipmi::responseResponseError();
Brandon Kim9cf85622019-06-19 12:05:08 -0700467 }
468#endif
Tom Joseph3ee668f2018-03-02 19:49:17 +0530469 catch (const std::exception& e)
470 {
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +0000471 // Intitilizing with default values
472 constexpr uint8_t senReading = 0;
473 constexpr uint5_t reserved{0};
474 constexpr bool readState = true;
475 constexpr bool senScanState = false;
476 constexpr bool allEventMessageState = false;
477 constexpr uint8_t assertionStatesLsb = 0;
478 constexpr uint8_t assertionStatesMsb = 0;
479
480 return ipmi::responseSuccess(senReading, reserved, readState,
481 senScanState, allEventMessageState,
482 assertionStatesLsb, assertionStatesMsb);
Tom Joseph3ee668f2018-03-02 19:49:17 +0530483 }
484}
485
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300486get_sdr::GetSensorThresholdsResponse
487 getSensorThresholds(ipmi::Context::ptr& ctx, uint8_t sensorNum)
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600488{
William A. Kennington III515bc372020-10-27 16:32:32 -0700489 get_sdr::GetSensorThresholdsResponse resp{};
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530490 constexpr auto warningThreshIntf =
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600491 "xyz.openbmc_project.Sensor.Threshold.Warning";
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530492 constexpr auto criticalThreshIntf =
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600493 "xyz.openbmc_project.Sensor.Threshold.Critical";
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600494
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700495 const auto iter = ipmi::sensor::sensors.find(sensorNum);
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530496 const auto info = iter->second;
497
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300498 std::string service;
499 boost::system::error_code ec;
500 ec = ipmi::getService(ctx, info.sensorInterface, info.sensorPath, service);
501 if (ec)
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530502 {
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300503 return resp;
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530504 }
505
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300506 ipmi::PropertyMap warnThresholds;
507 ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
508 warningThreshIntf, warnThresholds);
509 if (!ec)
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530510 {
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300511 double warnLow = std::visit(ipmi::VariantToDoubleVisitor(),
512 warnThresholds["WarningLow"]);
513 double warnHigh = std::visit(ipmi::VariantToDoubleVisitor(),
514 warnThresholds["WarningHigh"]);
515
516 if (std::isfinite(warnLow))
517 {
518 warnLow *= std::pow(10, info.scale - info.exponentR);
519 resp.lowerNonCritical = static_cast<uint8_t>(
520 (warnLow - info.scaledOffset) / info.coefficientM);
521 resp.validMask |= static_cast<uint8_t>(
522 ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK);
523 }
524
525 if (std::isfinite(warnHigh))
526 {
527 warnHigh *= std::pow(10, info.scale - info.exponentR);
528 resp.upperNonCritical = static_cast<uint8_t>(
529 (warnHigh - info.scaledOffset) / info.coefficientM);
530 resp.validMask |= static_cast<uint8_t>(
531 ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK);
532 }
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530533 }
534
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300535 ipmi::PropertyMap critThresholds;
536 ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
537 criticalThreshIntf, critThresholds);
538 if (!ec)
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530539 {
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300540 double critLow = std::visit(ipmi::VariantToDoubleVisitor(),
541 critThresholds["CriticalLow"]);
542 double critHigh = std::visit(ipmi::VariantToDoubleVisitor(),
543 critThresholds["CriticalHigh"]);
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530544
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300545 if (std::isfinite(critLow))
546 {
547 critLow *= std::pow(10, info.scale - info.exponentR);
548 resp.lowerCritical = static_cast<uint8_t>(
549 (critLow - info.scaledOffset) / info.coefficientM);
550 resp.validMask |= static_cast<uint8_t>(
551 ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK);
552 }
553
554 if (std::isfinite(critHigh))
555 {
556 critHigh *= std::pow(10, info.scale - info.exponentR);
557 resp.upperCritical = static_cast<uint8_t>(
558 (critHigh - info.scaledOffset) / info.coefficientM);
559 resp.validMask |= static_cast<uint8_t>(
560 ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK);
561 }
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530562 }
jayaprakash Mutyala996c9792019-05-03 15:56:48 +0000563
564 return resp;
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530565}
566
jayaprakash Mutyala996c9792019-05-03 15:56:48 +0000567/** @brief implements the get sensor thresholds command
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300568 * @param ctx - IPMI context pointer
jayaprakash Mutyala996c9792019-05-03 15:56:48 +0000569 * @param sensorNum - sensor number
570 *
571 * @returns IPMI completion code plus response data
572 * - validMask - threshold mask
573 * - lower non-critical threshold - IPMI messaging state
574 * - lower critical threshold - link authentication state
575 * - lower non-recoverable threshold - callback state
576 * - upper non-critical threshold
577 * - upper critical
578 * - upper non-recoverable
579 */
580ipmi::RspType<uint8_t, // validMask
581 uint8_t, // lowerNonCritical
582 uint8_t, // lowerCritical
583 uint8_t, // lowerNonRecoverable
584 uint8_t, // upperNonCritical
585 uint8_t, // upperCritical
586 uint8_t // upperNonRecoverable
587 >
Konstantin Aladyshev89a83b62021-05-12 18:59:27 +0300588 ipmiSensorGetSensorThresholds(ipmi::Context::ptr& ctx, uint8_t sensorNum)
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530589{
590 constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value";
591
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700592 const auto iter = ipmi::sensor::sensors.find(sensorNum);
593 if (iter == ipmi::sensor::sensors.end())
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600594 {
jayaprakash Mutyala996c9792019-05-03 15:56:48 +0000595 return ipmi::responseSensorInvalid();
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600596 }
597
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530598 const auto info = iter->second;
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600599
Patrick Venture0b02be92018-08-31 11:55:55 -0700600 // Proceed only if the sensor value interface is implemented.
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530601 if (info.propertyInterfaces.find(valueInterface) ==
602 info.propertyInterfaces.end())
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600603 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700604 // return with valid mask as 0
jayaprakash Mutyala996c9792019-05-03 15:56:48 +0000605 return ipmi::responseSuccess();
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600606 }
607
Lei YU14a47812021-09-17 15:58:04 +0800608 auto it = sensorThresholdMap.find(sensorNum);
609 if (it == sensorThresholdMap.end())
610 {
611 sensorThresholdMap[sensorNum] = getSensorThresholds(ctx, sensorNum);
612 }
613
614 const auto& resp = sensorThresholdMap[sensorNum];
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600615
jayaprakash Mutyala996c9792019-05-03 15:56:48 +0000616 return ipmi::responseSuccess(resp.validMask, resp.lowerNonCritical,
617 resp.lowerCritical, resp.lowerNonRecoverable,
618 resp.upperNonCritical, resp.upperCritical,
619 resp.upperNonRecoverable);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600620}
621
Lotus Xuf93da662021-10-18 17:20:06 +0800622/** @brief implements the Set Sensor threshold command
623 * @param sensorNumber - sensor number
624 * @param lowerNonCriticalThreshMask
625 * @param lowerCriticalThreshMask
626 * @param lowerNonRecovThreshMask
627 * @param upperNonCriticalThreshMask
628 * @param upperCriticalThreshMask
629 * @param upperNonRecovThreshMask
630 * @param reserved
631 * @param lowerNonCritical - lower non-critical threshold
632 * @param lowerCritical - Lower critical threshold
633 * @param lowerNonRecoverable - Lower non recovarable threshold
634 * @param upperNonCritical - Upper non-critical threshold
635 * @param upperCritical - Upper critical
636 * @param upperNonRecoverable - Upper Non-recoverable
637 *
638 * @returns IPMI completion code
639 */
640ipmi::RspType<> ipmiSenSetSensorThresholds(
641 ipmi::Context::ptr& ctx, uint8_t sensorNum, bool lowerNonCriticalThreshMask,
642 bool lowerCriticalThreshMask, bool lowerNonRecovThreshMask,
643 bool upperNonCriticalThreshMask, bool upperCriticalThreshMask,
644 bool upperNonRecovThreshMask, uint2_t reserved, uint8_t lowerNonCritical,
645 uint8_t lowerCritical, uint8_t lowerNonRecoverable,
646 uint8_t upperNonCritical, uint8_t upperCritical,
647 uint8_t upperNonRecoverable)
648{
649 if (reserved)
650 {
651 return ipmi::responseInvalidFieldRequest();
652 }
653
654 // lower nc and upper nc not suppported on any sensor
655 if (lowerNonRecovThreshMask || upperNonRecovThreshMask)
656 {
657 return ipmi::responseInvalidFieldRequest();
658 }
659
660 // if none of the threshold mask are set, nothing to do
661 if (!(lowerNonCriticalThreshMask | lowerCriticalThreshMask |
662 lowerNonRecovThreshMask | upperNonCriticalThreshMask |
663 upperCriticalThreshMask | upperNonRecovThreshMask))
664 {
665 return ipmi::responseSuccess();
666 }
667
668 constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value";
669
670 const auto iter = ipmi::sensor::sensors.find(sensorNum);
671 if (iter == ipmi::sensor::sensors.end())
672 {
673 return ipmi::responseSensorInvalid();
674 }
675
676 const auto& info = iter->second;
677
678 // Proceed only if the sensor value interface is implemented.
679 if (info.propertyInterfaces.find(valueInterface) ==
680 info.propertyInterfaces.end())
681 {
682 // return with valid mask as 0
683 return ipmi::responseSuccess();
684 }
685
686 constexpr auto warningThreshIntf =
687 "xyz.openbmc_project.Sensor.Threshold.Warning";
688 constexpr auto criticalThreshIntf =
689 "xyz.openbmc_project.Sensor.Threshold.Critical";
690
691 std::string service;
692 boost::system::error_code ec;
693 ec = ipmi::getService(ctx, info.sensorInterface, info.sensorPath, service);
694 if (ec)
695 {
696 return ipmi::responseResponseError();
697 }
698 // store a vector of property name, value to set, and interface
699 std::vector<std::tuple<std::string, uint8_t, std::string>> thresholdsToSet;
700
701 // define the indexes of the tuple
702 constexpr uint8_t propertyName = 0;
703 constexpr uint8_t thresholdValue = 1;
704 constexpr uint8_t interface = 2;
705 // verifiy all needed fields are present
706 if (lowerCriticalThreshMask || upperCriticalThreshMask)
707 {
708
709 ipmi::PropertyMap findThreshold;
710 ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
711 criticalThreshIntf, findThreshold);
712
713 if (!ec)
714 {
715 if (lowerCriticalThreshMask)
716 {
717 auto findLower = findThreshold.find("CriticalLow");
718 if (findLower == findThreshold.end())
719 {
720 return ipmi::responseInvalidFieldRequest();
721 }
722 thresholdsToSet.emplace_back("CriticalLow", lowerCritical,
723 criticalThreshIntf);
724 }
725 if (upperCriticalThreshMask)
726 {
727 auto findUpper = findThreshold.find("CriticalHigh");
728 if (findUpper == findThreshold.end())
729 {
730 return ipmi::responseInvalidFieldRequest();
731 }
732 thresholdsToSet.emplace_back("CriticalHigh", upperCritical,
733 criticalThreshIntf);
734 }
735 }
736 }
737 if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask)
738 {
739 ipmi::PropertyMap findThreshold;
740 ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
741 warningThreshIntf, findThreshold);
742
743 if (!ec)
744 {
745 if (lowerNonCriticalThreshMask)
746 {
747 auto findLower = findThreshold.find("WarningLow");
748 if (findLower == findThreshold.end())
749 {
750 return ipmi::responseInvalidFieldRequest();
751 }
752 thresholdsToSet.emplace_back("WarningLow", lowerNonCritical,
753 warningThreshIntf);
754 }
755 if (upperNonCriticalThreshMask)
756 {
757 auto findUpper = findThreshold.find("WarningHigh");
758 if (findUpper == findThreshold.end())
759 {
760 return ipmi::responseInvalidFieldRequest();
761 }
762 thresholdsToSet.emplace_back("WarningHigh", upperNonCritical,
763 warningThreshIntf);
764 }
765 }
766 }
767 for (const auto& property : thresholdsToSet)
768 {
769 // from section 36.3 in the IPMI Spec, assume all linear
770 double valueToSet =
771 ((info.coefficientM * std::get<thresholdValue>(property)) +
772 (info.scaledOffset * std::pow(10.0, info.scale))) *
773 std::pow(10.0, info.exponentR);
774 ipmi::setDbusProperty(
775 ctx, service, info.sensorPath, std::get<interface>(property),
776 std::get<propertyName>(property), ipmi::Value(valueToSet));
777 }
778
Lei YU14a47812021-09-17 15:58:04 +0800779 // Invalidate the cache
780 sensorThresholdMap.erase(sensorNum);
Lotus Xuf93da662021-10-18 17:20:06 +0800781 return ipmi::responseSuccess();
782}
783
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000784/** @brief implements the get SDR Info command
785 * @param count - Operation
786 *
787 * @returns IPMI completion code plus response data
788 * - sdrCount - sensor/SDR count
789 * - lunsAndDynamicPopulation - static/Dynamic sensor population flag
790 */
791ipmi::RspType<uint8_t, // respcount
792 uint8_t // dynamic population flags
793 >
794 ipmiSensorGetDeviceSdrInfo(std::optional<uint8_t> count)
Emily Shafferd06e0e72017-04-05 09:08:57 -0700795{
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000796 uint8_t sdrCount;
797 // multiple LUNs not supported.
798 constexpr uint8_t lunsAndDynamicPopulation = 1;
799 constexpr uint8_t getSdrCount = 0x01;
800 constexpr uint8_t getSensorCount = 0x00;
801
802 if (count.value_or(0) == getSdrCount)
Emily Shafferd06e0e72017-04-05 09:08:57 -0700803 {
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000804 // Get SDR count. This returns the total number of SDRs in the device.
Patrick Venture87fd2cd2019-08-19 12:07:18 -0700805 const auto& entityRecords =
806 ipmi::sensor::EntityInfoMapContainer::getContainer()
807 ->getIpmiEntityRecords();
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700808 sdrCount =
809 ipmi::sensor::sensors.size() + frus.size() + entityRecords.size();
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000810 }
811 else if (count.value_or(0) == getSensorCount)
812 {
813 // Get Sensor count. This returns the number of sensors
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700814 sdrCount = ipmi::sensor::sensors.size();
Emily Shafferd06e0e72017-04-05 09:08:57 -0700815 }
816 else
817 {
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000818 return ipmi::responseInvalidCommandOnLun();
Emily Shafferd06e0e72017-04-05 09:08:57 -0700819 }
820
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000821 return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation);
Emily Shafferd06e0e72017-04-05 09:08:57 -0700822}
823
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000824/** @brief implements the reserve SDR command
825 * @returns IPMI completion code plus response data
826 * - reservationID - reservation ID
827 */
828ipmi::RspType<uint16_t> ipmiSensorReserveSdr()
Emily Shaffera344afc2017-04-13 15:09:39 -0700829{
830 // A constant reservation ID is okay until we implement add/remove SDR.
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000831 constexpr uint16_t reservationID = 1;
Emily Shaffera344afc2017-04-13 15:09:39 -0700832
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000833 return ipmi::responseSuccess(reservationID);
Emily Shaffera344afc2017-04-13 15:09:39 -0700834}
Chris Austenac4604a2015-10-13 12:43:27 -0500835
Patrick Venture0b02be92018-08-31 11:55:55 -0700836void setUnitFieldsForObject(const ipmi::sensor::Info* info,
837 get_sdr::SensorDataFullRecordBody* body)
Emily Shaffercc941e12017-06-14 13:06:26 -0700838{
Tom Josephdc212b22018-02-16 09:59:57 +0530839 namespace server = sdbusplus::xyz::openbmc_project::Sensor::server;
840 try
Emily Shaffercc941e12017-06-14 13:06:26 -0700841 {
Tom Josephdc212b22018-02-16 09:59:57 +0530842 auto unit = server::Value::convertUnitFromString(info->unit);
843 // Unit strings defined in
844 // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml
845 switch (unit)
Emily Shaffercc941e12017-06-14 13:06:26 -0700846 {
Tom Josephdc212b22018-02-16 09:59:57 +0530847 case server::Value::Unit::DegreesC:
848 body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C;
849 break;
850 case server::Value::Unit::RPMS:
Kirill Pakhomov812e44c2018-10-22 16:25:35 +0300851 body->sensor_units_2_base = get_sdr::SENSOR_UNIT_RPM;
Tom Josephdc212b22018-02-16 09:59:57 +0530852 break;
853 case server::Value::Unit::Volts:
854 body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS;
855 break;
856 case server::Value::Unit::Meters:
857 body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS;
858 break;
859 case server::Value::Unit::Amperes:
860 body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES;
861 break;
862 case server::Value::Unit::Joules:
863 body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES;
864 break;
865 case server::Value::Unit::Watts:
866 body->sensor_units_2_base = get_sdr::SENSOR_UNIT_WATTS;
867 break;
868 default:
869 // Cannot be hit.
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700870 std::fprintf(stderr, "Unknown value unit type: = %s\n",
871 info->unit.c_str());
Emily Shaffercc941e12017-06-14 13:06:26 -0700872 }
873 }
Patrick Venture64678b82018-10-13 13:11:32 -0700874 catch (const sdbusplus::exception::InvalidEnumString& e)
Emily Shaffercc941e12017-06-14 13:06:26 -0700875 {
Tom Josephdc212b22018-02-16 09:59:57 +0530876 log<level::WARNING>("Warning: no unit provided for sensor!");
Emily Shaffercc941e12017-06-14 13:06:26 -0700877 }
Emily Shaffercc941e12017-06-14 13:06:26 -0700878}
879
Patrick Venture0b02be92018-08-31 11:55:55 -0700880ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody* body,
881 const ipmi::sensor::Info* info,
Emily Shafferbbef71c2017-05-08 16:36:17 -0700882 ipmi_data_len_t data_len)
883{
884 /* Functional sensor case */
Emily Shaffercc941e12017-06-14 13:06:26 -0700885 if (isAnalogSensor(info->propertyInterfaces.begin()->first))
Emily Shafferbbef71c2017-05-08 16:36:17 -0700886 {
Tony Leec5324252019-10-31 17:24:16 +0800887 body->sensor_units_1 = info->sensorUnits1; // default is 0. unsigned, no
888 // rate, no modifier, not a %
Emily Shafferbbef71c2017-05-08 16:36:17 -0700889 /* Unit info */
Tom Josephdc212b22018-02-16 09:59:57 +0530890 setUnitFieldsForObject(info, body);
Emily Shaffer10f49592017-05-10 12:01:10 -0700891
892 get_sdr::body::set_b(info->coefficientB, body);
893 get_sdr::body::set_m(info->coefficientM, body);
894 get_sdr::body::set_b_exp(info->exponentB, body);
Tom Josephdc212b22018-02-16 09:59:57 +0530895 get_sdr::body::set_r_exp(info->exponentR, body);
Emily Shafferbbef71c2017-05-08 16:36:17 -0700896
Emily Shafferbbef71c2017-05-08 16:36:17 -0700897 get_sdr::body::set_id_type(0b00, body); // 00 = unicode
Emily Shafferbbef71c2017-05-08 16:36:17 -0700898 }
899
Tom Joseph96423912018-01-25 00:14:34 +0530900 /* ID string */
Jeremy Kerrbe4ffa82020-08-10 16:17:37 +0800901 auto id_string = info->sensorName;
902
903 if (id_string.empty())
904 {
905 id_string = info->sensorNameFunc(*info);
906 }
Tom Joseph96423912018-01-25 00:14:34 +0530907
908 if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH)
909 {
910 get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body);
911 }
912 else
913 {
914 get_sdr::body::set_id_strlen(id_string.length(), body);
915 }
916 strncpy(body->id_string, id_string.c_str(),
917 get_sdr::body::get_id_strlen(body));
918
Emily Shafferbbef71c2017-05-08 16:36:17 -0700919 return IPMI_CC_OK;
920};
921
Ratan Guptae0cc8552018-01-22 14:23:04 +0530922ipmi_ret_t ipmi_fru_get_sdr(ipmi_request_t request, ipmi_response_t response,
923 ipmi_data_len_t data_len)
924{
925 auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request);
926 auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response);
Patrick Venture0b02be92018-08-31 11:55:55 -0700927 get_sdr::SensorDataFruRecord record{};
Ratan Guptae0cc8552018-01-22 14:23:04 +0530928 auto dataLength = 0;
929
930 auto fru = frus.begin();
Patrick Venture0b02be92018-08-31 11:55:55 -0700931 uint8_t fruID{};
Ratan Guptae0cc8552018-01-22 14:23:04 +0530932 auto recordID = get_sdr::request::get_record_id(req);
933
934 fruID = recordID - FRU_RECORD_ID_START;
935 fru = frus.find(fruID);
936 if (fru == frus.end())
937 {
938 return IPMI_CC_SENSOR_INVALID;
939 }
940
941 /* Header */
942 get_sdr::header::set_record_id(recordID, &(record.header));
943 record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1
944 record.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD;
945 record.header.record_length = sizeof(record.key) + sizeof(record.body);
946
947 /* Key */
948 record.key.fruID = fruID;
949 record.key.accessLun |= IPMI_LOGICAL_FRU;
950 record.key.deviceAddress = BMCSlaveAddress;
951
952 /* Body */
953 record.body.entityID = fru->second[0].entityID;
954 record.body.entityInstance = fru->second[0].entityInstance;
955 record.body.deviceType = fruInventoryDevice;
956 record.body.deviceTypeModifier = IPMIFruInventory;
957
958 /* Device ID string */
Patrick Venture0b02be92018-08-31 11:55:55 -0700959 auto deviceID =
960 fru->second[0].path.substr(fru->second[0].path.find_last_of('/') + 1,
961 fru->second[0].path.length());
Ratan Guptae0cc8552018-01-22 14:23:04 +0530962
963 if (deviceID.length() > get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH)
964 {
965 get_sdr::body::set_device_id_strlen(
Patrick Venture0b02be92018-08-31 11:55:55 -0700966 get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH, &(record.body));
Ratan Guptae0cc8552018-01-22 14:23:04 +0530967 }
968 else
969 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700970 get_sdr::body::set_device_id_strlen(deviceID.length(), &(record.body));
Ratan Guptae0cc8552018-01-22 14:23:04 +0530971 }
972
973 strncpy(record.body.deviceID, deviceID.c_str(),
974 get_sdr::body::get_device_id_strlen(&(record.body)));
975
976 if (++fru == frus.end())
977 {
Jaghathiswari Rankappagounder Natarajan9c118942019-02-12 13:22:55 -0800978 // we have reached till end of fru, so assign the next record id to
979 // 512(Max fru ID = 511) + Entity Record ID(may start with 0).
Patrick Venture87fd2cd2019-08-19 12:07:18 -0700980 const auto& entityRecords =
981 ipmi::sensor::EntityInfoMapContainer::getContainer()
982 ->getIpmiEntityRecords();
Jaghathiswari Rankappagounder Natarajan9c118942019-02-12 13:22:55 -0800983 auto next_record_id =
Patrick Venture83a0b842019-07-19 18:37:15 -0700984 (entityRecords.size())
985 ? entityRecords.begin()->first + ENTITY_RECORD_ID_START
986 : END_OF_RECORD;
Jaghathiswari Rankappagounder Natarajan9c118942019-02-12 13:22:55 -0800987 get_sdr::response::set_next_record_id(next_record_id, resp);
988 }
989 else
990 {
991 get_sdr::response::set_next_record_id(
992 (FRU_RECORD_ID_START + fru->first), resp);
993 }
994
995 // Check for invalid offset size
996 if (req->offset > sizeof(record))
997 {
998 return IPMI_CC_PARM_OUT_OF_RANGE;
999 }
1000
1001 dataLength = std::min(static_cast<size_t>(req->bytes_to_read),
1002 sizeof(record) - req->offset);
1003
1004 std::memcpy(resp->record_data,
1005 reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength);
1006
1007 *data_len = dataLength;
1008 *data_len += 2; // additional 2 bytes for next record ID
1009
1010 return IPMI_CC_OK;
1011}
1012
1013ipmi_ret_t ipmi_entity_get_sdr(ipmi_request_t request, ipmi_response_t response,
1014 ipmi_data_len_t data_len)
1015{
1016 auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request);
1017 auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response);
1018 get_sdr::SensorDataEntityRecord record{};
1019 auto dataLength = 0;
1020
Patrick Venture87fd2cd2019-08-19 12:07:18 -07001021 const auto& entityRecords =
1022 ipmi::sensor::EntityInfoMapContainer::getContainer()
1023 ->getIpmiEntityRecords();
Patrick Venture83a0b842019-07-19 18:37:15 -07001024 auto entity = entityRecords.begin();
Jaghathiswari Rankappagounder Natarajan9c118942019-02-12 13:22:55 -08001025 uint8_t entityRecordID;
1026 auto recordID = get_sdr::request::get_record_id(req);
1027
1028 entityRecordID = recordID - ENTITY_RECORD_ID_START;
Patrick Venture83a0b842019-07-19 18:37:15 -07001029 entity = entityRecords.find(entityRecordID);
1030 if (entity == entityRecords.end())
Jaghathiswari Rankappagounder Natarajan9c118942019-02-12 13:22:55 -08001031 {
1032 return IPMI_CC_SENSOR_INVALID;
1033 }
1034
1035 /* Header */
1036 get_sdr::header::set_record_id(recordID, &(record.header));
1037 record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1
1038 record.header.record_type = get_sdr::SENSOR_DATA_ENTITY_RECORD;
1039 record.header.record_length = sizeof(record.key) + sizeof(record.body);
1040
1041 /* Key */
1042 record.key.containerEntityId = entity->second.containerEntityId;
1043 record.key.containerEntityInstance = entity->second.containerEntityInstance;
1044 get_sdr::key::set_flags(entity->second.isList, entity->second.isLinked,
1045 &(record.key));
1046 record.key.entityId1 = entity->second.containedEntities[0].first;
1047 record.key.entityInstance1 = entity->second.containedEntities[0].second;
1048
1049 /* Body */
1050 record.body.entityId2 = entity->second.containedEntities[1].first;
1051 record.body.entityInstance2 = entity->second.containedEntities[1].second;
1052 record.body.entityId3 = entity->second.containedEntities[2].first;
1053 record.body.entityInstance3 = entity->second.containedEntities[2].second;
1054 record.body.entityId4 = entity->second.containedEntities[3].first;
1055 record.body.entityInstance4 = entity->second.containedEntities[3].second;
1056
Patrick Venture83a0b842019-07-19 18:37:15 -07001057 if (++entity == entityRecords.end())
Jaghathiswari Rankappagounder Natarajan9c118942019-02-12 13:22:55 -08001058 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001059 get_sdr::response::set_next_record_id(END_OF_RECORD,
1060 resp); // last record
Ratan Guptae0cc8552018-01-22 14:23:04 +05301061 }
1062 else
1063 {
1064 get_sdr::response::set_next_record_id(
Jaghathiswari Rankappagounder Natarajan9c118942019-02-12 13:22:55 -08001065 (ENTITY_RECORD_ID_START + entity->first), resp);
Ratan Guptae0cc8552018-01-22 14:23:04 +05301066 }
1067
Emily Shaffer0fbdbce2018-09-27 09:30:41 -07001068 // Check for invalid offset size
1069 if (req->offset > sizeof(record))
Ratan Guptae0cc8552018-01-22 14:23:04 +05301070 {
Emily Shaffer0fbdbce2018-09-27 09:30:41 -07001071 return IPMI_CC_PARM_OUT_OF_RANGE;
Ratan Guptae0cc8552018-01-22 14:23:04 +05301072 }
1073
Emily Shaffer0fbdbce2018-09-27 09:30:41 -07001074 dataLength = std::min(static_cast<size_t>(req->bytes_to_read),
1075 sizeof(record) - req->offset);
Ratan Guptae0cc8552018-01-22 14:23:04 +05301076
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001077 std::memcpy(resp->record_data,
Jason M. Bills1cd85962018-10-05 12:04:01 -07001078 reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength);
Ratan Guptae0cc8552018-01-22 14:23:04 +05301079
1080 *data_len = dataLength;
1081 *data_len += 2; // additional 2 bytes for next record ID
1082
1083 return IPMI_CC_OK;
1084}
1085
Emily Shafferbbef71c2017-05-08 16:36:17 -07001086ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1087 ipmi_request_t request, ipmi_response_t response,
1088 ipmi_data_len_t data_len, ipmi_context_t context)
1089{
1090 ipmi_ret_t ret = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001091 get_sdr::GetSdrReq* req = (get_sdr::GetSdrReq*)request;
1092 get_sdr::GetSdrResp* resp = (get_sdr::GetSdrResp*)response;
Patrick Venture38426dd2019-07-30 15:22:29 -07001093
1094 // Note: we use an iterator so we can provide the next ID at the end of
1095 // the call.
Patrick Venturedb0cbe62019-09-09 14:47:22 -07001096 auto sensor = ipmi::sensor::sensors.begin();
Patrick Venture38426dd2019-07-30 15:22:29 -07001097 auto recordID = get_sdr::request::get_record_id(req);
1098
1099 // At the beginning of a scan, the host side will send us id=0.
1100 if (recordID != 0)
Emily Shafferbbef71c2017-05-08 16:36:17 -07001101 {
Patrick Venture38426dd2019-07-30 15:22:29 -07001102 // recordID 0 to 255 means it is a FULL record.
1103 // recordID 256 to 511 means it is a FRU record.
1104 // recordID greater then 511 means it is a Entity Association
1105 // record. Currently we are supporting three record types: FULL
1106 // record, FRU record and Enttiy Association record.
1107 if (recordID >= ENTITY_RECORD_ID_START)
Emily Shafferbbef71c2017-05-08 16:36:17 -07001108 {
Patrick Venture38426dd2019-07-30 15:22:29 -07001109 return ipmi_entity_get_sdr(request, response, data_len);
Emily Shafferbbef71c2017-05-08 16:36:17 -07001110 }
Patrick Venture38426dd2019-07-30 15:22:29 -07001111 else if (recordID >= FRU_RECORD_ID_START &&
1112 recordID < ENTITY_RECORD_ID_START)
Jaghathiswari Rankappagounder Natarajan0780df12019-02-06 15:29:24 -08001113 {
Patrick Venture38426dd2019-07-30 15:22:29 -07001114 return ipmi_fru_get_sdr(request, response, data_len);
Emily Shafferbbef71c2017-05-08 16:36:17 -07001115 }
1116 else
1117 {
Patrick Venturedb0cbe62019-09-09 14:47:22 -07001118 sensor = ipmi::sensor::sensors.find(recordID);
1119 if (sensor == ipmi::sensor::sensors.end())
Patrick Venture38426dd2019-07-30 15:22:29 -07001120 {
1121 return IPMI_CC_SENSOR_INVALID;
1122 }
Emily Shafferbbef71c2017-05-08 16:36:17 -07001123 }
Emily Shafferbbef71c2017-05-08 16:36:17 -07001124 }
1125
Patrick Venture38426dd2019-07-30 15:22:29 -07001126 uint8_t sensor_id = sensor->first;
1127
Lei YU14a47812021-09-17 15:58:04 +08001128 auto it = sdrCacheMap.find(sensor_id);
1129 if (it == sdrCacheMap.end())
Patrick Venture38426dd2019-07-30 15:22:29 -07001130 {
Lei YU14a47812021-09-17 15:58:04 +08001131 /* Header */
1132 get_sdr::SensorDataFullRecord record = {0};
1133 get_sdr::header::set_record_id(sensor_id, &(record.header));
1134 record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1
1135 record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD;
1136 record.header.record_length = sizeof(record.key) + sizeof(record.body);
1137
1138 /* Key */
1139 get_sdr::key::set_owner_id_bmc(&(record.key));
1140 record.key.sensor_number = sensor_id;
1141
1142 /* Body */
1143 record.body.entity_id = sensor->second.entityType;
1144 record.body.sensor_type = sensor->second.sensorType;
1145 record.body.event_reading_type = sensor->second.sensorReadingType;
1146 record.body.entity_instance = sensor->second.instance;
1147 if (ipmi::sensor::Mutability::Write ==
1148 (sensor->second.mutability & ipmi::sensor::Mutability::Write))
1149 {
1150 get_sdr::body::init_settable_state(true, &(record.body));
1151 }
1152
1153 // Set the type-specific details given the DBus interface
1154 populate_record_from_dbus(&(record.body), &(sensor->second), data_len);
1155 sdrCacheMap[sensor_id] = std::move(record);
Patrick Venture38426dd2019-07-30 15:22:29 -07001156 }
1157
Lei YU14a47812021-09-17 15:58:04 +08001158 const auto& record = sdrCacheMap[sensor_id];
Patrick Venture38426dd2019-07-30 15:22:29 -07001159
Patrick Venturedb0cbe62019-09-09 14:47:22 -07001160 if (++sensor == ipmi::sensor::sensors.end())
Patrick Venture38426dd2019-07-30 15:22:29 -07001161 {
1162 // we have reached till end of sensor, so assign the next record id
1163 // to 256(Max Sensor ID = 255) + FRU ID(may start with 0).
1164 auto next_record_id = (frus.size())
1165 ? frus.begin()->first + FRU_RECORD_ID_START
1166 : END_OF_RECORD;
1167
1168 get_sdr::response::set_next_record_id(next_record_id, resp);
1169 }
1170 else
1171 {
1172 get_sdr::response::set_next_record_id(sensor->first, resp);
1173 }
1174
1175 if (req->offset > sizeof(record))
1176 {
1177 return IPMI_CC_PARM_OUT_OF_RANGE;
1178 }
1179
1180 // data_len will ultimately be the size of the record, plus
1181 // the size of the next record ID:
1182 *data_len = std::min(static_cast<size_t>(req->bytes_to_read),
1183 sizeof(record) - req->offset);
1184
1185 std::memcpy(resp->record_data,
Lei YU14a47812021-09-17 15:58:04 +08001186 reinterpret_cast<const uint8_t*>(&record) + req->offset,
1187 *data_len);
Patrick Venture38426dd2019-07-30 15:22:29 -07001188
1189 // data_len should include the LSB and MSB:
1190 *data_len +=
1191 sizeof(resp->next_record_id_lsb) + sizeof(resp->next_record_id_msb);
1192
Emily Shafferbbef71c2017-05-08 16:36:17 -07001193 return ret;
1194}
1195
Jia, Chunhui3342a8e2018-12-29 13:32:26 +08001196static bool isFromSystemChannel()
1197{
1198 // TODO we could not figure out where the request is from based on IPMI
1199 // command handler parameters. because of it, we can not differentiate
1200 // request from SMS/SMM or IPMB channel
1201 return true;
1202}
1203
1204ipmi_ret_t ipmicmdPlatformEvent(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1205 ipmi_request_t request,
1206 ipmi_response_t response,
1207 ipmi_data_len_t dataLen, ipmi_context_t context)
1208{
1209 uint16_t generatorID;
1210 size_t count;
1211 bool assert = true;
1212 std::string sensorPath;
1213 size_t paraLen = *dataLen;
1214 PlatformEventRequest* req;
1215 *dataLen = 0;
1216
1217 if ((paraLen < selSystemEventSizeWith1Bytes) ||
1218 (paraLen > selSystemEventSizeWith3Bytes))
1219 {
1220 return IPMI_CC_REQ_DATA_LEN_INVALID;
1221 }
1222
1223 if (isFromSystemChannel())
1224 { // first byte for SYSTEM Interface is Generator ID
1225 // +1 to get common struct
1226 req = reinterpret_cast<PlatformEventRequest*>((uint8_t*)request + 1);
1227 // Capture the generator ID
1228 generatorID = *reinterpret_cast<uint8_t*>(request);
1229 // Platform Event usually comes from other firmware, like BIOS.
1230 // Unlike BMC sensor, it does not have BMC DBUS sensor path.
1231 sensorPath = "System";
1232 }
1233 else
1234 {
1235 req = reinterpret_cast<PlatformEventRequest*>(request);
1236 // TODO GenratorID for IPMB is combination of RqSA and RqLUN
1237 generatorID = 0xff;
1238 sensorPath = "IPMB";
1239 }
1240 // Content of event data field depends on sensor class.
1241 // When data0 bit[5:4] is non-zero, valid data counts is 3.
1242 // When data0 bit[7:6] is non-zero, valid data counts is 2.
1243 if (((req->data[0] & byte3EnableMask) != 0 &&
1244 paraLen < selSystemEventSizeWith3Bytes) ||
1245 ((req->data[0] & byte2EnableMask) != 0 &&
1246 paraLen < selSystemEventSizeWith2Bytes))
1247 {
1248 return IPMI_CC_REQ_DATA_LEN_INVALID;
1249 }
1250
1251 // Count bytes of Event Data
1252 if ((req->data[0] & byte3EnableMask) != 0)
1253 {
1254 count = 3;
1255 }
1256 else if ((req->data[0] & byte2EnableMask) != 0)
1257 {
1258 count = 2;
1259 }
1260 else
1261 {
1262 count = 1;
1263 }
1264 assert = req->eventDirectionType & directionMask ? false : true;
1265 std::vector<uint8_t> eventData(req->data, req->data + count);
1266
1267 sdbusplus::bus::bus dbus(bus);
1268 std::string service =
1269 ipmi::getService(dbus, ipmiSELAddInterface, ipmiSELPath);
1270 sdbusplus::message::message writeSEL = dbus.new_method_call(
1271 service.c_str(), ipmiSELPath, ipmiSELAddInterface, "IpmiSelAdd");
1272 writeSEL.append(ipmiSELAddMessage, sensorPath, eventData, assert,
1273 generatorID);
1274 try
1275 {
1276 dbus.call(writeSEL);
1277 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -05001278 catch (const sdbusplus::exception_t& e)
Jia, Chunhui3342a8e2018-12-29 13:32:26 +08001279 {
1280 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
1281 return IPMI_CC_UNSPECIFIED_ERROR;
1282 }
1283 return IPMI_CC_OK;
1284}
1285
Chris Austenac4604a2015-10-13 12:43:27 -05001286void register_netfn_sen_functions()
1287{
Willy Tud351a722021-08-12 14:33:40 -07001288 // Handlers with dbus-sdr handler implementation.
1289 // Do not register the hander if it dynamic sensors stack is used.
Deepak Kumar Sahua8be7dc2019-05-07 14:26:53 +00001290
Willy Tud351a722021-08-12 14:33:40 -07001291#ifndef FEATURE_DYNAMIC_SENSORS
Tom05732372016-09-06 17:21:23 +05301292 // <Set Sensor Reading and Event Status>
Deepak Kumar Sahu9da3a752019-05-21 00:45:14 +00001293 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1294 ipmi::sensor_event::cmdSetSensorReadingAndEvtSts,
1295 ipmi::Privilege::Operator, ipmiSetSensorReading);
Tom05732372016-09-06 17:21:23 +05301296 // <Get Sensor Reading>
jayaprakash Mutyala4c3feba2019-07-16 00:14:35 +00001297 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1298 ipmi::sensor_event::cmdGetSensorReading,
1299 ipmi::Privilege::User, ipmiSensorGetSensorReading);
Emily Shaffera344afc2017-04-13 15:09:39 -07001300
Tom Joseph5ca50952018-02-22 00:33:38 +05301301 // <Reserve Device SDR Repository>
jayaprakash Mutyalad9578232019-05-13 20:22:50 +00001302 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1303 ipmi::sensor_event::cmdReserveDeviceSdrRepository,
1304 ipmi::Privilege::User, ipmiSensorReserveSdr);
Chris Austen10ccc0f2015-12-10 18:27:04 -06001305
Tom Joseph5ca50952018-02-22 00:33:38 +05301306 // <Get Device SDR Info>
jayaprakash Mutyalad9578232019-05-13 20:22:50 +00001307 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1308 ipmi::sensor_event::cmdGetDeviceSdrInfo,
1309 ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo);
Emily Shafferbbef71c2017-05-08 16:36:17 -07001310
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -06001311 // <Get Sensor Thresholds>
jayaprakash Mutyala996c9792019-05-03 15:56:48 +00001312 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1313 ipmi::sensor_event::cmdGetSensorThreshold,
1314 ipmi::Privilege::User, ipmiSensorGetSensorThresholds);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -06001315
Lotus Xuf93da662021-10-18 17:20:06 +08001316 // <Set Sensor Thresholds>
1317 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1318 ipmi::sensor_event::cmdSetSensorThreshold,
1319 ipmi::Privilege::User, ipmiSenSetSensorThresholds);
Willy Tud351a722021-08-12 14:33:40 -07001320#endif
1321
1322 // Common Handers used by both implementation.
1323
1324 // <Platform Event Message>
1325 ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_PLATFORM_EVENT, nullptr,
1326 ipmicmdPlatformEvent, PRIVILEGE_OPERATOR);
1327
1328 // <Get Sensor Type>
1329 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
1330 ipmi::sensor_event::cmdGetSensorType,
1331 ipmi::Privilege::User, ipmiGetSensorType);
1332
1333 // <Get Device SDR>
1334 ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR, nullptr,
1335 ipmi_sen_get_sdr, PRIVILEGE_USER);
Chris Austenac4604a2015-10-13 12:43:27 -05001336 return;
1337}