blob: 15ab26cacbd124be9c3a1e36d68c000dd3c91e07 [file] [log] [blame]
Patrick Venture0b02be92018-08-31 11:55:55 -07001#include "config.h"
2
Tom Josephbe5eaa12017-07-12 19:54:44 +05303#include "dcmihandler.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07004
Johnathan Mantey74a21022018-12-13 13:17:56 -08005#include "user_channel/channel_layer.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07006#include "utils.hpp"
7
Patrick Venture46470a32018-09-07 19:26:25 -07008#include <host-ipmid/ipmid-api.h>
Patrick Venture0b02be92018-08-31 11:55:55 -07009
10#include <bitset>
11#include <cmath>
12#include <fstream>
13#include <nlohmann/json.hpp>
Tom Josephbe5eaa12017-07-12 19:54:44 +053014#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050015#include <phosphor-logging/log.hpp>
16#include <sdbusplus/bus.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070017#include <sdbusplus/message/types.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070018#include <xyz/openbmc_project/Common/error.hpp>
19
Tom Josephbe5eaa12017-07-12 19:54:44 +053020using namespace phosphor::logging;
21using InternalFailure =
Patrick Venture0b02be92018-08-31 11:55:55 -070022 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Chris Austen1810bec2015-10-13 12:12:39 -050023
24void register_netfn_dcmi_functions() __attribute__((constructor));
25
Patrick Venture0b02be92018-08-31 11:55:55 -070026constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap";
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050027constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap";
28
29constexpr auto POWER_CAP_PROP = "PowerCap";
30constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
31
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -060032constexpr auto DCMI_PARAMETER_REVISION = 2;
33constexpr auto DCMI_SPEC_MAJOR_VERSION = 1;
34constexpr auto DCMI_SPEC_MINOR_VERSION = 5;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060035constexpr auto DCMI_CONFIG_PARAMETER_REVISION = 1;
36constexpr auto DCMI_RAND_BACK_OFF_MASK = 0x80;
37constexpr auto DCMI_OPTION_60_43_MASK = 0x02;
38constexpr auto DCMI_OPTION_12_MASK = 0x01;
39constexpr auto DCMI_ACTIVATE_DHCP_MASK = 0x01;
40constexpr auto DCMI_ACTIVATE_DHCP_REPLY = 0x00;
41constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE = 0x05;
42constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE = 0x04;
Patrick Venture0b02be92018-08-31 11:55:55 -070043constexpr auto DHCP_TIMING1 = 0x04; // 4 sec
44constexpr auto DHCP_TIMING2_UPPER = 0x00; // 2 min
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060045constexpr auto DHCP_TIMING2_LOWER = 0x78;
Patrick Venture0b02be92018-08-31 11:55:55 -070046constexpr auto DHCP_TIMING3_UPPER = 0x00; // 64 sec
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060047constexpr auto DHCP_TIMING3_LOWER = 0x40;
48// When DHCP Option 12 is enabled the string "SendHostName=true" will be
49// added into n/w configuration file and the parameter
50// SendHostNameEnabled will set to true.
51constexpr auto DHCP_OPT12_ENABLED = "SendHostNameEnabled";
52
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -060053constexpr auto DCMI_CAP_JSON_FILE = "/usr/share/ipmi-providers/dcmi_cap.json";
54
Marri Devender Rao66c5fda2018-01-18 10:48:37 -060055constexpr auto SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
56constexpr auto SENSOR_VALUE_PROP = "Value";
57constexpr auto SENSOR_SCALE_PROP = "Scale";
58
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050059using namespace phosphor::logging;
William A. Kennington III4c008022018-10-12 17:18:14 -070060namespace variant_ns = sdbusplus::message::variant_ns;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050061
Tom Josephb9d86f42017-07-26 18:03:47 +053062namespace dcmi
63{
64
Deepak Kodihalli0b459552018-02-06 06:25:12 -060065// Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
Patrick Venture0b02be92018-08-31 11:55:55 -070066static const std::map<uint8_t, std::string> entityIdToName{
67 {0x40, "inlet"}, {0x37, "inlet"}, {0x41, "cpu"},
68 {0x03, "cpu"}, {0x42, "baseboard"}, {0x07, "baseboard"}};
Deepak Kodihalli0b459552018-02-06 06:25:12 -060069
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050070uint32_t getPcap(sdbusplus::bus::bus& bus)
71{
Patrick Venture0b02be92018-08-31 11:55:55 -070072 auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050073
Patrick Venture0b02be92018-08-31 11:55:55 -070074 auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH,
75 "org.freedesktop.DBus.Properties", "Get");
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050076
77 method.append(PCAP_INTERFACE, POWER_CAP_PROP);
78 auto reply = bus.call(method);
79
80 if (reply.is_method_error())
81 {
82 log<level::ERR>("Error in getPcap prop");
Tom Josephb9d86f42017-07-26 18:03:47 +053083 elog<InternalFailure>();
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050084 }
85 sdbusplus::message::variant<uint32_t> pcap;
86 reply.read(pcap);
87
William A. Kennington III4c008022018-10-12 17:18:14 -070088 return variant_ns::get<uint32_t>(pcap);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050089}
90
91bool getPcapEnabled(sdbusplus::bus::bus& bus)
92{
Patrick Venture0b02be92018-08-31 11:55:55 -070093 auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050094
Patrick Venture0b02be92018-08-31 11:55:55 -070095 auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH,
96 "org.freedesktop.DBus.Properties", "Get");
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050097
98 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
99 auto reply = bus.call(method);
100
101 if (reply.is_method_error())
102 {
103 log<level::ERR>("Error in getPcapEnabled prop");
Tom Josephb9d86f42017-07-26 18:03:47 +0530104 elog<InternalFailure>();
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500105 }
106 sdbusplus::message::variant<bool> pcapEnabled;
107 reply.read(pcapEnabled);
108
William A. Kennington III4c008022018-10-12 17:18:14 -0700109 return variant_ns::get<bool>(pcapEnabled);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500110}
Chris Austen1810bec2015-10-13 12:12:39 -0500111
Tom Joseph46fa37d2017-07-26 18:11:55 +0530112void setPcap(sdbusplus::bus::bus& bus, const uint32_t powerCap)
113{
114 auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
115
Patrick Venture0b02be92018-08-31 11:55:55 -0700116 auto method = bus.new_method_call(service.c_str(), PCAP_PATH,
117 "org.freedesktop.DBus.Properties", "Set");
Tom Joseph46fa37d2017-07-26 18:11:55 +0530118
119 method.append(PCAP_INTERFACE, POWER_CAP_PROP);
120 method.append(sdbusplus::message::variant<uint32_t>(powerCap));
121
122 auto reply = bus.call(method);
123
124 if (reply.is_method_error())
125 {
126 log<level::ERR>("Error in setPcap property");
127 elog<InternalFailure>();
128 }
129}
130
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530131void setPcapEnable(sdbusplus::bus::bus& bus, bool enabled)
132{
133 auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
134
Patrick Venture0b02be92018-08-31 11:55:55 -0700135 auto method = bus.new_method_call(service.c_str(), PCAP_PATH,
136 "org.freedesktop.DBus.Properties", "Set");
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530137
138 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
139 method.append(sdbusplus::message::variant<bool>(enabled));
140
141 auto reply = bus.call(method);
142
143 if (reply.is_method_error())
144 {
145 log<level::ERR>("Error in setPcapEnabled property");
146 elog<InternalFailure>();
147 }
148}
149
Tom Josephbe5eaa12017-07-12 19:54:44 +0530150void readAssetTagObjectTree(dcmi::assettag::ObjectTree& objectTree)
151{
152 static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
153 static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
154 static constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper";
155 static constexpr auto inventoryRoot = "/xyz/openbmc_project/inventory/";
156
157 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
158 auto depth = 0;
159
Patrick Venture0b02be92018-08-31 11:55:55 -0700160 auto mapperCall = bus.new_method_call(mapperBusName, mapperObjPath,
161 mapperIface, "GetSubTree");
Tom Josephbe5eaa12017-07-12 19:54:44 +0530162
163 mapperCall.append(inventoryRoot);
164 mapperCall.append(depth);
165 mapperCall.append(std::vector<std::string>({dcmi::assetTagIntf}));
166
167 auto mapperReply = bus.call(mapperCall);
168 if (mapperReply.is_method_error())
169 {
170 log<level::ERR>("Error in mapper call");
171 elog<InternalFailure>();
172 }
173
174 mapperReply.read(objectTree);
175
176 if (objectTree.empty())
177 {
178 log<level::ERR>("AssetTag property is not populated");
179 elog<InternalFailure>();
180 }
181}
182
183std::string readAssetTag()
184{
185 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
186 dcmi::assettag::ObjectTree objectTree;
187
188 // Read the object tree with the inventory root to figure out the object
189 // that has implemented the Asset tag interface.
190 readAssetTagObjectTree(objectTree);
191
192 auto method = bus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -0700193 (objectTree.begin()->second.begin()->first).c_str(),
194 (objectTree.begin()->first).c_str(), dcmi::propIntf, "Get");
Tom Josephbe5eaa12017-07-12 19:54:44 +0530195 method.append(dcmi::assetTagIntf);
196 method.append(dcmi::assetTagProp);
197
198 auto reply = bus.call(method);
199 if (reply.is_method_error())
200 {
201 log<level::ERR>("Error in reading asset tag");
202 elog<InternalFailure>();
203 }
204
205 sdbusplus::message::variant<std::string> assetTag;
206 reply.read(assetTag);
207
William A. Kennington III4c008022018-10-12 17:18:14 -0700208 return variant_ns::get<std::string>(assetTag);
Tom Josephbe5eaa12017-07-12 19:54:44 +0530209}
210
Tom Josephbe5b9892017-07-15 00:55:23 +0530211void writeAssetTag(const std::string& assetTag)
212{
213 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
214 dcmi::assettag::ObjectTree objectTree;
215
216 // Read the object tree with the inventory root to figure out the object
217 // that has implemented the Asset tag interface.
218 readAssetTagObjectTree(objectTree);
219
220 auto method = bus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -0700221 (objectTree.begin()->second.begin()->first).c_str(),
222 (objectTree.begin()->first).c_str(), dcmi::propIntf, "Set");
Tom Josephbe5b9892017-07-15 00:55:23 +0530223 method.append(dcmi::assetTagIntf);
224 method.append(dcmi::assetTagProp);
225 method.append(sdbusplus::message::variant<std::string>(assetTag));
226
227 auto reply = bus.call(method);
228 if (reply.is_method_error())
229 {
230 log<level::ERR>("Error in writing asset tag");
231 elog<InternalFailure>();
232 }
233}
234
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300235std::string getHostName(void)
236{
Patrick Venture0b02be92018-08-31 11:55:55 -0700237 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300238
239 auto service = ipmi::getService(bus, networkConfigIntf, networkConfigObj);
Patrick Venture0b02be92018-08-31 11:55:55 -0700240 auto value = ipmi::getDbusProperty(bus, service, networkConfigObj,
241 networkConfigIntf, hostNameProp);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300242
William A. Kennington III4c008022018-10-12 17:18:14 -0700243 return variant_ns::get<std::string>(value);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300244}
245
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600246bool getDHCPEnabled()
247{
248 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
249
Johnathan Mantey74a21022018-12-13 13:17:56 -0800250 auto ethdevice = ipmi::getChannelName(ethernetDefaultChannelNum);
Patrick Venture0b02be92018-08-31 11:55:55 -0700251 auto ethernetObj =
252 ipmi::getDbusObject(bus, ethernetIntf, networkRoot, ethdevice);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600253 auto service = ipmi::getService(bus, ethernetIntf, ethernetObj.first);
Patrick Venture0b02be92018-08-31 11:55:55 -0700254 auto value = ipmi::getDbusProperty(bus, service, ethernetObj.first,
255 ethernetIntf, "DHCPEnabled");
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600256
William A. Kennington III4c008022018-10-12 17:18:14 -0700257 return variant_ns::get<bool>(value);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600258}
259
260bool getDHCPOption(std::string prop)
261{
262 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
263
264 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
265 auto value = ipmi::getDbusProperty(bus, service, dhcpObj, dhcpIntf, prop);
266
William A. Kennington III4c008022018-10-12 17:18:14 -0700267 return variant_ns::get<bool>(value);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600268}
269
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600270void setDHCPOption(std::string prop, bool value)
271{
272 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
273
274 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
275 ipmi::setDbusProperty(bus, service, dhcpObj, dhcpIntf, prop, value);
276}
277
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600278Json parseSensorConfig()
279{
280 std::ifstream jsonFile(configFile);
281 if (!jsonFile.is_open())
282 {
283 log<level::ERR>("Temperature readings JSON file not found");
284 elog<InternalFailure>();
285 }
286
287 auto data = Json::parse(jsonFile, nullptr, false);
288 if (data.is_discarded())
289 {
290 log<level::ERR>("Temperature readings JSON parser failure");
291 elog<InternalFailure>();
292 }
293
294 return data;
295}
296
Tom Josephbe5eaa12017-07-12 19:54:44 +0530297} // namespace dcmi
Chris Austen1810bec2015-10-13 12:12:39 -0500298
Tom Josephb9d86f42017-07-26 18:03:47 +0530299ipmi_ret_t getPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
300 ipmi_request_t request, ipmi_response_t response,
301 ipmi_data_len_t data_len, ipmi_context_t context)
302{
Patrick Venture0b02be92018-08-31 11:55:55 -0700303 auto requestData =
304 reinterpret_cast<const dcmi::GetPowerLimitRequest*>(request);
Tom Josephb9d86f42017-07-26 18:03:47 +0530305 std::vector<uint8_t> outPayload(sizeof(dcmi::GetPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700306 auto responseData =
307 reinterpret_cast<dcmi::GetPowerLimitResponse*>(outPayload.data());
Tom Josephb9d86f42017-07-26 18:03:47 +0530308
309 if (requestData->groupID != dcmi::groupExtId)
310 {
311 *data_len = 0;
312 return IPMI_CC_INVALID_FIELD_REQUEST;
313 }
314
Patrick Venture0b02be92018-08-31 11:55:55 -0700315 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Josephb9d86f42017-07-26 18:03:47 +0530316 uint32_t pcapValue = 0;
317 bool pcapEnable = false;
318
319 try
320 {
321 pcapValue = dcmi::getPcap(sdbus);
322 pcapEnable = dcmi::getPcapEnabled(sdbus);
323 }
324 catch (InternalFailure& e)
325 {
326 *data_len = 0;
327 return IPMI_CC_UNSPECIFIED_ERROR;
328 }
329
330 responseData->groupID = dcmi::groupExtId;
331
332 /*
333 * Exception action if power limit is exceeded and cannot be controlled
334 * with the correction time limit is hardcoded to Hard Power Off system
335 * and log event to SEL.
336 */
337 constexpr auto exception = 0x01;
338 responseData->exceptionAction = exception;
339
340 responseData->powerLimit = static_cast<uint16_t>(pcapValue);
341
342 /*
343 * Correction time limit and Statistics sampling period is currently not
344 * populated.
345 */
346
347 *data_len = outPayload.size();
348 memcpy(response, outPayload.data(), *data_len);
349
350 if (pcapEnable)
351 {
352 return IPMI_CC_OK;
353 }
354 else
355 {
356 return IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT;
357 }
358}
359
Tom Joseph46fa37d2017-07-26 18:11:55 +0530360ipmi_ret_t setPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
361 ipmi_request_t request, ipmi_response_t response,
362 ipmi_data_len_t data_len, ipmi_context_t context)
363{
Patrick Venture0b02be92018-08-31 11:55:55 -0700364 auto requestData =
365 reinterpret_cast<const dcmi::SetPowerLimitRequest*>(request);
Tom Joseph46fa37d2017-07-26 18:11:55 +0530366 std::vector<uint8_t> outPayload(sizeof(dcmi::SetPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700367 auto responseData =
368 reinterpret_cast<dcmi::SetPowerLimitResponse*>(outPayload.data());
Tom Joseph46fa37d2017-07-26 18:11:55 +0530369
370 if (requestData->groupID != dcmi::groupExtId)
371 {
372 *data_len = 0;
373 return IPMI_CC_INVALID_FIELD_REQUEST;
374 }
375
Patrick Venture0b02be92018-08-31 11:55:55 -0700376 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Joseph46fa37d2017-07-26 18:11:55 +0530377
378 // Only process the power limit requested in watts.
379 try
380 {
381 dcmi::setPcap(sdbus, requestData->powerLimit);
382 }
383 catch (InternalFailure& e)
384 {
385 *data_len = 0;
386 return IPMI_CC_UNSPECIFIED_ERROR;
387 }
388
389 log<level::INFO>("Set Power Cap",
390 entry("POWERCAP=%u", requestData->powerLimit));
391
392 responseData->groupID = dcmi::groupExtId;
393 memcpy(response, outPayload.data(), outPayload.size());
394 *data_len = outPayload.size();
395
396 return IPMI_CC_OK;
397}
398
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530399ipmi_ret_t applyPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
400 ipmi_request_t request, ipmi_response_t response,
401 ipmi_data_len_t data_len, ipmi_context_t context)
402{
Patrick Venture0b02be92018-08-31 11:55:55 -0700403 auto requestData =
404 reinterpret_cast<const dcmi::ApplyPowerLimitRequest*>(request);
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530405 std::vector<uint8_t> outPayload(sizeof(dcmi::ApplyPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700406 auto responseData =
407 reinterpret_cast<dcmi::ApplyPowerLimitResponse*>(outPayload.data());
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530408
409 if (requestData->groupID != dcmi::groupExtId)
410 {
411 *data_len = 0;
412 return IPMI_CC_INVALID_FIELD_REQUEST;
413 }
414
Patrick Venture0b02be92018-08-31 11:55:55 -0700415 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530416
417 try
418 {
419 dcmi::setPcapEnable(sdbus,
420 static_cast<bool>(requestData->powerLimitAction));
421 }
422 catch (InternalFailure& e)
423 {
424 *data_len = 0;
425 return IPMI_CC_UNSPECIFIED_ERROR;
426 }
427
428 log<level::INFO>("Set Power Cap Enable",
429 entry("POWERCAPENABLE=%u", requestData->powerLimitAction));
430
431 responseData->groupID = dcmi::groupExtId;
432 memcpy(response, outPayload.data(), outPayload.size());
433 *data_len = outPayload.size();
434
435 return IPMI_CC_OK;
436}
437
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530438ipmi_ret_t getAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
439 ipmi_request_t request, ipmi_response_t response,
440 ipmi_data_len_t data_len, ipmi_context_t context)
441{
Patrick Venture0b02be92018-08-31 11:55:55 -0700442 auto requestData =
443 reinterpret_cast<const dcmi::GetAssetTagRequest*>(request);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530444 std::vector<uint8_t> outPayload(sizeof(dcmi::GetAssetTagResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700445 auto responseData =
446 reinterpret_cast<dcmi::GetAssetTagResponse*>(outPayload.data());
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530447
448 if (requestData->groupID != dcmi::groupExtId)
449 {
450 *data_len = 0;
451 return IPMI_CC_INVALID_FIELD_REQUEST;
452 }
453
454 // Verify offset to read and number of bytes to read are not exceeding the
455 // range.
456 if ((requestData->offset > dcmi::assetTagMaxOffset) ||
457 (requestData->bytes > dcmi::maxBytes) ||
458 ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize))
459 {
460 *data_len = 0;
461 return IPMI_CC_PARM_OUT_OF_RANGE;
462 }
463
464 std::string assetTag;
465
466 try
467 {
468 assetTag = dcmi::readAssetTag();
469 }
470 catch (InternalFailure& e)
471 {
472 *data_len = 0;
473 return IPMI_CC_UNSPECIFIED_ERROR;
474 }
475
476 responseData->groupID = dcmi::groupExtId;
477
478 // Return if the asset tag is not populated.
479 if (!assetTag.size())
480 {
481 responseData->tagLength = 0;
482 memcpy(response, outPayload.data(), outPayload.size());
483 *data_len = outPayload.size();
484 return IPMI_CC_OK;
485 }
486
487 // If the asset tag is longer than 63 bytes, restrict it to 63 bytes to suit
488 // Get Asset Tag command.
489 if (assetTag.size() > dcmi::assetTagMaxSize)
490 {
491 assetTag.resize(dcmi::assetTagMaxSize);
492 }
493
494 // If the requested offset is beyond the asset tag size.
495 if (requestData->offset >= assetTag.size())
496 {
497 *data_len = 0;
498 return IPMI_CC_PARM_OUT_OF_RANGE;
499 }
500
501 auto returnData = assetTag.substr(requestData->offset, requestData->bytes);
502
503 responseData->tagLength = assetTag.size();
504
505 memcpy(response, outPayload.data(), outPayload.size());
506 memcpy(static_cast<uint8_t*>(response) + outPayload.size(),
507 returnData.data(), returnData.size());
508 *data_len = outPayload.size() + returnData.size();
509
510 return IPMI_CC_OK;
511}
512
Tom Joseph545dd232017-07-12 20:20:49 +0530513ipmi_ret_t setAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
514 ipmi_request_t request, ipmi_response_t response,
515 ipmi_data_len_t data_len, ipmi_context_t context)
516{
Patrick Venture0b02be92018-08-31 11:55:55 -0700517 auto requestData =
518 reinterpret_cast<const dcmi::SetAssetTagRequest*>(request);
Tom Joseph545dd232017-07-12 20:20:49 +0530519 std::vector<uint8_t> outPayload(sizeof(dcmi::SetAssetTagResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700520 auto responseData =
521 reinterpret_cast<dcmi::SetAssetTagResponse*>(outPayload.data());
Tom Joseph545dd232017-07-12 20:20:49 +0530522
523 if (requestData->groupID != dcmi::groupExtId)
524 {
525 *data_len = 0;
526 return IPMI_CC_INVALID_FIELD_REQUEST;
527 }
528
529 // Verify offset to read and number of bytes to read are not exceeding the
530 // range.
531 if ((requestData->offset > dcmi::assetTagMaxOffset) ||
532 (requestData->bytes > dcmi::maxBytes) ||
533 ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize))
534 {
535 *data_len = 0;
536 return IPMI_CC_PARM_OUT_OF_RANGE;
537 }
538
539 std::string assetTag;
540
541 try
542 {
543 assetTag = dcmi::readAssetTag();
544
545 if (requestData->offset > assetTag.size())
546 {
547 *data_len = 0;
548 return IPMI_CC_PARM_OUT_OF_RANGE;
549 }
550
551 assetTag.replace(requestData->offset,
552 assetTag.size() - requestData->offset,
553 static_cast<const char*>(request) +
Patrick Venture0b02be92018-08-31 11:55:55 -0700554 sizeof(dcmi::SetAssetTagRequest),
Tom Joseph545dd232017-07-12 20:20:49 +0530555 requestData->bytes);
556
557 dcmi::writeAssetTag(assetTag);
558
559 responseData->groupID = dcmi::groupExtId;
560 responseData->tagLength = assetTag.size();
561 memcpy(response, outPayload.data(), outPayload.size());
562 *data_len = outPayload.size();
563
564 return IPMI_CC_OK;
565 }
566 catch (InternalFailure& e)
567 {
568 *data_len = 0;
569 return IPMI_CC_UNSPECIFIED_ERROR;
570 }
571}
572
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300573ipmi_ret_t getMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700574 ipmi_request_t request, ipmi_response_t response,
575 ipmi_data_len_t data_len, ipmi_context_t context)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300576{
Patrick Venture0b02be92018-08-31 11:55:55 -0700577 auto requestData =
578 reinterpret_cast<const dcmi::GetMgmntCtrlIdStrRequest*>(request);
579 auto responseData =
580 reinterpret_cast<dcmi::GetMgmntCtrlIdStrResponse*>(response);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300581 std::string hostName;
582
583 *data_len = 0;
584
585 if (requestData->groupID != dcmi::groupExtId ||
586 requestData->bytes > dcmi::maxBytes ||
587 requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen)
588 {
589 return IPMI_CC_INVALID_FIELD_REQUEST;
590 }
591
592 try
593 {
594 hostName = dcmi::getHostName();
595 }
596 catch (InternalFailure& e)
597 {
598 return IPMI_CC_UNSPECIFIED_ERROR;
599 }
600
601 if (requestData->offset > hostName.length())
602 {
603 return IPMI_CC_PARM_OUT_OF_RANGE;
604 }
605 auto responseStr = hostName.substr(requestData->offset, requestData->bytes);
606 auto responseStrLen = std::min(static_cast<std::size_t>(requestData->bytes),
Patrick Venture0b02be92018-08-31 11:55:55 -0700607 responseStr.length() + 1);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300608 responseData->groupID = dcmi::groupExtId;
609 responseData->strLen = hostName.length();
610 std::copy(begin(responseStr), end(responseStr), responseData->data);
611
612 *data_len = sizeof(*responseData) + responseStrLen;
613 return IPMI_CC_OK;
614}
615
616ipmi_ret_t setMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700617 ipmi_request_t request, ipmi_response_t response,
618 ipmi_data_len_t data_len, ipmi_context_t context)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300619{
620 static std::array<char, dcmi::maxCtrlIdStrLen + 1> newCtrlIdStr;
621
Patrick Venture0b02be92018-08-31 11:55:55 -0700622 auto requestData =
623 reinterpret_cast<const dcmi::SetMgmntCtrlIdStrRequest*>(request);
624 auto responseData =
625 reinterpret_cast<dcmi::SetMgmntCtrlIdStrResponse*>(response);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300626
627 *data_len = 0;
628
629 if (requestData->groupID != dcmi::groupExtId ||
630 requestData->bytes > dcmi::maxBytes ||
631 requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen + 1 ||
Patrick Venture0b02be92018-08-31 11:55:55 -0700632 (requestData->offset + requestData->bytes ==
633 dcmi::maxCtrlIdStrLen + 1 &&
634 requestData->data[requestData->bytes - 1] != '\0'))
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300635 {
636 return IPMI_CC_INVALID_FIELD_REQUEST;
637 }
638
639 try
640 {
641 /* if there is no old value and offset is not 0 */
642 if (newCtrlIdStr[0] == '\0' && requestData->offset != 0)
643 {
644 /* read old ctrlIdStr */
645 auto hostName = dcmi::getHostName();
646 hostName.resize(dcmi::maxCtrlIdStrLen);
647 std::copy(begin(hostName), end(hostName), begin(newCtrlIdStr));
648 newCtrlIdStr[hostName.length()] = '\0';
649 }
650
651 /* replace part of string and mark byte after the last as \0 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700652 auto restStrIter =
653 std::copy_n(requestData->data, requestData->bytes,
654 begin(newCtrlIdStr) + requestData->offset);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300655 /* if the last written byte is not 64th - add '\0' */
656 if (requestData->offset + requestData->bytes <= dcmi::maxCtrlIdStrLen)
657 {
658 *restStrIter = '\0';
659 }
660
661 /* if input data contains '\0' whole string is sent - update hostname */
662 auto it = std::find(requestData->data,
Patrick Venture0b02be92018-08-31 11:55:55 -0700663 requestData->data + requestData->bytes, '\0');
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300664 if (it != requestData->data + requestData->bytes)
665 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700666 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300667 ipmi::setDbusProperty(bus, dcmi::networkServiceName,
Patrick Venture0b02be92018-08-31 11:55:55 -0700668 dcmi::networkConfigObj,
669 dcmi::networkConfigIntf, dcmi::hostNameProp,
670 std::string(newCtrlIdStr.data()));
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300671 }
672 }
673 catch (InternalFailure& e)
674 {
675 *data_len = 0;
676 return IPMI_CC_UNSPECIFIED_ERROR;
677 }
678
679 responseData->groupID = dcmi::groupExtId;
680 responseData->offset = requestData->offset + requestData->bytes;
681 *data_len = sizeof(*responseData);
682 return IPMI_CC_OK;
683}
684
Patrick Venture0b02be92018-08-31 11:55:55 -0700685// List of the capabilities under each parameter
686dcmi::DCMICaps dcmiCaps = {
687 // Supported DCMI Capabilities
688 {dcmi::DCMICapParameters::SUPPORTED_DCMI_CAPS,
689 {3,
690 {{"PowerManagement", 2, 0, 1},
691 {"OOBSecondaryLan", 3, 2, 1},
692 {"SerialTMODE", 3, 1, 1},
693 {"InBandSystemInterfaceChannel", 3, 0, 1}}}},
694 // Mandatory Platform Attributes
695 {dcmi::DCMICapParameters::MANDATORY_PLAT_ATTRIBUTES,
696 {5,
697 {{"SELAutoRollOver", 1, 15, 1},
698 {"FlushEntireSELUponRollOver", 1, 14, 1},
699 {"RecordLevelSELFlushUponRollOver", 1, 13, 1},
700 {"NumberOfSELEntries", 1, 0, 12},
701 {"TempMonitoringSamplingFreq", 5, 0, 8}}}},
702 // Optional Platform Attributes
703 {dcmi::DCMICapParameters::OPTIONAL_PLAT_ATTRIBUTES,
704 {2,
705 {{"PowerMgmtDeviceSlaveAddress", 1, 1, 7},
706 {"BMCChannelNumber", 2, 4, 4},
707 {"DeviceRivision", 2, 0, 4}}}},
708 // Manageability Access Attributes
709 {dcmi::DCMICapParameters::MANAGEABILITY_ACCESS_ATTRIBUTES,
710 {3,
711 {{"MandatoryPrimaryLanOOBSupport", 1, 0, 8},
712 {"OptionalSecondaryLanOOBSupport", 2, 0, 8},
713 {"OptionalSerialOOBMTMODECapability", 3, 0, 8}}}}};
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600714
715ipmi_ret_t getDCMICapabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
716 ipmi_request_t request, ipmi_response_t response,
717 ipmi_data_len_t data_len, ipmi_context_t context)
718{
719
720 std::ifstream dcmiCapFile(DCMI_CAP_JSON_FILE);
721 if (!dcmiCapFile.is_open())
722 {
723 log<level::ERR>("DCMI Capabilities file not found");
724 return IPMI_CC_UNSPECIFIED_ERROR;
725 }
726
727 auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false);
728 if (data.is_discarded())
729 {
730 log<level::ERR>("DCMI Capabilities JSON parser failure");
731 return IPMI_CC_UNSPECIFIED_ERROR;
732 }
733
Patrick Venture0b02be92018-08-31 11:55:55 -0700734 auto requestData =
735 reinterpret_cast<const dcmi::GetDCMICapRequest*>(request);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600736
Patrick Venture0b02be92018-08-31 11:55:55 -0700737 // get list of capabilities in a parameter
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600738 auto caps =
739 dcmiCaps.find(static_cast<dcmi::DCMICapParameters>(requestData->param));
740 if (caps == dcmiCaps.end())
741 {
742 log<level::ERR>("Invalid input parameter");
743 return IPMI_CC_INVALID_FIELD_REQUEST;
744 }
745
746 if (requestData->groupID != dcmi::groupExtId)
747 {
748 *data_len = 0;
749 return IPMI_CC_INVALID_FIELD_REQUEST;
750 }
751
Patrick Venture0b02be92018-08-31 11:55:55 -0700752 auto responseData = reinterpret_cast<dcmi::GetDCMICapResponse*>(response);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600753
Patrick Venture0b02be92018-08-31 11:55:55 -0700754 // For each capabilities in a parameter fill the data from
755 // the json file based on the capability name.
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600756 for (auto cap : caps->second.capList)
757 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700758 // If the data is beyond first byte boundary, insert in a
759 // 16bit pattern for example number of SEL entries are represented
760 // in 12bits.
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600761 if ((cap.length + cap.position) > 8)
762 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700763 // Read the value corresponding to capability name and assign to
764 // 16bit bitset.
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600765 std::bitset<16> val(data.value(cap.name.c_str(), 0));
766 val <<= cap.position;
Patrick Venture0b02be92018-08-31 11:55:55 -0700767 reinterpret_cast<uint16_t*>(
768 responseData
769 ->data)[(cap.bytePosition - 1) / sizeof(uint16_t)] |=
770 val.to_ulong();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600771 }
772 else
773 {
774 responseData->data[cap.bytePosition - 1] |=
775 data.value(cap.name.c_str(), 0) << cap.position;
776 }
777 }
778
779 responseData->groupID = dcmi::groupExtId;
780 responseData->major = DCMI_SPEC_MAJOR_VERSION;
781 responseData->minor = DCMI_SPEC_MINOR_VERSION;
782 responseData->paramRevision = DCMI_PARAMETER_REVISION;
783 *data_len = sizeof(*responseData) + caps->second.size;
784
785 return IPMI_CC_OK;
786}
787
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600788namespace dcmi
789{
790namespace temp_readings
791{
792
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600793Temperature readTemp(const std::string& dbusService,
794 const std::string& dbusPath)
795{
796 // Read the temperature value from d-bus object. Need some conversion.
797 // As per the interface xyz.openbmc_project.Sensor.Value, the temperature
James Feist9cc0ea52018-10-09 10:53:11 -0700798 // is an double and in degrees C. It needs to be scaled by using the
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600799 // formula Value * 10^Scale. The ipmi spec has the temperature as a uint8_t,
800 // with a separate single bit for the sign.
801
802 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700803 auto result = ipmi::getAllDbusProperties(
804 bus, dbusService, dbusPath, "xyz.openbmc_project.Sensor.Value");
James Feist9cc0ea52018-10-09 10:53:11 -0700805 auto temperature = sdbusplus::message::variant_ns::visit(
806 ipmi::VariantToDoubleVisitor(), result.at("Value"));
807 double absTemp = std::abs(temperature);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600808
James Feist9cc0ea52018-10-09 10:53:11 -0700809 auto findFactor = result.find("Scale");
810 double factor = 0.0;
811 if (findFactor != result.end())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600812 {
James Feist9cc0ea52018-10-09 10:53:11 -0700813 factor = sdbusplus::message::variant_ns::visit(
814 ipmi::VariantToDoubleVisitor(), findFactor->second);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600815 }
James Feist9cc0ea52018-10-09 10:53:11 -0700816 double scale = std::pow(10, factor);
817
818 auto tempDegrees = absTemp * scale;
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600819 // Max absolute temp as per ipmi spec is 128.
820 if (tempDegrees > maxTemp)
821 {
822 tempDegrees = maxTemp;
823 }
824
825 return std::make_tuple(static_cast<uint8_t>(tempDegrees),
826 (temperature < 0));
827}
828
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600829std::tuple<Response, NumInstances> read(const std::string& type,
830 uint8_t instance)
831{
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600832 Response response{};
833 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
834
835 if (!instance)
836 {
837 log<level::ERR>("Expected non-zero instance");
838 elog<InternalFailure>();
839 }
840
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600841 auto data = parseSensorConfig();
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600842 static const std::vector<Json> empty{};
843 std::vector<Json> readings = data.value(type, empty);
844 size_t numInstances = readings.size();
845 for (const auto& j : readings)
846 {
847 uint8_t instanceNum = j.value("instance", 0);
848 // Not the instance we're interested in
849 if (instanceNum != instance)
850 {
851 continue;
852 }
853
854 std::string path = j.value("dbus", "");
855 std::string service;
856 try
857 {
858 service =
Patrick Venture0b02be92018-08-31 11:55:55 -0700859 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600860 }
861 catch (std::exception& e)
862 {
863 log<level::DEBUG>(e.what());
864 return std::make_tuple(response, numInstances);
865 }
866
867 response.instance = instance;
868 uint8_t temp{};
869 bool sign{};
870 std::tie(temp, sign) = readTemp(service, path);
871 response.temperature = temp;
872 response.sign = sign;
873
874 // Found the instance we're interested in
875 break;
876 }
877
878 if (numInstances > maxInstances)
879 {
880 numInstances = maxInstances;
881 }
882 return std::make_tuple(response, numInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600883}
884
885std::tuple<ResponseList, NumInstances> readAll(const std::string& type,
886 uint8_t instanceStart)
887{
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600888 ResponseList response{};
889 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
890
891 size_t numInstances = 0;
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600892 auto data = parseSensorConfig();
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600893 static const std::vector<Json> empty{};
894 std::vector<Json> readings = data.value(type, empty);
895 numInstances = readings.size();
896 for (const auto& j : readings)
897 {
898 try
899 {
900 // Max of 8 response data sets
901 if (response.size() == maxDataSets)
902 {
903 break;
904 }
905
906 uint8_t instanceNum = j.value("instance", 0);
907 // Not in the instance range we're interested in
908 if (instanceNum < instanceStart)
909 {
910 continue;
911 }
912
913 std::string path = j.value("dbus", "");
914 auto service =
Patrick Venture0b02be92018-08-31 11:55:55 -0700915 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600916
917 Response r{};
918 r.instance = instanceNum;
919 uint8_t temp{};
920 bool sign{};
921 std::tie(temp, sign) = readTemp(service, path);
922 r.temperature = temp;
923 r.sign = sign;
924 response.push_back(r);
925 }
926 catch (std::exception& e)
927 {
928 log<level::DEBUG>(e.what());
929 continue;
930 }
931 }
932
933 if (numInstances > maxInstances)
934 {
935 numInstances = maxInstances;
936 }
937 return std::make_tuple(response, numInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600938}
939
Patrick Venture0b02be92018-08-31 11:55:55 -0700940} // namespace temp_readings
941} // namespace dcmi
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600942
943ipmi_ret_t getTempReadings(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700944 ipmi_request_t request, ipmi_response_t response,
945 ipmi_data_len_t data_len, ipmi_context_t context)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600946{
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600947 auto requestData =
948 reinterpret_cast<const dcmi::GetTempReadingsRequest*>(request);
949 auto responseData =
950 reinterpret_cast<dcmi::GetTempReadingsResponseHdr*>(response);
951
952 if (*data_len != sizeof(dcmi::GetTempReadingsRequest))
953 {
954 log<level::ERR>("Malformed request data",
955 entry("DATA_SIZE=%d", *data_len));
956 return IPMI_CC_REQ_DATA_LEN_INVALID;
957 }
958 *data_len = 0;
959
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600960 auto it = dcmi::entityIdToName.find(requestData->entityId);
961 if (it == dcmi::entityIdToName.end())
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600962 {
963 log<level::ERR>("Unknown Entity ID",
964 entry("ENTITY_ID=%d", requestData->entityId));
965 return IPMI_CC_INVALID_FIELD_REQUEST;
966 }
967
968 if (requestData->groupID != dcmi::groupExtId)
969 {
970 log<level::ERR>("Invalid Group ID",
971 entry("GROUP_ID=%d", requestData->groupID));
972 return IPMI_CC_INVALID_FIELD_REQUEST;
973 }
974
975 if (requestData->sensorType != dcmi::temperatureSensorType)
976 {
977 log<level::ERR>("Invalid sensor type",
978 entry("SENSOR_TYPE=%d", requestData->sensorType));
979 return IPMI_CC_INVALID_FIELD_REQUEST;
980 }
981
982 dcmi::temp_readings::ResponseList temps{};
983 try
984 {
985 if (!requestData->entityInstance)
986 {
987 // Read all instances
988 std::tie(temps, responseData->numInstances) =
989 dcmi::temp_readings::readAll(it->second,
990 requestData->instanceStart);
991 }
992 else
993 {
994 // Read one instance
995 temps.resize(1);
996 std::tie(temps[0], responseData->numInstances) =
997 dcmi::temp_readings::read(it->second,
998 requestData->entityInstance);
999 }
1000 responseData->numDataSets = temps.size();
1001 }
1002 catch (InternalFailure& e)
1003 {
1004 return IPMI_CC_UNSPECIFIED_ERROR;
1005 }
1006
1007 responseData->groupID = dcmi::groupExtId;
Patrick Venture0b02be92018-08-31 11:55:55 -07001008 size_t payloadSize = temps.size() * sizeof(dcmi::temp_readings::Response);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001009 if (!temps.empty())
1010 {
1011 memcpy(responseData + 1, // copy payload right after the response header
Patrick Venture0b02be92018-08-31 11:55:55 -07001012 temps.data(), payloadSize);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001013 }
1014 *data_len = sizeof(dcmi::GetTempReadingsResponseHdr) + payloadSize;
1015
1016 return IPMI_CC_OK;
1017}
1018
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001019int64_t getPowerReading(sdbusplus::bus::bus& bus)
1020{
1021 std::ifstream sensorFile(POWER_READING_SENSOR);
1022 std::string objectPath;
1023 if (!sensorFile.is_open())
1024 {
1025 log<level::ERR>("Power reading configuration file not found",
Patrick Venture0b02be92018-08-31 11:55:55 -07001026 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001027 elog<InternalFailure>();
1028 }
1029
1030 auto data = nlohmann::json::parse(sensorFile, nullptr, false);
1031 if (data.is_discarded())
1032 {
1033 log<level::ERR>("Error in parsing configuration file",
Patrick Venture0b02be92018-08-31 11:55:55 -07001034 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001035 elog<InternalFailure>();
1036 }
1037
1038 objectPath = data.value("path", "");
1039 if (objectPath.empty())
1040 {
1041 log<level::ERR>("Power sensor D-Bus object path is empty",
1042 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
1043 elog<InternalFailure>();
1044 }
1045
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001046 // Return default value if failed to read from D-Bus object
1047 int64_t power = 0;
1048 try
1049 {
1050 auto service = ipmi::getService(bus, SENSOR_VALUE_INTF, objectPath);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001051
Patrick Venture0b02be92018-08-31 11:55:55 -07001052 // Read the sensor value and scale properties
1053 auto properties = ipmi::getAllDbusProperties(bus, service, objectPath,
1054 SENSOR_VALUE_INTF);
William A. Kennington III4c008022018-10-12 17:18:14 -07001055 auto value = variant_ns::get<int64_t>(properties[SENSOR_VALUE_PROP]);
1056 auto scale = variant_ns::get<int64_t>(properties[SENSOR_SCALE_PROP]);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001057
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001058 // Power reading needs to be scaled with the Scale value using the
1059 // formula Value * 10^Scale.
1060 power = value * std::pow(10, scale);
1061 }
1062 catch (std::exception& e)
1063 {
1064 log<level::INFO>("Failure to read power value from D-Bus object",
Patrick Venture0b02be92018-08-31 11:55:55 -07001065 entry("OBJECT_PATH=%s", objectPath.c_str()),
1066 entry("INTERFACE=%s", SENSOR_VALUE_INTF));
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001067 }
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001068 return power;
1069}
1070
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001071ipmi_ret_t setDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1072 ipmi_request_t request, ipmi_response_t response,
1073 ipmi_data_len_t data_len, ipmi_context_t context)
1074{
Patrick Venture0b02be92018-08-31 11:55:55 -07001075 auto requestData =
1076 reinterpret_cast<const dcmi::SetConfParamsRequest*>(request);
1077 auto responseData =
1078 reinterpret_cast<dcmi::SetConfParamsResponse*>(response);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001079
Patrick Venture0b02be92018-08-31 11:55:55 -07001080 if (requestData->groupID != dcmi::groupExtId ||
1081 *data_len < DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE ||
1082 *data_len > DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001083 {
Gunnar Mills8466b792018-03-23 12:18:12 -05001084 log<level::ERR>("Invalid Group ID or Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001085 entry("GROUP_ID=%d", requestData->groupID),
1086 entry("PACKET SIZE=%d", *data_len));
1087 return IPMI_CC_INVALID_FIELD_REQUEST;
1088 }
1089
1090 *data_len = 0;
1091
1092 try
1093 {
1094 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -07001095 switch (
1096 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001097 {
1098 case dcmi::DCMIConfigParameters::ActivateDHCP:
1099
1100 if ((requestData->data[0] & DCMI_ACTIVATE_DHCP_MASK) &&
Patrick Venture0b02be92018-08-31 11:55:55 -07001101 dcmi::getDHCPEnabled())
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001102 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001103 // When these conditions are met we have to trigger DHCP
1104 // protocol restart using the latest parameter settings, but
1105 // as per n/w manager design, each time when we update n/w
1106 // parameters, n/w service is restarted. So we no need to
1107 // take any action in this case.
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001108 }
1109 break;
1110
1111 case dcmi::DCMIConfigParameters::DiscoveryConfig:
1112
1113 if (requestData->data[0] & DCMI_OPTION_12_MASK)
1114 {
1115 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, true);
1116 }
1117 else
1118 {
1119 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, false);
1120 }
1121
1122 // Systemd-networkd doesn't support Random Back off
1123 if (requestData->data[0] & DCMI_RAND_BACK_OFF_MASK)
1124 {
1125 return IPMI_CC_INVALID;
1126 }
1127 break;
1128 // Systemd-networkd doesn't allow to configure DHCP timigs
1129 case dcmi::DCMIConfigParameters::DHCPTiming1:
1130 case dcmi::DCMIConfigParameters::DHCPTiming2:
1131 case dcmi::DCMIConfigParameters::DHCPTiming3:
1132 default:
1133 return IPMI_CC_INVALID;
1134 }
1135 }
1136 catch (std::exception& e)
1137 {
1138 log<level::ERR>(e.what());
1139 return IPMI_CC_UNSPECIFIED_ERROR;
1140 }
1141 responseData->groupID = dcmi::groupExtId;
1142 *data_len = sizeof(dcmi::SetConfParamsResponse);
1143
1144 return IPMI_CC_OK;
1145}
1146
1147ipmi_ret_t getDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1148 ipmi_request_t request, ipmi_response_t response,
1149 ipmi_data_len_t data_len, ipmi_context_t context)
1150{
1151
Patrick Venture0b02be92018-08-31 11:55:55 -07001152 auto requestData =
1153 reinterpret_cast<const dcmi::GetConfParamsRequest*>(request);
1154 auto responseData =
1155 reinterpret_cast<dcmi::GetConfParamsResponse*>(response);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001156
1157 responseData->data[0] = 0x00;
1158
Patrick Venture0b02be92018-08-31 11:55:55 -07001159 if (requestData->groupID != dcmi::groupExtId ||
1160 *data_len != sizeof(dcmi::GetConfParamsRequest))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001161 {
Gunnar Mills8466b792018-03-23 12:18:12 -05001162 log<level::ERR>("Invalid Group ID or Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001163 entry("GROUP_ID=%d", requestData->groupID),
1164 entry("PACKET SIZE=%d", *data_len));
1165 return IPMI_CC_INVALID_FIELD_REQUEST;
1166 }
1167
1168 *data_len = 0;
1169
1170 try
1171 {
1172 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -07001173 switch (
1174 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001175 {
1176 case dcmi::DCMIConfigParameters::ActivateDHCP:
1177 responseData->data[0] = DCMI_ACTIVATE_DHCP_REPLY;
1178 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1179 break;
1180 case dcmi::DCMIConfigParameters::DiscoveryConfig:
1181 if (dcmi::getDHCPOption(DHCP_OPT12_ENABLED))
1182 {
1183 responseData->data[0] |= DCMI_OPTION_12_MASK;
1184 }
1185 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1186 break;
1187 // Get below values from Systemd-networkd source code
1188 case dcmi::DCMIConfigParameters::DHCPTiming1:
1189 responseData->data[0] = DHCP_TIMING1;
1190 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1191 break;
1192 case dcmi::DCMIConfigParameters::DHCPTiming2:
1193 responseData->data[0] = DHCP_TIMING2_LOWER;
1194 responseData->data[1] = DHCP_TIMING2_UPPER;
1195 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
1196 break;
1197 case dcmi::DCMIConfigParameters::DHCPTiming3:
1198 responseData->data[0] = DHCP_TIMING3_LOWER;
1199 responseData->data[1] = DHCP_TIMING3_UPPER;
1200 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
1201 break;
1202 default:
1203 *data_len = 0;
1204 return IPMI_CC_INVALID;
1205 }
1206 }
1207 catch (std::exception& e)
1208 {
1209 log<level::ERR>(e.what());
1210 return IPMI_CC_UNSPECIFIED_ERROR;
1211 }
1212
1213 responseData->groupID = dcmi::groupExtId;
1214 responseData->major = DCMI_SPEC_MAJOR_VERSION;
1215 responseData->minor = DCMI_SPEC_MINOR_VERSION;
1216 responseData->paramRevision = DCMI_CONFIG_PARAMETER_REVISION;
1217
1218 return IPMI_CC_OK;
1219}
1220
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001221ipmi_ret_t getPowerReading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -07001222 ipmi_request_t request, ipmi_response_t response,
1223 ipmi_data_len_t data_len, ipmi_context_t context)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001224{
1225 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001226 auto requestData =
1227 reinterpret_cast<const dcmi::GetPowerReadingRequest*>(request);
1228 auto responseData =
1229 reinterpret_cast<dcmi::GetPowerReadingResponse*>(response);
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001230
1231 if (requestData->groupID != dcmi::groupExtId)
1232 {
1233 *data_len = 0;
1234 return IPMI_CC_INVALID_FIELD_REQUEST;
1235 }
1236
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001237 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001238 int64_t power = 0;
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001239 try
1240 {
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001241 power = getPowerReading(bus);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001242 }
1243 catch (InternalFailure& e)
1244 {
1245 log<level::ERR>("Error in reading power sensor value",
1246 entry("INTERFACE=%s", SENSOR_VALUE_INTF),
1247 entry("PROPERTY=%s", SENSOR_VALUE_PROP));
1248 return IPMI_CC_UNSPECIFIED_ERROR;
1249 }
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001250 responseData->groupID = dcmi::groupExtId;
1251
1252 // TODO: openbmc/openbmc#2819
Gunnar Mills8466b792018-03-23 12:18:12 -05001253 // Minimum, Maximum, Average power, TimeFrame, TimeStamp,
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001254 // PowerReadingState readings need to be populated
1255 // after Telemetry changes.
1256 uint16_t totalPower = static_cast<uint16_t>(power);
1257 responseData->currentPower = totalPower;
1258 responseData->minimumPower = totalPower;
1259 responseData->maximumPower = totalPower;
1260 responseData->averagePower = totalPower;
1261
1262 *data_len = sizeof(*responseData);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001263 return rc;
1264}
1265
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001266namespace dcmi
1267{
1268namespace sensor_info
1269{
1270
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001271Response createFromJson(const Json& config)
1272{
1273 Response response{};
1274 uint16_t recordId = config.value("record_id", 0);
1275 response.recordIdLsb = recordId & 0xFF;
1276 response.recordIdMsb = (recordId >> 8) & 0xFF;
1277 return response;
1278}
1279
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001280std::tuple<Response, NumInstances> read(const std::string& type,
Patrick Venture0b02be92018-08-31 11:55:55 -07001281 uint8_t instance, const Json& config)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001282{
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001283 Response response{};
1284
1285 if (!instance)
1286 {
1287 log<level::ERR>("Expected non-zero instance");
1288 elog<InternalFailure>();
1289 }
1290
1291 static const std::vector<Json> empty{};
1292 std::vector<Json> readings = config.value(type, empty);
1293 size_t numInstances = readings.size();
1294 for (const auto& reading : readings)
1295 {
1296 uint8_t instanceNum = reading.value("instance", 0);
1297 // Not the instance we're interested in
1298 if (instanceNum != instance)
1299 {
1300 continue;
1301 }
1302
1303 response = createFromJson(reading);
1304
1305 // Found the instance we're interested in
1306 break;
1307 }
1308
1309 if (numInstances > maxInstances)
1310 {
1311 log<level::DEBUG>("Trimming IPMI num instances",
1312 entry("NUM_INSTANCES=%d", numInstances));
1313 numInstances = maxInstances;
1314 }
1315 return std::make_tuple(response, numInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001316}
1317
Patrick Venture0b02be92018-08-31 11:55:55 -07001318std::tuple<ResponseList, NumInstances>
1319 readAll(const std::string& type, uint8_t instanceStart, const Json& config)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001320{
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001321 ResponseList responses{};
1322
1323 size_t numInstances = 0;
1324 static const std::vector<Json> empty{};
1325 std::vector<Json> readings = config.value(type, empty);
1326 numInstances = readings.size();
1327 for (const auto& reading : readings)
1328 {
1329 try
1330 {
1331 // Max of 8 records
1332 if (responses.size() == maxRecords)
1333 {
1334 break;
1335 }
1336
1337 uint8_t instanceNum = reading.value("instance", 0);
1338 // Not in the instance range we're interested in
1339 if (instanceNum < instanceStart)
1340 {
1341 continue;
1342 }
1343
1344 Response response = createFromJson(reading);
1345 responses.push_back(response);
1346 }
1347 catch (std::exception& e)
1348 {
1349 log<level::DEBUG>(e.what());
1350 continue;
1351 }
1352 }
1353
1354 if (numInstances > maxInstances)
1355 {
1356 log<level::DEBUG>("Trimming IPMI num instances",
1357 entry("NUM_INSTANCES=%d", numInstances));
1358 numInstances = maxInstances;
1359 }
1360 return std::make_tuple(responses, numInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001361}
1362
1363} // namespace sensor_info
1364} // namespace dcmi
1365
1366ipmi_ret_t getSensorInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1367 ipmi_request_t request, ipmi_response_t response,
1368 ipmi_data_len_t data_len, ipmi_context_t context)
1369{
1370 auto requestData =
1371 reinterpret_cast<const dcmi::GetSensorInfoRequest*>(request);
1372 auto responseData =
1373 reinterpret_cast<dcmi::GetSensorInfoResponseHdr*>(response);
1374
1375 if (*data_len != sizeof(dcmi::GetSensorInfoRequest))
1376 {
1377 log<level::ERR>("Malformed request data",
1378 entry("DATA_SIZE=%d", *data_len));
1379 return IPMI_CC_REQ_DATA_LEN_INVALID;
1380 }
1381 *data_len = 0;
1382
1383 auto it = dcmi::entityIdToName.find(requestData->entityId);
1384 if (it == dcmi::entityIdToName.end())
1385 {
1386 log<level::ERR>("Unknown Entity ID",
1387 entry("ENTITY_ID=%d", requestData->entityId));
1388 return IPMI_CC_INVALID_FIELD_REQUEST;
1389 }
1390
1391 if (requestData->groupID != dcmi::groupExtId)
1392 {
1393 log<level::ERR>("Invalid Group ID",
1394 entry("GROUP_ID=%d", requestData->groupID));
1395 return IPMI_CC_INVALID_FIELD_REQUEST;
1396 }
1397
1398 if (requestData->sensorType != dcmi::temperatureSensorType)
1399 {
1400 log<level::ERR>("Invalid sensor type",
1401 entry("SENSOR_TYPE=%d", requestData->sensorType));
1402 return IPMI_CC_INVALID_FIELD_REQUEST;
1403 }
1404
1405 dcmi::sensor_info::ResponseList sensors{};
1406 static dcmi::Json config{};
1407 static bool parsed = false;
1408
1409 try
1410 {
1411 if (!parsed)
1412 {
1413 config = dcmi::parseSensorConfig();
1414 parsed = true;
1415 }
1416
1417 if (!requestData->entityInstance)
1418 {
1419 // Read all instances
1420 std::tie(sensors, responseData->numInstances) =
1421 dcmi::sensor_info::readAll(it->second,
Patrick Venture0b02be92018-08-31 11:55:55 -07001422 requestData->instanceStart, config);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001423 }
1424 else
1425 {
1426 // Read one instance
1427 sensors.resize(1);
1428 std::tie(sensors[0], responseData->numInstances) =
Patrick Venture0b02be92018-08-31 11:55:55 -07001429 dcmi::sensor_info::read(it->second, requestData->entityInstance,
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001430 config);
1431 }
1432 responseData->numRecords = sensors.size();
1433 }
1434 catch (InternalFailure& e)
1435 {
1436 return IPMI_CC_UNSPECIFIED_ERROR;
1437 }
1438
1439 responseData->groupID = dcmi::groupExtId;
1440 size_t payloadSize = sensors.size() * sizeof(dcmi::sensor_info::Response);
1441 if (!sensors.empty())
1442 {
1443 memcpy(responseData + 1, // copy payload right after the response header
Patrick Venture0b02be92018-08-31 11:55:55 -07001444 sensors.data(), payloadSize);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001445 }
1446 *data_len = sizeof(dcmi::GetSensorInfoResponseHdr) + payloadSize;
1447
1448 return IPMI_CC_OK;
1449}
1450
Chris Austen1810bec2015-10-13 12:12:39 -05001451void register_netfn_dcmi_functions()
1452{
Tom05732372016-09-06 17:21:23 +05301453 // <Get Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301454
Patrick Venture0b02be92018-08-31 11:55:55 -07001455 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_LIMIT, NULL,
1456 getPowerLimit, PRIVILEGE_USER);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301457
Tom Joseph46fa37d2017-07-26 18:11:55 +05301458 // <Set Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301459
Patrick Venture0b02be92018-08-31 11:55:55 -07001460 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_POWER_LIMIT, NULL,
1461 setPowerLimit, PRIVILEGE_OPERATOR);
Tom Joseph46fa37d2017-07-26 18:11:55 +05301462
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301463 // <Activate/Deactivate Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301464
1465 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::APPLY_POWER_LIMIT,
1466 NULL, applyPowerLimit, PRIVILEGE_OPERATOR);
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301467
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301468 // <Get Asset Tag>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301469
Patrick Venture0b02be92018-08-31 11:55:55 -07001470 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_ASSET_TAG, NULL,
1471 getAssetTag, PRIVILEGE_USER);
Tom Joseph545dd232017-07-12 20:20:49 +05301472
1473 // <Set Asset Tag>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301474
Patrick Venture0b02be92018-08-31 11:55:55 -07001475 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_ASSET_TAG, NULL,
1476 setAssetTag, PRIVILEGE_OPERATOR);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001477
Gunnar Mills8991dd62017-10-25 17:11:29 -05001478 // <Get Management Controller Identifier String>
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001479
1480 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_MGMNT_CTRL_ID_STR,
Patrick Venture0b02be92018-08-31 11:55:55 -07001481 NULL, getMgmntCtrlIdStr, PRIVILEGE_USER);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001482
1483 // <Set Management Controller Identifier String>
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001484 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_MGMNT_CTRL_ID_STR,
Patrick Venture0b02be92018-08-31 11:55:55 -07001485 NULL, setMgmntCtrlIdStr, PRIVILEGE_ADMIN);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001486
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -06001487 // <Get DCMI capabilities>
1488 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CAPABILITIES,
Patrick Venture0b02be92018-08-31 11:55:55 -07001489 NULL, getDCMICapabilities, PRIVILEGE_USER);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001490
1491 // <Get Temperature Readings>
1492 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_TEMP_READINGS,
1493 NULL, getTempReadings, PRIVILEGE_USER);
1494
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001495 // <Get Power Reading>
1496 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_READING,
1497 NULL, getPowerReading, PRIVILEGE_USER);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001498
1499 // <Get Sensor Info>
Patrick Venture0b02be92018-08-31 11:55:55 -07001500 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_SENSOR_INFO, NULL,
1501 getSensorInfo, PRIVILEGE_USER);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001502
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001503 // <Get DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001504 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CONF_PARAMS, NULL,
1505 getDCMIConfParams, PRIVILEGE_USER);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001506
1507 // <Set DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001508 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_CONF_PARAMS, NULL,
1509 setDCMIConfParams, PRIVILEGE_ADMIN);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001510
Chris Austen1810bec2015-10-13 12:12:39 -05001511 return;
1512}
Tom05732372016-09-06 17:21:23 +05301513// 956379