blob: edbca8f6fa61c9bb5ea240739fd35095d6602f9d [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
Patrick Venture0b02be92018-08-31 11:55:55 -07007#include <bitset>
8#include <cmath>
9#include <fstream>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070010#include <ipmid/api.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070011#include <ipmid/utils.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070012#include <nlohmann/json.hpp>
Tom Josephbe5eaa12017-07-12 19:54:44 +053013#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050014#include <phosphor-logging/log.hpp>
15#include <sdbusplus/bus.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070016#include <sdbusplus/message/types.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070017#include <xyz/openbmc_project/Common/error.hpp>
18
Tom Josephbe5eaa12017-07-12 19:54:44 +053019using namespace phosphor::logging;
20using InternalFailure =
Patrick Venture0b02be92018-08-31 11:55:55 -070021 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Chris Austen1810bec2015-10-13 12:12:39 -050022
23void register_netfn_dcmi_functions() __attribute__((constructor));
24
Patrick Venture0b02be92018-08-31 11:55:55 -070025constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap";
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050026constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap";
27
28constexpr auto POWER_CAP_PROP = "PowerCap";
29constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
30
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -060031constexpr auto DCMI_PARAMETER_REVISION = 2;
32constexpr auto DCMI_SPEC_MAJOR_VERSION = 1;
33constexpr auto DCMI_SPEC_MINOR_VERSION = 5;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060034constexpr auto DCMI_CONFIG_PARAMETER_REVISION = 1;
35constexpr auto DCMI_RAND_BACK_OFF_MASK = 0x80;
36constexpr auto DCMI_OPTION_60_43_MASK = 0x02;
37constexpr auto DCMI_OPTION_12_MASK = 0x01;
38constexpr auto DCMI_ACTIVATE_DHCP_MASK = 0x01;
39constexpr auto DCMI_ACTIVATE_DHCP_REPLY = 0x00;
40constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE = 0x05;
41constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE = 0x04;
Patrick Venture0b02be92018-08-31 11:55:55 -070042constexpr auto DHCP_TIMING1 = 0x04; // 4 sec
43constexpr auto DHCP_TIMING2_UPPER = 0x00; // 2 min
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060044constexpr auto DHCP_TIMING2_LOWER = 0x78;
Patrick Venture0b02be92018-08-31 11:55:55 -070045constexpr auto DHCP_TIMING3_UPPER = 0x00; // 64 sec
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060046constexpr auto DHCP_TIMING3_LOWER = 0x40;
47// When DHCP Option 12 is enabled the string "SendHostName=true" will be
48// added into n/w configuration file and the parameter
49// SendHostNameEnabled will set to true.
50constexpr auto DHCP_OPT12_ENABLED = "SendHostNameEnabled";
51
Marri Devender Rao66c5fda2018-01-18 10:48:37 -060052constexpr auto SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
53constexpr auto SENSOR_VALUE_PROP = "Value";
54constexpr auto SENSOR_SCALE_PROP = "Scale";
55
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050056using namespace phosphor::logging;
57
Tom Josephb9d86f42017-07-26 18:03:47 +053058namespace dcmi
59{
60
Deepak Kodihalli0b459552018-02-06 06:25:12 -060061// Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
Patrick Venture0b02be92018-08-31 11:55:55 -070062static const std::map<uint8_t, std::string> entityIdToName{
63 {0x40, "inlet"}, {0x37, "inlet"}, {0x41, "cpu"},
64 {0x03, "cpu"}, {0x42, "baseboard"}, {0x07, "baseboard"}};
Deepak Kodihalli0b459552018-02-06 06:25:12 -060065
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +030066bool isDCMIPowerMgmtSupported()
67{
68 auto data = parseJSONConfig(gDCMICapabilitiesConfig);
69
70 return (gDCMIPowerMgmtSupported == data.value(gDCMIPowerMgmtCapability, 0));
71}
72
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050073uint32_t getPcap(sdbusplus::bus::bus& bus)
74{
Patrick Venture0b02be92018-08-31 11:55:55 -070075 auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050076
Patrick Venture0b02be92018-08-31 11:55:55 -070077 auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH,
78 "org.freedesktop.DBus.Properties", "Get");
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050079
80 method.append(PCAP_INTERFACE, POWER_CAP_PROP);
81 auto reply = bus.call(method);
82
83 if (reply.is_method_error())
84 {
85 log<level::ERR>("Error in getPcap prop");
Tom Josephb9d86f42017-07-26 18:03:47 +053086 elog<InternalFailure>();
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050087 }
88 sdbusplus::message::variant<uint32_t> pcap;
89 reply.read(pcap);
90
Vernon Maueryf442e112019-04-09 11:44:36 -070091 return std::get<uint32_t>(pcap);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050092}
93
94bool getPcapEnabled(sdbusplus::bus::bus& bus)
95{
Patrick Venture0b02be92018-08-31 11:55:55 -070096 auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050097
Patrick Venture0b02be92018-08-31 11:55:55 -070098 auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH,
99 "org.freedesktop.DBus.Properties", "Get");
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500100
101 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
102 auto reply = bus.call(method);
103
104 if (reply.is_method_error())
105 {
106 log<level::ERR>("Error in getPcapEnabled prop");
Tom Josephb9d86f42017-07-26 18:03:47 +0530107 elog<InternalFailure>();
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500108 }
109 sdbusplus::message::variant<bool> pcapEnabled;
110 reply.read(pcapEnabled);
111
Vernon Maueryf442e112019-04-09 11:44:36 -0700112 return std::get<bool>(pcapEnabled);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500113}
Chris Austen1810bec2015-10-13 12:12:39 -0500114
Tom Joseph46fa37d2017-07-26 18:11:55 +0530115void setPcap(sdbusplus::bus::bus& bus, const uint32_t powerCap)
116{
117 auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
118
Patrick Venture0b02be92018-08-31 11:55:55 -0700119 auto method = bus.new_method_call(service.c_str(), PCAP_PATH,
120 "org.freedesktop.DBus.Properties", "Set");
Tom Joseph46fa37d2017-07-26 18:11:55 +0530121
122 method.append(PCAP_INTERFACE, POWER_CAP_PROP);
123 method.append(sdbusplus::message::variant<uint32_t>(powerCap));
124
125 auto reply = bus.call(method);
126
127 if (reply.is_method_error())
128 {
129 log<level::ERR>("Error in setPcap property");
130 elog<InternalFailure>();
131 }
132}
133
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530134void setPcapEnable(sdbusplus::bus::bus& bus, bool enabled)
135{
136 auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
137
Patrick Venture0b02be92018-08-31 11:55:55 -0700138 auto method = bus.new_method_call(service.c_str(), PCAP_PATH,
139 "org.freedesktop.DBus.Properties", "Set");
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530140
141 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
142 method.append(sdbusplus::message::variant<bool>(enabled));
143
144 auto reply = bus.call(method);
145
146 if (reply.is_method_error())
147 {
148 log<level::ERR>("Error in setPcapEnabled property");
149 elog<InternalFailure>();
150 }
151}
152
Tom Josephbe5eaa12017-07-12 19:54:44 +0530153void readAssetTagObjectTree(dcmi::assettag::ObjectTree& objectTree)
154{
155 static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
156 static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
157 static constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper";
158 static constexpr auto inventoryRoot = "/xyz/openbmc_project/inventory/";
159
160 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
161 auto depth = 0;
162
Patrick Venture0b02be92018-08-31 11:55:55 -0700163 auto mapperCall = bus.new_method_call(mapperBusName, mapperObjPath,
164 mapperIface, "GetSubTree");
Tom Josephbe5eaa12017-07-12 19:54:44 +0530165
166 mapperCall.append(inventoryRoot);
167 mapperCall.append(depth);
168 mapperCall.append(std::vector<std::string>({dcmi::assetTagIntf}));
169
170 auto mapperReply = bus.call(mapperCall);
171 if (mapperReply.is_method_error())
172 {
173 log<level::ERR>("Error in mapper call");
174 elog<InternalFailure>();
175 }
176
177 mapperReply.read(objectTree);
178
179 if (objectTree.empty())
180 {
181 log<level::ERR>("AssetTag property is not populated");
182 elog<InternalFailure>();
183 }
184}
185
186std::string readAssetTag()
187{
188 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
189 dcmi::assettag::ObjectTree objectTree;
190
191 // Read the object tree with the inventory root to figure out the object
192 // that has implemented the Asset tag interface.
193 readAssetTagObjectTree(objectTree);
194
195 auto method = bus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -0700196 (objectTree.begin()->second.begin()->first).c_str(),
197 (objectTree.begin()->first).c_str(), dcmi::propIntf, "Get");
Tom Josephbe5eaa12017-07-12 19:54:44 +0530198 method.append(dcmi::assetTagIntf);
199 method.append(dcmi::assetTagProp);
200
201 auto reply = bus.call(method);
202 if (reply.is_method_error())
203 {
204 log<level::ERR>("Error in reading asset tag");
205 elog<InternalFailure>();
206 }
207
208 sdbusplus::message::variant<std::string> assetTag;
209 reply.read(assetTag);
210
Vernon Maueryf442e112019-04-09 11:44:36 -0700211 return std::get<std::string>(assetTag);
Tom Josephbe5eaa12017-07-12 19:54:44 +0530212}
213
Tom Josephbe5b9892017-07-15 00:55:23 +0530214void writeAssetTag(const std::string& assetTag)
215{
216 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
217 dcmi::assettag::ObjectTree objectTree;
218
219 // Read the object tree with the inventory root to figure out the object
220 // that has implemented the Asset tag interface.
221 readAssetTagObjectTree(objectTree);
222
223 auto method = bus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -0700224 (objectTree.begin()->second.begin()->first).c_str(),
225 (objectTree.begin()->first).c_str(), dcmi::propIntf, "Set");
Tom Josephbe5b9892017-07-15 00:55:23 +0530226 method.append(dcmi::assetTagIntf);
227 method.append(dcmi::assetTagProp);
228 method.append(sdbusplus::message::variant<std::string>(assetTag));
229
230 auto reply = bus.call(method);
231 if (reply.is_method_error())
232 {
233 log<level::ERR>("Error in writing asset tag");
234 elog<InternalFailure>();
235 }
236}
237
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300238std::string getHostName(void)
239{
Patrick Venture0b02be92018-08-31 11:55:55 -0700240 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300241
242 auto service = ipmi::getService(bus, networkConfigIntf, networkConfigObj);
Patrick Venture0b02be92018-08-31 11:55:55 -0700243 auto value = ipmi::getDbusProperty(bus, service, networkConfigObj,
244 networkConfigIntf, hostNameProp);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300245
Vernon Maueryf442e112019-04-09 11:44:36 -0700246 return std::get<std::string>(value);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300247}
248
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600249bool getDHCPEnabled()
250{
251 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
252
Johnathan Mantey74a21022018-12-13 13:17:56 -0800253 auto ethdevice = ipmi::getChannelName(ethernetDefaultChannelNum);
Patrick Venture0b02be92018-08-31 11:55:55 -0700254 auto ethernetObj =
255 ipmi::getDbusObject(bus, ethernetIntf, networkRoot, ethdevice);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600256 auto service = ipmi::getService(bus, ethernetIntf, ethernetObj.first);
Patrick Venture0b02be92018-08-31 11:55:55 -0700257 auto value = ipmi::getDbusProperty(bus, service, ethernetObj.first,
258 ethernetIntf, "DHCPEnabled");
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600259
Vernon Maueryf442e112019-04-09 11:44:36 -0700260 return std::get<bool>(value);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600261}
262
263bool getDHCPOption(std::string prop)
264{
265 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
266
267 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
268 auto value = ipmi::getDbusProperty(bus, service, dhcpObj, dhcpIntf, prop);
269
Vernon Maueryf442e112019-04-09 11:44:36 -0700270 return std::get<bool>(value);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600271}
272
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600273void setDHCPOption(std::string prop, bool value)
274{
275 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
276
277 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
278 ipmi::setDbusProperty(bus, service, dhcpObj, dhcpIntf, prop, value);
279}
280
Kirill Pakhomova2573622018-11-02 19:00:18 +0300281Json parseJSONConfig(const std::string& configFile)
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600282{
283 std::ifstream jsonFile(configFile);
284 if (!jsonFile.is_open())
285 {
286 log<level::ERR>("Temperature readings JSON file not found");
287 elog<InternalFailure>();
288 }
289
290 auto data = Json::parse(jsonFile, nullptr, false);
291 if (data.is_discarded())
292 {
293 log<level::ERR>("Temperature readings JSON parser failure");
294 elog<InternalFailure>();
295 }
296
297 return data;
298}
299
Tom Josephbe5eaa12017-07-12 19:54:44 +0530300} // namespace dcmi
Chris Austen1810bec2015-10-13 12:12:39 -0500301
Tom Josephb9d86f42017-07-26 18:03:47 +0530302ipmi_ret_t getPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
303 ipmi_request_t request, ipmi_response_t response,
304 ipmi_data_len_t data_len, ipmi_context_t context)
305{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300306 if (!dcmi::isDCMIPowerMgmtSupported())
307 {
308 *data_len = 0;
309 log<level::ERR>("DCMI Power management is unsupported!");
310 return IPMI_CC_INVALID;
311 }
312
Patrick Venture0b02be92018-08-31 11:55:55 -0700313 auto requestData =
314 reinterpret_cast<const dcmi::GetPowerLimitRequest*>(request);
Tom Josephb9d86f42017-07-26 18:03:47 +0530315 std::vector<uint8_t> outPayload(sizeof(dcmi::GetPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700316 auto responseData =
317 reinterpret_cast<dcmi::GetPowerLimitResponse*>(outPayload.data());
Tom Josephb9d86f42017-07-26 18:03:47 +0530318
319 if (requestData->groupID != dcmi::groupExtId)
320 {
321 *data_len = 0;
322 return IPMI_CC_INVALID_FIELD_REQUEST;
323 }
324
Patrick Venture0b02be92018-08-31 11:55:55 -0700325 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Josephb9d86f42017-07-26 18:03:47 +0530326 uint32_t pcapValue = 0;
327 bool pcapEnable = false;
328
329 try
330 {
331 pcapValue = dcmi::getPcap(sdbus);
332 pcapEnable = dcmi::getPcapEnabled(sdbus);
333 }
334 catch (InternalFailure& e)
335 {
336 *data_len = 0;
337 return IPMI_CC_UNSPECIFIED_ERROR;
338 }
339
340 responseData->groupID = dcmi::groupExtId;
341
342 /*
343 * Exception action if power limit is exceeded and cannot be controlled
344 * with the correction time limit is hardcoded to Hard Power Off system
345 * and log event to SEL.
346 */
347 constexpr auto exception = 0x01;
348 responseData->exceptionAction = exception;
349
350 responseData->powerLimit = static_cast<uint16_t>(pcapValue);
351
352 /*
353 * Correction time limit and Statistics sampling period is currently not
354 * populated.
355 */
356
357 *data_len = outPayload.size();
358 memcpy(response, outPayload.data(), *data_len);
359
360 if (pcapEnable)
361 {
362 return IPMI_CC_OK;
363 }
364 else
365 {
366 return IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT;
367 }
368}
369
Tom Joseph46fa37d2017-07-26 18:11:55 +0530370ipmi_ret_t setPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
371 ipmi_request_t request, ipmi_response_t response,
372 ipmi_data_len_t data_len, ipmi_context_t context)
373{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300374 if (!dcmi::isDCMIPowerMgmtSupported())
375 {
376 *data_len = 0;
377 log<level::ERR>("DCMI Power management is unsupported!");
378 return IPMI_CC_INVALID;
379 }
380
Patrick Venture0b02be92018-08-31 11:55:55 -0700381 auto requestData =
382 reinterpret_cast<const dcmi::SetPowerLimitRequest*>(request);
Tom Joseph46fa37d2017-07-26 18:11:55 +0530383 std::vector<uint8_t> outPayload(sizeof(dcmi::SetPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700384 auto responseData =
385 reinterpret_cast<dcmi::SetPowerLimitResponse*>(outPayload.data());
Tom Joseph46fa37d2017-07-26 18:11:55 +0530386
387 if (requestData->groupID != dcmi::groupExtId)
388 {
389 *data_len = 0;
390 return IPMI_CC_INVALID_FIELD_REQUEST;
391 }
392
Patrick Venture0b02be92018-08-31 11:55:55 -0700393 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Joseph46fa37d2017-07-26 18:11:55 +0530394
395 // Only process the power limit requested in watts.
396 try
397 {
398 dcmi::setPcap(sdbus, requestData->powerLimit);
399 }
400 catch (InternalFailure& e)
401 {
402 *data_len = 0;
403 return IPMI_CC_UNSPECIFIED_ERROR;
404 }
405
406 log<level::INFO>("Set Power Cap",
407 entry("POWERCAP=%u", requestData->powerLimit));
408
409 responseData->groupID = dcmi::groupExtId;
410 memcpy(response, outPayload.data(), outPayload.size());
411 *data_len = outPayload.size();
412
413 return IPMI_CC_OK;
414}
415
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530416ipmi_ret_t applyPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
417 ipmi_request_t request, ipmi_response_t response,
418 ipmi_data_len_t data_len, ipmi_context_t context)
419{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300420 if (!dcmi::isDCMIPowerMgmtSupported())
421 {
422 *data_len = 0;
423 log<level::ERR>("DCMI Power management is unsupported!");
424 return IPMI_CC_INVALID;
425 }
426
Patrick Venture0b02be92018-08-31 11:55:55 -0700427 auto requestData =
428 reinterpret_cast<const dcmi::ApplyPowerLimitRequest*>(request);
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530429 std::vector<uint8_t> outPayload(sizeof(dcmi::ApplyPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700430 auto responseData =
431 reinterpret_cast<dcmi::ApplyPowerLimitResponse*>(outPayload.data());
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530432
433 if (requestData->groupID != dcmi::groupExtId)
434 {
435 *data_len = 0;
436 return IPMI_CC_INVALID_FIELD_REQUEST;
437 }
438
Patrick Venture0b02be92018-08-31 11:55:55 -0700439 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530440
441 try
442 {
443 dcmi::setPcapEnable(sdbus,
444 static_cast<bool>(requestData->powerLimitAction));
445 }
446 catch (InternalFailure& e)
447 {
448 *data_len = 0;
449 return IPMI_CC_UNSPECIFIED_ERROR;
450 }
451
452 log<level::INFO>("Set Power Cap Enable",
453 entry("POWERCAPENABLE=%u", requestData->powerLimitAction));
454
455 responseData->groupID = dcmi::groupExtId;
456 memcpy(response, outPayload.data(), outPayload.size());
457 *data_len = outPayload.size();
458
459 return IPMI_CC_OK;
460}
461
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530462ipmi_ret_t getAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
463 ipmi_request_t request, ipmi_response_t response,
464 ipmi_data_len_t data_len, ipmi_context_t context)
465{
Patrick Venture0b02be92018-08-31 11:55:55 -0700466 auto requestData =
467 reinterpret_cast<const dcmi::GetAssetTagRequest*>(request);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530468 std::vector<uint8_t> outPayload(sizeof(dcmi::GetAssetTagResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700469 auto responseData =
470 reinterpret_cast<dcmi::GetAssetTagResponse*>(outPayload.data());
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530471
472 if (requestData->groupID != dcmi::groupExtId)
473 {
474 *data_len = 0;
475 return IPMI_CC_INVALID_FIELD_REQUEST;
476 }
477
478 // Verify offset to read and number of bytes to read are not exceeding the
479 // range.
480 if ((requestData->offset > dcmi::assetTagMaxOffset) ||
481 (requestData->bytes > dcmi::maxBytes) ||
482 ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize))
483 {
484 *data_len = 0;
485 return IPMI_CC_PARM_OUT_OF_RANGE;
486 }
487
488 std::string assetTag;
489
490 try
491 {
492 assetTag = dcmi::readAssetTag();
493 }
494 catch (InternalFailure& e)
495 {
496 *data_len = 0;
497 return IPMI_CC_UNSPECIFIED_ERROR;
498 }
499
500 responseData->groupID = dcmi::groupExtId;
501
502 // Return if the asset tag is not populated.
503 if (!assetTag.size())
504 {
505 responseData->tagLength = 0;
506 memcpy(response, outPayload.data(), outPayload.size());
507 *data_len = outPayload.size();
508 return IPMI_CC_OK;
509 }
510
511 // If the asset tag is longer than 63 bytes, restrict it to 63 bytes to suit
512 // Get Asset Tag command.
513 if (assetTag.size() > dcmi::assetTagMaxSize)
514 {
515 assetTag.resize(dcmi::assetTagMaxSize);
516 }
517
518 // If the requested offset is beyond the asset tag size.
519 if (requestData->offset >= assetTag.size())
520 {
521 *data_len = 0;
522 return IPMI_CC_PARM_OUT_OF_RANGE;
523 }
524
525 auto returnData = assetTag.substr(requestData->offset, requestData->bytes);
526
527 responseData->tagLength = assetTag.size();
528
529 memcpy(response, outPayload.data(), outPayload.size());
530 memcpy(static_cast<uint8_t*>(response) + outPayload.size(),
531 returnData.data(), returnData.size());
532 *data_len = outPayload.size() + returnData.size();
533
534 return IPMI_CC_OK;
535}
536
Tom Joseph545dd232017-07-12 20:20:49 +0530537ipmi_ret_t setAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
538 ipmi_request_t request, ipmi_response_t response,
539 ipmi_data_len_t data_len, ipmi_context_t context)
540{
Patrick Venture0b02be92018-08-31 11:55:55 -0700541 auto requestData =
542 reinterpret_cast<const dcmi::SetAssetTagRequest*>(request);
Tom Joseph545dd232017-07-12 20:20:49 +0530543 std::vector<uint8_t> outPayload(sizeof(dcmi::SetAssetTagResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700544 auto responseData =
545 reinterpret_cast<dcmi::SetAssetTagResponse*>(outPayload.data());
Tom Joseph545dd232017-07-12 20:20:49 +0530546
547 if (requestData->groupID != dcmi::groupExtId)
548 {
549 *data_len = 0;
550 return IPMI_CC_INVALID_FIELD_REQUEST;
551 }
552
553 // Verify offset to read and number of bytes to read are not exceeding the
554 // range.
555 if ((requestData->offset > dcmi::assetTagMaxOffset) ||
556 (requestData->bytes > dcmi::maxBytes) ||
557 ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize))
558 {
559 *data_len = 0;
560 return IPMI_CC_PARM_OUT_OF_RANGE;
561 }
562
563 std::string assetTag;
564
565 try
566 {
567 assetTag = dcmi::readAssetTag();
568
569 if (requestData->offset > assetTag.size())
570 {
571 *data_len = 0;
572 return IPMI_CC_PARM_OUT_OF_RANGE;
573 }
574
575 assetTag.replace(requestData->offset,
576 assetTag.size() - requestData->offset,
577 static_cast<const char*>(request) +
Patrick Venture0b02be92018-08-31 11:55:55 -0700578 sizeof(dcmi::SetAssetTagRequest),
Tom Joseph545dd232017-07-12 20:20:49 +0530579 requestData->bytes);
580
581 dcmi::writeAssetTag(assetTag);
582
583 responseData->groupID = dcmi::groupExtId;
584 responseData->tagLength = assetTag.size();
585 memcpy(response, outPayload.data(), outPayload.size());
586 *data_len = outPayload.size();
587
588 return IPMI_CC_OK;
589 }
590 catch (InternalFailure& e)
591 {
592 *data_len = 0;
593 return IPMI_CC_UNSPECIFIED_ERROR;
594 }
595}
596
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300597ipmi_ret_t getMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700598 ipmi_request_t request, ipmi_response_t response,
599 ipmi_data_len_t data_len, ipmi_context_t context)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300600{
Patrick Venture0b02be92018-08-31 11:55:55 -0700601 auto requestData =
602 reinterpret_cast<const dcmi::GetMgmntCtrlIdStrRequest*>(request);
603 auto responseData =
604 reinterpret_cast<dcmi::GetMgmntCtrlIdStrResponse*>(response);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300605 std::string hostName;
606
607 *data_len = 0;
608
609 if (requestData->groupID != dcmi::groupExtId ||
610 requestData->bytes > dcmi::maxBytes ||
611 requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen)
612 {
613 return IPMI_CC_INVALID_FIELD_REQUEST;
614 }
615
616 try
617 {
618 hostName = dcmi::getHostName();
619 }
620 catch (InternalFailure& e)
621 {
622 return IPMI_CC_UNSPECIFIED_ERROR;
623 }
624
625 if (requestData->offset > hostName.length())
626 {
627 return IPMI_CC_PARM_OUT_OF_RANGE;
628 }
629 auto responseStr = hostName.substr(requestData->offset, requestData->bytes);
630 auto responseStrLen = std::min(static_cast<std::size_t>(requestData->bytes),
Patrick Venture0b02be92018-08-31 11:55:55 -0700631 responseStr.length() + 1);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300632 responseData->groupID = dcmi::groupExtId;
633 responseData->strLen = hostName.length();
634 std::copy(begin(responseStr), end(responseStr), responseData->data);
635
636 *data_len = sizeof(*responseData) + responseStrLen;
637 return IPMI_CC_OK;
638}
639
640ipmi_ret_t setMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700641 ipmi_request_t request, ipmi_response_t response,
642 ipmi_data_len_t data_len, ipmi_context_t context)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300643{
644 static std::array<char, dcmi::maxCtrlIdStrLen + 1> newCtrlIdStr;
645
Patrick Venture0b02be92018-08-31 11:55:55 -0700646 auto requestData =
647 reinterpret_cast<const dcmi::SetMgmntCtrlIdStrRequest*>(request);
648 auto responseData =
649 reinterpret_cast<dcmi::SetMgmntCtrlIdStrResponse*>(response);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300650
651 *data_len = 0;
652
653 if (requestData->groupID != dcmi::groupExtId ||
654 requestData->bytes > dcmi::maxBytes ||
655 requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen + 1 ||
Patrick Venture0b02be92018-08-31 11:55:55 -0700656 (requestData->offset + requestData->bytes ==
657 dcmi::maxCtrlIdStrLen + 1 &&
658 requestData->data[requestData->bytes - 1] != '\0'))
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300659 {
660 return IPMI_CC_INVALID_FIELD_REQUEST;
661 }
662
663 try
664 {
665 /* if there is no old value and offset is not 0 */
666 if (newCtrlIdStr[0] == '\0' && requestData->offset != 0)
667 {
668 /* read old ctrlIdStr */
669 auto hostName = dcmi::getHostName();
670 hostName.resize(dcmi::maxCtrlIdStrLen);
671 std::copy(begin(hostName), end(hostName), begin(newCtrlIdStr));
672 newCtrlIdStr[hostName.length()] = '\0';
673 }
674
675 /* replace part of string and mark byte after the last as \0 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700676 auto restStrIter =
677 std::copy_n(requestData->data, requestData->bytes,
678 begin(newCtrlIdStr) + requestData->offset);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300679 /* if the last written byte is not 64th - add '\0' */
680 if (requestData->offset + requestData->bytes <= dcmi::maxCtrlIdStrLen)
681 {
682 *restStrIter = '\0';
683 }
684
685 /* if input data contains '\0' whole string is sent - update hostname */
686 auto it = std::find(requestData->data,
Patrick Venture0b02be92018-08-31 11:55:55 -0700687 requestData->data + requestData->bytes, '\0');
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300688 if (it != requestData->data + requestData->bytes)
689 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700690 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300691 ipmi::setDbusProperty(bus, dcmi::networkServiceName,
Patrick Venture0b02be92018-08-31 11:55:55 -0700692 dcmi::networkConfigObj,
693 dcmi::networkConfigIntf, dcmi::hostNameProp,
694 std::string(newCtrlIdStr.data()));
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300695 }
696 }
697 catch (InternalFailure& e)
698 {
699 *data_len = 0;
700 return IPMI_CC_UNSPECIFIED_ERROR;
701 }
702
703 responseData->groupID = dcmi::groupExtId;
704 responseData->offset = requestData->offset + requestData->bytes;
705 *data_len = sizeof(*responseData);
706 return IPMI_CC_OK;
707}
708
Patrick Venture0b02be92018-08-31 11:55:55 -0700709// List of the capabilities under each parameter
710dcmi::DCMICaps dcmiCaps = {
711 // Supported DCMI Capabilities
712 {dcmi::DCMICapParameters::SUPPORTED_DCMI_CAPS,
713 {3,
714 {{"PowerManagement", 2, 0, 1},
715 {"OOBSecondaryLan", 3, 2, 1},
716 {"SerialTMODE", 3, 1, 1},
717 {"InBandSystemInterfaceChannel", 3, 0, 1}}}},
718 // Mandatory Platform Attributes
719 {dcmi::DCMICapParameters::MANDATORY_PLAT_ATTRIBUTES,
720 {5,
721 {{"SELAutoRollOver", 1, 15, 1},
722 {"FlushEntireSELUponRollOver", 1, 14, 1},
723 {"RecordLevelSELFlushUponRollOver", 1, 13, 1},
724 {"NumberOfSELEntries", 1, 0, 12},
725 {"TempMonitoringSamplingFreq", 5, 0, 8}}}},
726 // Optional Platform Attributes
727 {dcmi::DCMICapParameters::OPTIONAL_PLAT_ATTRIBUTES,
728 {2,
729 {{"PowerMgmtDeviceSlaveAddress", 1, 1, 7},
730 {"BMCChannelNumber", 2, 4, 4},
731 {"DeviceRivision", 2, 0, 4}}}},
732 // Manageability Access Attributes
733 {dcmi::DCMICapParameters::MANAGEABILITY_ACCESS_ATTRIBUTES,
734 {3,
735 {{"MandatoryPrimaryLanOOBSupport", 1, 0, 8},
736 {"OptionalSecondaryLanOOBSupport", 2, 0, 8},
737 {"OptionalSerialOOBMTMODECapability", 3, 0, 8}}}}};
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600738
739ipmi_ret_t getDCMICapabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
740 ipmi_request_t request, ipmi_response_t response,
741 ipmi_data_len_t data_len, ipmi_context_t context)
742{
743
Kirill Pakhomova2573622018-11-02 19:00:18 +0300744 std::ifstream dcmiCapFile(dcmi::gDCMICapabilitiesConfig);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600745 if (!dcmiCapFile.is_open())
746 {
747 log<level::ERR>("DCMI Capabilities file not found");
748 return IPMI_CC_UNSPECIFIED_ERROR;
749 }
750
751 auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false);
752 if (data.is_discarded())
753 {
754 log<level::ERR>("DCMI Capabilities JSON parser failure");
755 return IPMI_CC_UNSPECIFIED_ERROR;
756 }
757
Patrick Venture0b02be92018-08-31 11:55:55 -0700758 auto requestData =
759 reinterpret_cast<const dcmi::GetDCMICapRequest*>(request);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600760
Patrick Venture0b02be92018-08-31 11:55:55 -0700761 // get list of capabilities in a parameter
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600762 auto caps =
763 dcmiCaps.find(static_cast<dcmi::DCMICapParameters>(requestData->param));
764 if (caps == dcmiCaps.end())
765 {
766 log<level::ERR>("Invalid input parameter");
767 return IPMI_CC_INVALID_FIELD_REQUEST;
768 }
769
770 if (requestData->groupID != dcmi::groupExtId)
771 {
772 *data_len = 0;
773 return IPMI_CC_INVALID_FIELD_REQUEST;
774 }
775
Patrick Venture0b02be92018-08-31 11:55:55 -0700776 auto responseData = reinterpret_cast<dcmi::GetDCMICapResponse*>(response);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600777
Patrick Venture0b02be92018-08-31 11:55:55 -0700778 // For each capabilities in a parameter fill the data from
779 // the json file based on the capability name.
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600780 for (auto cap : caps->second.capList)
781 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700782 // If the data is beyond first byte boundary, insert in a
783 // 16bit pattern for example number of SEL entries are represented
784 // in 12bits.
Kirill Pakhomovdb5d9b02018-11-06 19:17:51 +0300785 if ((cap.length + cap.position) > dcmi::gByteBitSize)
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600786 {
Kirill Pakhomovdb5d9b02018-11-06 19:17:51 +0300787 uint16_t val = data.value(cap.name.c_str(), 0);
788 // According to DCMI spec v1.5, max number of SEL entries is
789 // 4096, but bit 12b of DCMI capabilities Mandatory Platform
790 // Attributes field is reserved and therefore we can use only
791 // the provided 12 bits with maximum value of 4095.
792 // We're playing safe here by applying the mask
793 // to ensure that provided value will fit into 12 bits.
794 if (cap.length > dcmi::gByteBitSize)
795 {
796 val &= dcmi::gMaxSELEntriesMask;
797 }
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600798 val <<= cap.position;
Kirill Pakhomovdb5d9b02018-11-06 19:17:51 +0300799 responseData->data[cap.bytePosition - 1] |=
800 static_cast<uint8_t>(val);
801 responseData->data[cap.bytePosition] |= val >> dcmi::gByteBitSize;
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600802 }
803 else
804 {
805 responseData->data[cap.bytePosition - 1] |=
806 data.value(cap.name.c_str(), 0) << cap.position;
807 }
808 }
809
810 responseData->groupID = dcmi::groupExtId;
811 responseData->major = DCMI_SPEC_MAJOR_VERSION;
812 responseData->minor = DCMI_SPEC_MINOR_VERSION;
813 responseData->paramRevision = DCMI_PARAMETER_REVISION;
814 *data_len = sizeof(*responseData) + caps->second.size;
815
816 return IPMI_CC_OK;
817}
818
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600819namespace dcmi
820{
821namespace temp_readings
822{
823
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600824Temperature readTemp(const std::string& dbusService,
825 const std::string& dbusPath)
826{
827 // Read the temperature value from d-bus object. Need some conversion.
828 // As per the interface xyz.openbmc_project.Sensor.Value, the temperature
James Feist9cc0ea52018-10-09 10:53:11 -0700829 // is an double and in degrees C. It needs to be scaled by using the
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600830 // formula Value * 10^Scale. The ipmi spec has the temperature as a uint8_t,
831 // with a separate single bit for the sign.
832
833 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700834 auto result = ipmi::getAllDbusProperties(
835 bus, dbusService, dbusPath, "xyz.openbmc_project.Sensor.Value");
Vernon Maueryf442e112019-04-09 11:44:36 -0700836 auto temperature =
837 std::visit(ipmi::VariantToDoubleVisitor(), result.at("Value"));
James Feist9cc0ea52018-10-09 10:53:11 -0700838 double absTemp = std::abs(temperature);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600839
James Feist9cc0ea52018-10-09 10:53:11 -0700840 auto findFactor = result.find("Scale");
841 double factor = 0.0;
842 if (findFactor != result.end())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600843 {
Vernon Maueryf442e112019-04-09 11:44:36 -0700844 factor = std::visit(ipmi::VariantToDoubleVisitor(), findFactor->second);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600845 }
James Feist9cc0ea52018-10-09 10:53:11 -0700846 double scale = std::pow(10, factor);
847
848 auto tempDegrees = absTemp * scale;
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600849 // Max absolute temp as per ipmi spec is 128.
850 if (tempDegrees > maxTemp)
851 {
852 tempDegrees = maxTemp;
853 }
854
855 return std::make_tuple(static_cast<uint8_t>(tempDegrees),
856 (temperature < 0));
857}
858
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600859std::tuple<Response, NumInstances> read(const std::string& type,
860 uint8_t instance)
861{
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600862 Response response{};
863 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
864
865 if (!instance)
866 {
867 log<level::ERR>("Expected non-zero instance");
868 elog<InternalFailure>();
869 }
870
Kirill Pakhomova2573622018-11-02 19:00:18 +0300871 auto data = parseJSONConfig(gDCMISensorsConfig);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600872 static const std::vector<Json> empty{};
873 std::vector<Json> readings = data.value(type, empty);
874 size_t numInstances = readings.size();
875 for (const auto& j : readings)
876 {
877 uint8_t instanceNum = j.value("instance", 0);
878 // Not the instance we're interested in
879 if (instanceNum != instance)
880 {
881 continue;
882 }
883
884 std::string path = j.value("dbus", "");
885 std::string service;
886 try
887 {
888 service =
Patrick Venture0b02be92018-08-31 11:55:55 -0700889 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600890 }
891 catch (std::exception& e)
892 {
893 log<level::DEBUG>(e.what());
894 return std::make_tuple(response, numInstances);
895 }
896
897 response.instance = instance;
898 uint8_t temp{};
899 bool sign{};
900 std::tie(temp, sign) = readTemp(service, path);
901 response.temperature = temp;
902 response.sign = sign;
903
904 // Found the instance we're interested in
905 break;
906 }
907
908 if (numInstances > maxInstances)
909 {
910 numInstances = maxInstances;
911 }
912 return std::make_tuple(response, numInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600913}
914
915std::tuple<ResponseList, NumInstances> readAll(const std::string& type,
916 uint8_t instanceStart)
917{
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600918 ResponseList response{};
919 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
920
921 size_t numInstances = 0;
Kirill Pakhomova2573622018-11-02 19:00:18 +0300922 auto data = parseJSONConfig(gDCMISensorsConfig);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600923 static const std::vector<Json> empty{};
924 std::vector<Json> readings = data.value(type, empty);
925 numInstances = readings.size();
926 for (const auto& j : readings)
927 {
928 try
929 {
930 // Max of 8 response data sets
931 if (response.size() == maxDataSets)
932 {
933 break;
934 }
935
936 uint8_t instanceNum = j.value("instance", 0);
937 // Not in the instance range we're interested in
938 if (instanceNum < instanceStart)
939 {
940 continue;
941 }
942
943 std::string path = j.value("dbus", "");
944 auto service =
Patrick Venture0b02be92018-08-31 11:55:55 -0700945 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600946
947 Response r{};
948 r.instance = instanceNum;
949 uint8_t temp{};
950 bool sign{};
951 std::tie(temp, sign) = readTemp(service, path);
952 r.temperature = temp;
953 r.sign = sign;
954 response.push_back(r);
955 }
956 catch (std::exception& e)
957 {
958 log<level::DEBUG>(e.what());
959 continue;
960 }
961 }
962
963 if (numInstances > maxInstances)
964 {
965 numInstances = maxInstances;
966 }
967 return std::make_tuple(response, numInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600968}
969
Patrick Venture0b02be92018-08-31 11:55:55 -0700970} // namespace temp_readings
971} // namespace dcmi
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600972
973ipmi_ret_t getTempReadings(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700974 ipmi_request_t request, ipmi_response_t response,
975 ipmi_data_len_t data_len, ipmi_context_t context)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600976{
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600977 auto requestData =
978 reinterpret_cast<const dcmi::GetTempReadingsRequest*>(request);
979 auto responseData =
980 reinterpret_cast<dcmi::GetTempReadingsResponseHdr*>(response);
981
982 if (*data_len != sizeof(dcmi::GetTempReadingsRequest))
983 {
984 log<level::ERR>("Malformed request data",
985 entry("DATA_SIZE=%d", *data_len));
986 return IPMI_CC_REQ_DATA_LEN_INVALID;
987 }
988 *data_len = 0;
989
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600990 auto it = dcmi::entityIdToName.find(requestData->entityId);
991 if (it == dcmi::entityIdToName.end())
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600992 {
993 log<level::ERR>("Unknown Entity ID",
994 entry("ENTITY_ID=%d", requestData->entityId));
995 return IPMI_CC_INVALID_FIELD_REQUEST;
996 }
997
998 if (requestData->groupID != dcmi::groupExtId)
999 {
1000 log<level::ERR>("Invalid Group ID",
1001 entry("GROUP_ID=%d", requestData->groupID));
1002 return IPMI_CC_INVALID_FIELD_REQUEST;
1003 }
1004
1005 if (requestData->sensorType != dcmi::temperatureSensorType)
1006 {
1007 log<level::ERR>("Invalid sensor type",
1008 entry("SENSOR_TYPE=%d", requestData->sensorType));
1009 return IPMI_CC_INVALID_FIELD_REQUEST;
1010 }
1011
1012 dcmi::temp_readings::ResponseList temps{};
1013 try
1014 {
1015 if (!requestData->entityInstance)
1016 {
1017 // Read all instances
1018 std::tie(temps, responseData->numInstances) =
1019 dcmi::temp_readings::readAll(it->second,
1020 requestData->instanceStart);
1021 }
1022 else
1023 {
1024 // Read one instance
1025 temps.resize(1);
1026 std::tie(temps[0], responseData->numInstances) =
1027 dcmi::temp_readings::read(it->second,
1028 requestData->entityInstance);
1029 }
1030 responseData->numDataSets = temps.size();
1031 }
1032 catch (InternalFailure& e)
1033 {
1034 return IPMI_CC_UNSPECIFIED_ERROR;
1035 }
1036
1037 responseData->groupID = dcmi::groupExtId;
Patrick Venture0b02be92018-08-31 11:55:55 -07001038 size_t payloadSize = temps.size() * sizeof(dcmi::temp_readings::Response);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001039 if (!temps.empty())
1040 {
1041 memcpy(responseData + 1, // copy payload right after the response header
Patrick Venture0b02be92018-08-31 11:55:55 -07001042 temps.data(), payloadSize);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001043 }
1044 *data_len = sizeof(dcmi::GetTempReadingsResponseHdr) + payloadSize;
1045
1046 return IPMI_CC_OK;
1047}
1048
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001049int64_t getPowerReading(sdbusplus::bus::bus& bus)
1050{
1051 std::ifstream sensorFile(POWER_READING_SENSOR);
1052 std::string objectPath;
1053 if (!sensorFile.is_open())
1054 {
1055 log<level::ERR>("Power reading configuration file not found",
Patrick Venture0b02be92018-08-31 11:55:55 -07001056 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001057 elog<InternalFailure>();
1058 }
1059
1060 auto data = nlohmann::json::parse(sensorFile, nullptr, false);
1061 if (data.is_discarded())
1062 {
1063 log<level::ERR>("Error in parsing configuration file",
Patrick Venture0b02be92018-08-31 11:55:55 -07001064 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001065 elog<InternalFailure>();
1066 }
1067
1068 objectPath = data.value("path", "");
1069 if (objectPath.empty())
1070 {
1071 log<level::ERR>("Power sensor D-Bus object path is empty",
1072 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
1073 elog<InternalFailure>();
1074 }
1075
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001076 // Return default value if failed to read from D-Bus object
1077 int64_t power = 0;
1078 try
1079 {
1080 auto service = ipmi::getService(bus, SENSOR_VALUE_INTF, objectPath);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001081
Patrick Venture0b02be92018-08-31 11:55:55 -07001082 // Read the sensor value and scale properties
1083 auto properties = ipmi::getAllDbusProperties(bus, service, objectPath,
1084 SENSOR_VALUE_INTF);
Vernon Maueryf442e112019-04-09 11:44:36 -07001085 auto value = std::get<int64_t>(properties[SENSOR_VALUE_PROP]);
1086 auto scale = std::get<int64_t>(properties[SENSOR_SCALE_PROP]);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001087
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001088 // Power reading needs to be scaled with the Scale value using the
1089 // formula Value * 10^Scale.
1090 power = value * std::pow(10, scale);
1091 }
1092 catch (std::exception& e)
1093 {
1094 log<level::INFO>("Failure to read power value from D-Bus object",
Patrick Venture0b02be92018-08-31 11:55:55 -07001095 entry("OBJECT_PATH=%s", objectPath.c_str()),
1096 entry("INTERFACE=%s", SENSOR_VALUE_INTF));
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001097 }
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001098 return power;
1099}
1100
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001101ipmi_ret_t setDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1102 ipmi_request_t request, ipmi_response_t response,
1103 ipmi_data_len_t data_len, ipmi_context_t context)
1104{
Patrick Venture0b02be92018-08-31 11:55:55 -07001105 auto requestData =
1106 reinterpret_cast<const dcmi::SetConfParamsRequest*>(request);
1107 auto responseData =
1108 reinterpret_cast<dcmi::SetConfParamsResponse*>(response);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001109
Patrick Venture0b02be92018-08-31 11:55:55 -07001110 if (requestData->groupID != dcmi::groupExtId ||
1111 *data_len < DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE ||
1112 *data_len > DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001113 {
Gunnar Mills8466b792018-03-23 12:18:12 -05001114 log<level::ERR>("Invalid Group ID or Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001115 entry("GROUP_ID=%d", requestData->groupID),
1116 entry("PACKET SIZE=%d", *data_len));
1117 return IPMI_CC_INVALID_FIELD_REQUEST;
1118 }
1119
1120 *data_len = 0;
1121
1122 try
1123 {
1124 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -07001125 switch (
1126 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001127 {
1128 case dcmi::DCMIConfigParameters::ActivateDHCP:
1129
1130 if ((requestData->data[0] & DCMI_ACTIVATE_DHCP_MASK) &&
Patrick Venture0b02be92018-08-31 11:55:55 -07001131 dcmi::getDHCPEnabled())
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001132 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001133 // When these conditions are met we have to trigger DHCP
1134 // protocol restart using the latest parameter settings, but
1135 // as per n/w manager design, each time when we update n/w
1136 // parameters, n/w service is restarted. So we no need to
1137 // take any action in this case.
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001138 }
1139 break;
1140
1141 case dcmi::DCMIConfigParameters::DiscoveryConfig:
1142
1143 if (requestData->data[0] & DCMI_OPTION_12_MASK)
1144 {
1145 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, true);
1146 }
1147 else
1148 {
1149 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, false);
1150 }
1151
1152 // Systemd-networkd doesn't support Random Back off
1153 if (requestData->data[0] & DCMI_RAND_BACK_OFF_MASK)
1154 {
1155 return IPMI_CC_INVALID;
1156 }
1157 break;
1158 // Systemd-networkd doesn't allow to configure DHCP timigs
1159 case dcmi::DCMIConfigParameters::DHCPTiming1:
1160 case dcmi::DCMIConfigParameters::DHCPTiming2:
1161 case dcmi::DCMIConfigParameters::DHCPTiming3:
1162 default:
1163 return IPMI_CC_INVALID;
1164 }
1165 }
1166 catch (std::exception& e)
1167 {
1168 log<level::ERR>(e.what());
1169 return IPMI_CC_UNSPECIFIED_ERROR;
1170 }
1171 responseData->groupID = dcmi::groupExtId;
1172 *data_len = sizeof(dcmi::SetConfParamsResponse);
1173
1174 return IPMI_CC_OK;
1175}
1176
1177ipmi_ret_t getDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1178 ipmi_request_t request, ipmi_response_t response,
1179 ipmi_data_len_t data_len, ipmi_context_t context)
1180{
1181
Patrick Venture0b02be92018-08-31 11:55:55 -07001182 auto requestData =
1183 reinterpret_cast<const dcmi::GetConfParamsRequest*>(request);
1184 auto responseData =
1185 reinterpret_cast<dcmi::GetConfParamsResponse*>(response);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001186
1187 responseData->data[0] = 0x00;
1188
Patrick Venture0b02be92018-08-31 11:55:55 -07001189 if (requestData->groupID != dcmi::groupExtId ||
1190 *data_len != sizeof(dcmi::GetConfParamsRequest))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001191 {
Gunnar Mills8466b792018-03-23 12:18:12 -05001192 log<level::ERR>("Invalid Group ID or Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001193 entry("GROUP_ID=%d", requestData->groupID),
1194 entry("PACKET SIZE=%d", *data_len));
1195 return IPMI_CC_INVALID_FIELD_REQUEST;
1196 }
1197
1198 *data_len = 0;
1199
1200 try
1201 {
1202 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -07001203 switch (
1204 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001205 {
1206 case dcmi::DCMIConfigParameters::ActivateDHCP:
1207 responseData->data[0] = DCMI_ACTIVATE_DHCP_REPLY;
1208 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1209 break;
1210 case dcmi::DCMIConfigParameters::DiscoveryConfig:
1211 if (dcmi::getDHCPOption(DHCP_OPT12_ENABLED))
1212 {
1213 responseData->data[0] |= DCMI_OPTION_12_MASK;
1214 }
1215 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1216 break;
1217 // Get below values from Systemd-networkd source code
1218 case dcmi::DCMIConfigParameters::DHCPTiming1:
1219 responseData->data[0] = DHCP_TIMING1;
1220 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1221 break;
1222 case dcmi::DCMIConfigParameters::DHCPTiming2:
1223 responseData->data[0] = DHCP_TIMING2_LOWER;
1224 responseData->data[1] = DHCP_TIMING2_UPPER;
1225 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
1226 break;
1227 case dcmi::DCMIConfigParameters::DHCPTiming3:
1228 responseData->data[0] = DHCP_TIMING3_LOWER;
1229 responseData->data[1] = DHCP_TIMING3_UPPER;
1230 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
1231 break;
1232 default:
1233 *data_len = 0;
1234 return IPMI_CC_INVALID;
1235 }
1236 }
1237 catch (std::exception& e)
1238 {
1239 log<level::ERR>(e.what());
1240 return IPMI_CC_UNSPECIFIED_ERROR;
1241 }
1242
1243 responseData->groupID = dcmi::groupExtId;
1244 responseData->major = DCMI_SPEC_MAJOR_VERSION;
1245 responseData->minor = DCMI_SPEC_MINOR_VERSION;
1246 responseData->paramRevision = DCMI_CONFIG_PARAMETER_REVISION;
1247
1248 return IPMI_CC_OK;
1249}
1250
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001251ipmi_ret_t getPowerReading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -07001252 ipmi_request_t request, ipmi_response_t response,
1253 ipmi_data_len_t data_len, ipmi_context_t context)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001254{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001255 if (!dcmi::isDCMIPowerMgmtSupported())
1256 {
1257 *data_len = 0;
1258 log<level::ERR>("DCMI Power management is unsupported!");
1259 return IPMI_CC_INVALID;
1260 }
1261
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001262 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001263 auto requestData =
1264 reinterpret_cast<const dcmi::GetPowerReadingRequest*>(request);
1265 auto responseData =
1266 reinterpret_cast<dcmi::GetPowerReadingResponse*>(response);
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001267
1268 if (requestData->groupID != dcmi::groupExtId)
1269 {
1270 *data_len = 0;
1271 return IPMI_CC_INVALID_FIELD_REQUEST;
1272 }
1273
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001274 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001275 int64_t power = 0;
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001276 try
1277 {
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001278 power = getPowerReading(bus);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001279 }
1280 catch (InternalFailure& e)
1281 {
1282 log<level::ERR>("Error in reading power sensor value",
1283 entry("INTERFACE=%s", SENSOR_VALUE_INTF),
1284 entry("PROPERTY=%s", SENSOR_VALUE_PROP));
1285 return IPMI_CC_UNSPECIFIED_ERROR;
1286 }
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001287 responseData->groupID = dcmi::groupExtId;
1288
1289 // TODO: openbmc/openbmc#2819
Gunnar Mills8466b792018-03-23 12:18:12 -05001290 // Minimum, Maximum, Average power, TimeFrame, TimeStamp,
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001291 // PowerReadingState readings need to be populated
1292 // after Telemetry changes.
1293 uint16_t totalPower = static_cast<uint16_t>(power);
1294 responseData->currentPower = totalPower;
1295 responseData->minimumPower = totalPower;
1296 responseData->maximumPower = totalPower;
1297 responseData->averagePower = totalPower;
1298
1299 *data_len = sizeof(*responseData);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001300 return rc;
1301}
1302
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001303namespace dcmi
1304{
1305namespace sensor_info
1306{
1307
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001308Response createFromJson(const Json& config)
1309{
1310 Response response{};
1311 uint16_t recordId = config.value("record_id", 0);
1312 response.recordIdLsb = recordId & 0xFF;
1313 response.recordIdMsb = (recordId >> 8) & 0xFF;
1314 return response;
1315}
1316
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001317std::tuple<Response, NumInstances> read(const std::string& type,
Patrick Venture0b02be92018-08-31 11:55:55 -07001318 uint8_t instance, const Json& config)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001319{
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001320 Response response{};
1321
1322 if (!instance)
1323 {
1324 log<level::ERR>("Expected non-zero instance");
1325 elog<InternalFailure>();
1326 }
1327
1328 static const std::vector<Json> empty{};
1329 std::vector<Json> readings = config.value(type, empty);
1330 size_t numInstances = readings.size();
1331 for (const auto& reading : readings)
1332 {
1333 uint8_t instanceNum = reading.value("instance", 0);
1334 // Not the instance we're interested in
1335 if (instanceNum != instance)
1336 {
1337 continue;
1338 }
1339
1340 response = createFromJson(reading);
1341
1342 // Found the instance we're interested in
1343 break;
1344 }
1345
1346 if (numInstances > maxInstances)
1347 {
1348 log<level::DEBUG>("Trimming IPMI num instances",
1349 entry("NUM_INSTANCES=%d", numInstances));
1350 numInstances = maxInstances;
1351 }
1352 return std::make_tuple(response, numInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001353}
1354
Patrick Venture0b02be92018-08-31 11:55:55 -07001355std::tuple<ResponseList, NumInstances>
1356 readAll(const std::string& type, uint8_t instanceStart, const Json& config)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001357{
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001358 ResponseList responses{};
1359
1360 size_t numInstances = 0;
1361 static const std::vector<Json> empty{};
1362 std::vector<Json> readings = config.value(type, empty);
1363 numInstances = readings.size();
1364 for (const auto& reading : readings)
1365 {
1366 try
1367 {
1368 // Max of 8 records
1369 if (responses.size() == maxRecords)
1370 {
1371 break;
1372 }
1373
1374 uint8_t instanceNum = reading.value("instance", 0);
1375 // Not in the instance range we're interested in
1376 if (instanceNum < instanceStart)
1377 {
1378 continue;
1379 }
1380
1381 Response response = createFromJson(reading);
1382 responses.push_back(response);
1383 }
1384 catch (std::exception& e)
1385 {
1386 log<level::DEBUG>(e.what());
1387 continue;
1388 }
1389 }
1390
1391 if (numInstances > maxInstances)
1392 {
1393 log<level::DEBUG>("Trimming IPMI num instances",
1394 entry("NUM_INSTANCES=%d", numInstances));
1395 numInstances = maxInstances;
1396 }
1397 return std::make_tuple(responses, numInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001398}
1399
1400} // namespace sensor_info
1401} // namespace dcmi
1402
1403ipmi_ret_t getSensorInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1404 ipmi_request_t request, ipmi_response_t response,
1405 ipmi_data_len_t data_len, ipmi_context_t context)
1406{
1407 auto requestData =
1408 reinterpret_cast<const dcmi::GetSensorInfoRequest*>(request);
1409 auto responseData =
1410 reinterpret_cast<dcmi::GetSensorInfoResponseHdr*>(response);
1411
1412 if (*data_len != sizeof(dcmi::GetSensorInfoRequest))
1413 {
1414 log<level::ERR>("Malformed request data",
1415 entry("DATA_SIZE=%d", *data_len));
1416 return IPMI_CC_REQ_DATA_LEN_INVALID;
1417 }
1418 *data_len = 0;
1419
1420 auto it = dcmi::entityIdToName.find(requestData->entityId);
1421 if (it == dcmi::entityIdToName.end())
1422 {
1423 log<level::ERR>("Unknown Entity ID",
1424 entry("ENTITY_ID=%d", requestData->entityId));
1425 return IPMI_CC_INVALID_FIELD_REQUEST;
1426 }
1427
1428 if (requestData->groupID != dcmi::groupExtId)
1429 {
1430 log<level::ERR>("Invalid Group ID",
1431 entry("GROUP_ID=%d", requestData->groupID));
1432 return IPMI_CC_INVALID_FIELD_REQUEST;
1433 }
1434
1435 if (requestData->sensorType != dcmi::temperatureSensorType)
1436 {
1437 log<level::ERR>("Invalid sensor type",
1438 entry("SENSOR_TYPE=%d", requestData->sensorType));
1439 return IPMI_CC_INVALID_FIELD_REQUEST;
1440 }
1441
1442 dcmi::sensor_info::ResponseList sensors{};
1443 static dcmi::Json config{};
1444 static bool parsed = false;
1445
1446 try
1447 {
1448 if (!parsed)
1449 {
Kirill Pakhomova2573622018-11-02 19:00:18 +03001450 config = dcmi::parseJSONConfig(dcmi::gDCMISensorsConfig);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001451 parsed = true;
1452 }
1453
1454 if (!requestData->entityInstance)
1455 {
1456 // Read all instances
1457 std::tie(sensors, responseData->numInstances) =
1458 dcmi::sensor_info::readAll(it->second,
Patrick Venture0b02be92018-08-31 11:55:55 -07001459 requestData->instanceStart, config);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001460 }
1461 else
1462 {
1463 // Read one instance
1464 sensors.resize(1);
1465 std::tie(sensors[0], responseData->numInstances) =
Patrick Venture0b02be92018-08-31 11:55:55 -07001466 dcmi::sensor_info::read(it->second, requestData->entityInstance,
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001467 config);
1468 }
1469 responseData->numRecords = sensors.size();
1470 }
1471 catch (InternalFailure& e)
1472 {
1473 return IPMI_CC_UNSPECIFIED_ERROR;
1474 }
1475
1476 responseData->groupID = dcmi::groupExtId;
1477 size_t payloadSize = sensors.size() * sizeof(dcmi::sensor_info::Response);
1478 if (!sensors.empty())
1479 {
1480 memcpy(responseData + 1, // copy payload right after the response header
Patrick Venture0b02be92018-08-31 11:55:55 -07001481 sensors.data(), payloadSize);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001482 }
1483 *data_len = sizeof(dcmi::GetSensorInfoResponseHdr) + payloadSize;
1484
1485 return IPMI_CC_OK;
1486}
1487
Chris Austen1810bec2015-10-13 12:12:39 -05001488void register_netfn_dcmi_functions()
1489{
Tom05732372016-09-06 17:21:23 +05301490 // <Get Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301491
Patrick Venture0b02be92018-08-31 11:55:55 -07001492 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_LIMIT, NULL,
1493 getPowerLimit, PRIVILEGE_USER);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301494
Tom Joseph46fa37d2017-07-26 18:11:55 +05301495 // <Set Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301496
Patrick Venture0b02be92018-08-31 11:55:55 -07001497 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_POWER_LIMIT, NULL,
1498 setPowerLimit, PRIVILEGE_OPERATOR);
Tom Joseph46fa37d2017-07-26 18:11:55 +05301499
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301500 // <Activate/Deactivate Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301501
1502 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::APPLY_POWER_LIMIT,
1503 NULL, applyPowerLimit, PRIVILEGE_OPERATOR);
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301504
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301505 // <Get Asset Tag>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301506
Patrick Venture0b02be92018-08-31 11:55:55 -07001507 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_ASSET_TAG, NULL,
1508 getAssetTag, PRIVILEGE_USER);
Tom Joseph545dd232017-07-12 20:20:49 +05301509
1510 // <Set Asset Tag>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301511
Patrick Venture0b02be92018-08-31 11:55:55 -07001512 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_ASSET_TAG, NULL,
1513 setAssetTag, PRIVILEGE_OPERATOR);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001514
Gunnar Mills8991dd62017-10-25 17:11:29 -05001515 // <Get Management Controller Identifier String>
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001516
1517 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_MGMNT_CTRL_ID_STR,
Patrick Venture0b02be92018-08-31 11:55:55 -07001518 NULL, getMgmntCtrlIdStr, PRIVILEGE_USER);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001519
1520 // <Set Management Controller Identifier String>
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001521 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_MGMNT_CTRL_ID_STR,
Patrick Venture0b02be92018-08-31 11:55:55 -07001522 NULL, setMgmntCtrlIdStr, PRIVILEGE_ADMIN);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001523
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -06001524 // <Get DCMI capabilities>
1525 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CAPABILITIES,
Patrick Venture0b02be92018-08-31 11:55:55 -07001526 NULL, getDCMICapabilities, PRIVILEGE_USER);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001527
1528 // <Get Temperature Readings>
1529 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_TEMP_READINGS,
1530 NULL, getTempReadings, PRIVILEGE_USER);
1531
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001532 // <Get Power Reading>
1533 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_READING,
1534 NULL, getPowerReading, PRIVILEGE_USER);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001535
1536 // <Get Sensor Info>
Patrick Venture0b02be92018-08-31 11:55:55 -07001537 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_SENSOR_INFO, NULL,
1538 getSensorInfo, PRIVILEGE_USER);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001539
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001540 // <Get DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001541 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CONF_PARAMS, NULL,
1542 getDCMIConfParams, PRIVILEGE_USER);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001543
1544 // <Set DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001545 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_CONF_PARAMS, NULL,
1546 setDCMIConfParams, PRIVILEGE_ADMIN);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001547
Chris Austen1810bec2015-10-13 12:12:39 -05001548 return;
1549}
Tom05732372016-09-06 17:21:23 +05301550// 956379