blob: 7a4db9f5ea17ef10fa741c11a07e66b20ac22e72 [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
William A. Kennington III194375f2018-12-14 02:14:33 -08008#include <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
Marri Devender Rao66c5fda2018-01-18 10:48:37 -060053constexpr auto SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
54constexpr auto SENSOR_VALUE_PROP = "Value";
55constexpr auto SENSOR_SCALE_PROP = "Scale";
56
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050057using namespace phosphor::logging;
William A. Kennington III4c008022018-10-12 17:18:14 -070058namespace variant_ns = sdbusplus::message::variant_ns;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050059
Tom Josephb9d86f42017-07-26 18:03:47 +053060namespace dcmi
61{
62
Deepak Kodihalli0b459552018-02-06 06:25:12 -060063// Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
Patrick Venture0b02be92018-08-31 11:55:55 -070064static const std::map<uint8_t, std::string> entityIdToName{
65 {0x40, "inlet"}, {0x37, "inlet"}, {0x41, "cpu"},
66 {0x03, "cpu"}, {0x42, "baseboard"}, {0x07, "baseboard"}};
Deepak Kodihalli0b459552018-02-06 06:25:12 -060067
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050068uint32_t getPcap(sdbusplus::bus::bus& bus)
69{
Patrick Venture0b02be92018-08-31 11:55:55 -070070 auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050071
Patrick Venture0b02be92018-08-31 11:55:55 -070072 auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH,
73 "org.freedesktop.DBus.Properties", "Get");
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050074
75 method.append(PCAP_INTERFACE, POWER_CAP_PROP);
76 auto reply = bus.call(method);
77
78 if (reply.is_method_error())
79 {
80 log<level::ERR>("Error in getPcap prop");
Tom Josephb9d86f42017-07-26 18:03:47 +053081 elog<InternalFailure>();
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050082 }
83 sdbusplus::message::variant<uint32_t> pcap;
84 reply.read(pcap);
85
William A. Kennington III4c008022018-10-12 17:18:14 -070086 return variant_ns::get<uint32_t>(pcap);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050087}
88
89bool getPcapEnabled(sdbusplus::bus::bus& bus)
90{
Patrick Venture0b02be92018-08-31 11:55:55 -070091 auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050092
Patrick Venture0b02be92018-08-31 11:55:55 -070093 auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH,
94 "org.freedesktop.DBus.Properties", "Get");
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050095
96 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
97 auto reply = bus.call(method);
98
99 if (reply.is_method_error())
100 {
101 log<level::ERR>("Error in getPcapEnabled prop");
Tom Josephb9d86f42017-07-26 18:03:47 +0530102 elog<InternalFailure>();
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500103 }
104 sdbusplus::message::variant<bool> pcapEnabled;
105 reply.read(pcapEnabled);
106
William A. Kennington III4c008022018-10-12 17:18:14 -0700107 return variant_ns::get<bool>(pcapEnabled);
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500108}
Chris Austen1810bec2015-10-13 12:12:39 -0500109
Tom Joseph46fa37d2017-07-26 18:11:55 +0530110void setPcap(sdbusplus::bus::bus& bus, const uint32_t powerCap)
111{
112 auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
113
Patrick Venture0b02be92018-08-31 11:55:55 -0700114 auto method = bus.new_method_call(service.c_str(), PCAP_PATH,
115 "org.freedesktop.DBus.Properties", "Set");
Tom Joseph46fa37d2017-07-26 18:11:55 +0530116
117 method.append(PCAP_INTERFACE, POWER_CAP_PROP);
118 method.append(sdbusplus::message::variant<uint32_t>(powerCap));
119
120 auto reply = bus.call(method);
121
122 if (reply.is_method_error())
123 {
124 log<level::ERR>("Error in setPcap property");
125 elog<InternalFailure>();
126 }
127}
128
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530129void setPcapEnable(sdbusplus::bus::bus& bus, bool enabled)
130{
131 auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH);
132
Patrick Venture0b02be92018-08-31 11:55:55 -0700133 auto method = bus.new_method_call(service.c_str(), PCAP_PATH,
134 "org.freedesktop.DBus.Properties", "Set");
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530135
136 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
137 method.append(sdbusplus::message::variant<bool>(enabled));
138
139 auto reply = bus.call(method);
140
141 if (reply.is_method_error())
142 {
143 log<level::ERR>("Error in setPcapEnabled property");
144 elog<InternalFailure>();
145 }
146}
147
Tom Josephbe5eaa12017-07-12 19:54:44 +0530148void readAssetTagObjectTree(dcmi::assettag::ObjectTree& objectTree)
149{
150 static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
151 static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
152 static constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper";
153 static constexpr auto inventoryRoot = "/xyz/openbmc_project/inventory/";
154
155 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
156 auto depth = 0;
157
Patrick Venture0b02be92018-08-31 11:55:55 -0700158 auto mapperCall = bus.new_method_call(mapperBusName, mapperObjPath,
159 mapperIface, "GetSubTree");
Tom Josephbe5eaa12017-07-12 19:54:44 +0530160
161 mapperCall.append(inventoryRoot);
162 mapperCall.append(depth);
163 mapperCall.append(std::vector<std::string>({dcmi::assetTagIntf}));
164
165 auto mapperReply = bus.call(mapperCall);
166 if (mapperReply.is_method_error())
167 {
168 log<level::ERR>("Error in mapper call");
169 elog<InternalFailure>();
170 }
171
172 mapperReply.read(objectTree);
173
174 if (objectTree.empty())
175 {
176 log<level::ERR>("AssetTag property is not populated");
177 elog<InternalFailure>();
178 }
179}
180
181std::string readAssetTag()
182{
183 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
184 dcmi::assettag::ObjectTree objectTree;
185
186 // Read the object tree with the inventory root to figure out the object
187 // that has implemented the Asset tag interface.
188 readAssetTagObjectTree(objectTree);
189
190 auto method = bus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -0700191 (objectTree.begin()->second.begin()->first).c_str(),
192 (objectTree.begin()->first).c_str(), dcmi::propIntf, "Get");
Tom Josephbe5eaa12017-07-12 19:54:44 +0530193 method.append(dcmi::assetTagIntf);
194 method.append(dcmi::assetTagProp);
195
196 auto reply = bus.call(method);
197 if (reply.is_method_error())
198 {
199 log<level::ERR>("Error in reading asset tag");
200 elog<InternalFailure>();
201 }
202
203 sdbusplus::message::variant<std::string> assetTag;
204 reply.read(assetTag);
205
William A. Kennington III4c008022018-10-12 17:18:14 -0700206 return variant_ns::get<std::string>(assetTag);
Tom Josephbe5eaa12017-07-12 19:54:44 +0530207}
208
Tom Josephbe5b9892017-07-15 00:55:23 +0530209void writeAssetTag(const std::string& assetTag)
210{
211 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
212 dcmi::assettag::ObjectTree objectTree;
213
214 // Read the object tree with the inventory root to figure out the object
215 // that has implemented the Asset tag interface.
216 readAssetTagObjectTree(objectTree);
217
218 auto method = bus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -0700219 (objectTree.begin()->second.begin()->first).c_str(),
220 (objectTree.begin()->first).c_str(), dcmi::propIntf, "Set");
Tom Josephbe5b9892017-07-15 00:55:23 +0530221 method.append(dcmi::assetTagIntf);
222 method.append(dcmi::assetTagProp);
223 method.append(sdbusplus::message::variant<std::string>(assetTag));
224
225 auto reply = bus.call(method);
226 if (reply.is_method_error())
227 {
228 log<level::ERR>("Error in writing asset tag");
229 elog<InternalFailure>();
230 }
231}
232
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300233std::string getHostName(void)
234{
Patrick Venture0b02be92018-08-31 11:55:55 -0700235 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300236
237 auto service = ipmi::getService(bus, networkConfigIntf, networkConfigObj);
Patrick Venture0b02be92018-08-31 11:55:55 -0700238 auto value = ipmi::getDbusProperty(bus, service, networkConfigObj,
239 networkConfigIntf, hostNameProp);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300240
William A. Kennington III4c008022018-10-12 17:18:14 -0700241 return variant_ns::get<std::string>(value);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300242}
243
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600244bool getDHCPEnabled()
245{
246 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
247
Johnathan Mantey74a21022018-12-13 13:17:56 -0800248 auto ethdevice = ipmi::getChannelName(ethernetDefaultChannelNum);
Patrick Venture0b02be92018-08-31 11:55:55 -0700249 auto ethernetObj =
250 ipmi::getDbusObject(bus, ethernetIntf, networkRoot, ethdevice);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600251 auto service = ipmi::getService(bus, ethernetIntf, ethernetObj.first);
Patrick Venture0b02be92018-08-31 11:55:55 -0700252 auto value = ipmi::getDbusProperty(bus, service, ethernetObj.first,
253 ethernetIntf, "DHCPEnabled");
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600254
William A. Kennington III4c008022018-10-12 17:18:14 -0700255 return variant_ns::get<bool>(value);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600256}
257
258bool getDHCPOption(std::string prop)
259{
260 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
261
262 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
263 auto value = ipmi::getDbusProperty(bus, service, dhcpObj, dhcpIntf, prop);
264
William A. Kennington III4c008022018-10-12 17:18:14 -0700265 return variant_ns::get<bool>(value);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600266}
267
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600268void setDHCPOption(std::string prop, bool value)
269{
270 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
271
272 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
273 ipmi::setDbusProperty(bus, service, dhcpObj, dhcpIntf, prop, value);
274}
275
Kirill Pakhomova2573622018-11-02 19:00:18 +0300276Json parseJSONConfig(const std::string& configFile)
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600277{
278 std::ifstream jsonFile(configFile);
279 if (!jsonFile.is_open())
280 {
281 log<level::ERR>("Temperature readings JSON file not found");
282 elog<InternalFailure>();
283 }
284
285 auto data = Json::parse(jsonFile, nullptr, false);
286 if (data.is_discarded())
287 {
288 log<level::ERR>("Temperature readings JSON parser failure");
289 elog<InternalFailure>();
290 }
291
292 return data;
293}
294
Tom Josephbe5eaa12017-07-12 19:54:44 +0530295} // namespace dcmi
Chris Austen1810bec2015-10-13 12:12:39 -0500296
Tom Josephb9d86f42017-07-26 18:03:47 +0530297ipmi_ret_t getPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
298 ipmi_request_t request, ipmi_response_t response,
299 ipmi_data_len_t data_len, ipmi_context_t context)
300{
Patrick Venture0b02be92018-08-31 11:55:55 -0700301 auto requestData =
302 reinterpret_cast<const dcmi::GetPowerLimitRequest*>(request);
Tom Josephb9d86f42017-07-26 18:03:47 +0530303 std::vector<uint8_t> outPayload(sizeof(dcmi::GetPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700304 auto responseData =
305 reinterpret_cast<dcmi::GetPowerLimitResponse*>(outPayload.data());
Tom Josephb9d86f42017-07-26 18:03:47 +0530306
307 if (requestData->groupID != dcmi::groupExtId)
308 {
309 *data_len = 0;
310 return IPMI_CC_INVALID_FIELD_REQUEST;
311 }
312
Patrick Venture0b02be92018-08-31 11:55:55 -0700313 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Josephb9d86f42017-07-26 18:03:47 +0530314 uint32_t pcapValue = 0;
315 bool pcapEnable = false;
316
317 try
318 {
319 pcapValue = dcmi::getPcap(sdbus);
320 pcapEnable = dcmi::getPcapEnabled(sdbus);
321 }
322 catch (InternalFailure& e)
323 {
324 *data_len = 0;
325 return IPMI_CC_UNSPECIFIED_ERROR;
326 }
327
328 responseData->groupID = dcmi::groupExtId;
329
330 /*
331 * Exception action if power limit is exceeded and cannot be controlled
332 * with the correction time limit is hardcoded to Hard Power Off system
333 * and log event to SEL.
334 */
335 constexpr auto exception = 0x01;
336 responseData->exceptionAction = exception;
337
338 responseData->powerLimit = static_cast<uint16_t>(pcapValue);
339
340 /*
341 * Correction time limit and Statistics sampling period is currently not
342 * populated.
343 */
344
345 *data_len = outPayload.size();
346 memcpy(response, outPayload.data(), *data_len);
347
348 if (pcapEnable)
349 {
350 return IPMI_CC_OK;
351 }
352 else
353 {
354 return IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT;
355 }
356}
357
Tom Joseph46fa37d2017-07-26 18:11:55 +0530358ipmi_ret_t setPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
359 ipmi_request_t request, ipmi_response_t response,
360 ipmi_data_len_t data_len, ipmi_context_t context)
361{
Patrick Venture0b02be92018-08-31 11:55:55 -0700362 auto requestData =
363 reinterpret_cast<const dcmi::SetPowerLimitRequest*>(request);
Tom Joseph46fa37d2017-07-26 18:11:55 +0530364 std::vector<uint8_t> outPayload(sizeof(dcmi::SetPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700365 auto responseData =
366 reinterpret_cast<dcmi::SetPowerLimitResponse*>(outPayload.data());
Tom Joseph46fa37d2017-07-26 18:11:55 +0530367
368 if (requestData->groupID != dcmi::groupExtId)
369 {
370 *data_len = 0;
371 return IPMI_CC_INVALID_FIELD_REQUEST;
372 }
373
Patrick Venture0b02be92018-08-31 11:55:55 -0700374 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Joseph46fa37d2017-07-26 18:11:55 +0530375
376 // Only process the power limit requested in watts.
377 try
378 {
379 dcmi::setPcap(sdbus, requestData->powerLimit);
380 }
381 catch (InternalFailure& e)
382 {
383 *data_len = 0;
384 return IPMI_CC_UNSPECIFIED_ERROR;
385 }
386
387 log<level::INFO>("Set Power Cap",
388 entry("POWERCAP=%u", requestData->powerLimit));
389
390 responseData->groupID = dcmi::groupExtId;
391 memcpy(response, outPayload.data(), outPayload.size());
392 *data_len = outPayload.size();
393
394 return IPMI_CC_OK;
395}
396
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530397ipmi_ret_t applyPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
398 ipmi_request_t request, ipmi_response_t response,
399 ipmi_data_len_t data_len, ipmi_context_t context)
400{
Patrick Venture0b02be92018-08-31 11:55:55 -0700401 auto requestData =
402 reinterpret_cast<const dcmi::ApplyPowerLimitRequest*>(request);
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530403 std::vector<uint8_t> outPayload(sizeof(dcmi::ApplyPowerLimitResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700404 auto responseData =
405 reinterpret_cast<dcmi::ApplyPowerLimitResponse*>(outPayload.data());
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530406
407 if (requestData->groupID != dcmi::groupExtId)
408 {
409 *data_len = 0;
410 return IPMI_CC_INVALID_FIELD_REQUEST;
411 }
412
Patrick Venture0b02be92018-08-31 11:55:55 -0700413 sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()};
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530414
415 try
416 {
417 dcmi::setPcapEnable(sdbus,
418 static_cast<bool>(requestData->powerLimitAction));
419 }
420 catch (InternalFailure& e)
421 {
422 *data_len = 0;
423 return IPMI_CC_UNSPECIFIED_ERROR;
424 }
425
426 log<level::INFO>("Set Power Cap Enable",
427 entry("POWERCAPENABLE=%u", requestData->powerLimitAction));
428
429 responseData->groupID = dcmi::groupExtId;
430 memcpy(response, outPayload.data(), outPayload.size());
431 *data_len = outPayload.size();
432
433 return IPMI_CC_OK;
434}
435
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530436ipmi_ret_t getAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
437 ipmi_request_t request, ipmi_response_t response,
438 ipmi_data_len_t data_len, ipmi_context_t context)
439{
Patrick Venture0b02be92018-08-31 11:55:55 -0700440 auto requestData =
441 reinterpret_cast<const dcmi::GetAssetTagRequest*>(request);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530442 std::vector<uint8_t> outPayload(sizeof(dcmi::GetAssetTagResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700443 auto responseData =
444 reinterpret_cast<dcmi::GetAssetTagResponse*>(outPayload.data());
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530445
446 if (requestData->groupID != dcmi::groupExtId)
447 {
448 *data_len = 0;
449 return IPMI_CC_INVALID_FIELD_REQUEST;
450 }
451
452 // Verify offset to read and number of bytes to read are not exceeding the
453 // range.
454 if ((requestData->offset > dcmi::assetTagMaxOffset) ||
455 (requestData->bytes > dcmi::maxBytes) ||
456 ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize))
457 {
458 *data_len = 0;
459 return IPMI_CC_PARM_OUT_OF_RANGE;
460 }
461
462 std::string assetTag;
463
464 try
465 {
466 assetTag = dcmi::readAssetTag();
467 }
468 catch (InternalFailure& e)
469 {
470 *data_len = 0;
471 return IPMI_CC_UNSPECIFIED_ERROR;
472 }
473
474 responseData->groupID = dcmi::groupExtId;
475
476 // Return if the asset tag is not populated.
477 if (!assetTag.size())
478 {
479 responseData->tagLength = 0;
480 memcpy(response, outPayload.data(), outPayload.size());
481 *data_len = outPayload.size();
482 return IPMI_CC_OK;
483 }
484
485 // If the asset tag is longer than 63 bytes, restrict it to 63 bytes to suit
486 // Get Asset Tag command.
487 if (assetTag.size() > dcmi::assetTagMaxSize)
488 {
489 assetTag.resize(dcmi::assetTagMaxSize);
490 }
491
492 // If the requested offset is beyond the asset tag size.
493 if (requestData->offset >= assetTag.size())
494 {
495 *data_len = 0;
496 return IPMI_CC_PARM_OUT_OF_RANGE;
497 }
498
499 auto returnData = assetTag.substr(requestData->offset, requestData->bytes);
500
501 responseData->tagLength = assetTag.size();
502
503 memcpy(response, outPayload.data(), outPayload.size());
504 memcpy(static_cast<uint8_t*>(response) + outPayload.size(),
505 returnData.data(), returnData.size());
506 *data_len = outPayload.size() + returnData.size();
507
508 return IPMI_CC_OK;
509}
510
Tom Joseph545dd232017-07-12 20:20:49 +0530511ipmi_ret_t setAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
512 ipmi_request_t request, ipmi_response_t response,
513 ipmi_data_len_t data_len, ipmi_context_t context)
514{
Patrick Venture0b02be92018-08-31 11:55:55 -0700515 auto requestData =
516 reinterpret_cast<const dcmi::SetAssetTagRequest*>(request);
Tom Joseph545dd232017-07-12 20:20:49 +0530517 std::vector<uint8_t> outPayload(sizeof(dcmi::SetAssetTagResponse));
Patrick Venture0b02be92018-08-31 11:55:55 -0700518 auto responseData =
519 reinterpret_cast<dcmi::SetAssetTagResponse*>(outPayload.data());
Tom Joseph545dd232017-07-12 20:20:49 +0530520
521 if (requestData->groupID != dcmi::groupExtId)
522 {
523 *data_len = 0;
524 return IPMI_CC_INVALID_FIELD_REQUEST;
525 }
526
527 // Verify offset to read and number of bytes to read are not exceeding the
528 // range.
529 if ((requestData->offset > dcmi::assetTagMaxOffset) ||
530 (requestData->bytes > dcmi::maxBytes) ||
531 ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize))
532 {
533 *data_len = 0;
534 return IPMI_CC_PARM_OUT_OF_RANGE;
535 }
536
537 std::string assetTag;
538
539 try
540 {
541 assetTag = dcmi::readAssetTag();
542
543 if (requestData->offset > assetTag.size())
544 {
545 *data_len = 0;
546 return IPMI_CC_PARM_OUT_OF_RANGE;
547 }
548
549 assetTag.replace(requestData->offset,
550 assetTag.size() - requestData->offset,
551 static_cast<const char*>(request) +
Patrick Venture0b02be92018-08-31 11:55:55 -0700552 sizeof(dcmi::SetAssetTagRequest),
Tom Joseph545dd232017-07-12 20:20:49 +0530553 requestData->bytes);
554
555 dcmi::writeAssetTag(assetTag);
556
557 responseData->groupID = dcmi::groupExtId;
558 responseData->tagLength = assetTag.size();
559 memcpy(response, outPayload.data(), outPayload.size());
560 *data_len = outPayload.size();
561
562 return IPMI_CC_OK;
563 }
564 catch (InternalFailure& e)
565 {
566 *data_len = 0;
567 return IPMI_CC_UNSPECIFIED_ERROR;
568 }
569}
570
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300571ipmi_ret_t getMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700572 ipmi_request_t request, ipmi_response_t response,
573 ipmi_data_len_t data_len, ipmi_context_t context)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300574{
Patrick Venture0b02be92018-08-31 11:55:55 -0700575 auto requestData =
576 reinterpret_cast<const dcmi::GetMgmntCtrlIdStrRequest*>(request);
577 auto responseData =
578 reinterpret_cast<dcmi::GetMgmntCtrlIdStrResponse*>(response);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300579 std::string hostName;
580
581 *data_len = 0;
582
583 if (requestData->groupID != dcmi::groupExtId ||
584 requestData->bytes > dcmi::maxBytes ||
585 requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen)
586 {
587 return IPMI_CC_INVALID_FIELD_REQUEST;
588 }
589
590 try
591 {
592 hostName = dcmi::getHostName();
593 }
594 catch (InternalFailure& e)
595 {
596 return IPMI_CC_UNSPECIFIED_ERROR;
597 }
598
599 if (requestData->offset > hostName.length())
600 {
601 return IPMI_CC_PARM_OUT_OF_RANGE;
602 }
603 auto responseStr = hostName.substr(requestData->offset, requestData->bytes);
604 auto responseStrLen = std::min(static_cast<std::size_t>(requestData->bytes),
Patrick Venture0b02be92018-08-31 11:55:55 -0700605 responseStr.length() + 1);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300606 responseData->groupID = dcmi::groupExtId;
607 responseData->strLen = hostName.length();
608 std::copy(begin(responseStr), end(responseStr), responseData->data);
609
610 *data_len = sizeof(*responseData) + responseStrLen;
611 return IPMI_CC_OK;
612}
613
614ipmi_ret_t setMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700615 ipmi_request_t request, ipmi_response_t response,
616 ipmi_data_len_t data_len, ipmi_context_t context)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300617{
618 static std::array<char, dcmi::maxCtrlIdStrLen + 1> newCtrlIdStr;
619
Patrick Venture0b02be92018-08-31 11:55:55 -0700620 auto requestData =
621 reinterpret_cast<const dcmi::SetMgmntCtrlIdStrRequest*>(request);
622 auto responseData =
623 reinterpret_cast<dcmi::SetMgmntCtrlIdStrResponse*>(response);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300624
625 *data_len = 0;
626
627 if (requestData->groupID != dcmi::groupExtId ||
628 requestData->bytes > dcmi::maxBytes ||
629 requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen + 1 ||
Patrick Venture0b02be92018-08-31 11:55:55 -0700630 (requestData->offset + requestData->bytes ==
631 dcmi::maxCtrlIdStrLen + 1 &&
632 requestData->data[requestData->bytes - 1] != '\0'))
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300633 {
634 return IPMI_CC_INVALID_FIELD_REQUEST;
635 }
636
637 try
638 {
639 /* if there is no old value and offset is not 0 */
640 if (newCtrlIdStr[0] == '\0' && requestData->offset != 0)
641 {
642 /* read old ctrlIdStr */
643 auto hostName = dcmi::getHostName();
644 hostName.resize(dcmi::maxCtrlIdStrLen);
645 std::copy(begin(hostName), end(hostName), begin(newCtrlIdStr));
646 newCtrlIdStr[hostName.length()] = '\0';
647 }
648
649 /* replace part of string and mark byte after the last as \0 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700650 auto restStrIter =
651 std::copy_n(requestData->data, requestData->bytes,
652 begin(newCtrlIdStr) + requestData->offset);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300653 /* if the last written byte is not 64th - add '\0' */
654 if (requestData->offset + requestData->bytes <= dcmi::maxCtrlIdStrLen)
655 {
656 *restStrIter = '\0';
657 }
658
659 /* if input data contains '\0' whole string is sent - update hostname */
660 auto it = std::find(requestData->data,
Patrick Venture0b02be92018-08-31 11:55:55 -0700661 requestData->data + requestData->bytes, '\0');
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300662 if (it != requestData->data + requestData->bytes)
663 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700664 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300665 ipmi::setDbusProperty(bus, dcmi::networkServiceName,
Patrick Venture0b02be92018-08-31 11:55:55 -0700666 dcmi::networkConfigObj,
667 dcmi::networkConfigIntf, dcmi::hostNameProp,
668 std::string(newCtrlIdStr.data()));
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300669 }
670 }
671 catch (InternalFailure& e)
672 {
673 *data_len = 0;
674 return IPMI_CC_UNSPECIFIED_ERROR;
675 }
676
677 responseData->groupID = dcmi::groupExtId;
678 responseData->offset = requestData->offset + requestData->bytes;
679 *data_len = sizeof(*responseData);
680 return IPMI_CC_OK;
681}
682
Patrick Venture0b02be92018-08-31 11:55:55 -0700683// List of the capabilities under each parameter
684dcmi::DCMICaps dcmiCaps = {
685 // Supported DCMI Capabilities
686 {dcmi::DCMICapParameters::SUPPORTED_DCMI_CAPS,
687 {3,
688 {{"PowerManagement", 2, 0, 1},
689 {"OOBSecondaryLan", 3, 2, 1},
690 {"SerialTMODE", 3, 1, 1},
691 {"InBandSystemInterfaceChannel", 3, 0, 1}}}},
692 // Mandatory Platform Attributes
693 {dcmi::DCMICapParameters::MANDATORY_PLAT_ATTRIBUTES,
694 {5,
695 {{"SELAutoRollOver", 1, 15, 1},
696 {"FlushEntireSELUponRollOver", 1, 14, 1},
697 {"RecordLevelSELFlushUponRollOver", 1, 13, 1},
698 {"NumberOfSELEntries", 1, 0, 12},
699 {"TempMonitoringSamplingFreq", 5, 0, 8}}}},
700 // Optional Platform Attributes
701 {dcmi::DCMICapParameters::OPTIONAL_PLAT_ATTRIBUTES,
702 {2,
703 {{"PowerMgmtDeviceSlaveAddress", 1, 1, 7},
704 {"BMCChannelNumber", 2, 4, 4},
705 {"DeviceRivision", 2, 0, 4}}}},
706 // Manageability Access Attributes
707 {dcmi::DCMICapParameters::MANAGEABILITY_ACCESS_ATTRIBUTES,
708 {3,
709 {{"MandatoryPrimaryLanOOBSupport", 1, 0, 8},
710 {"OptionalSecondaryLanOOBSupport", 2, 0, 8},
711 {"OptionalSerialOOBMTMODECapability", 3, 0, 8}}}}};
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600712
713ipmi_ret_t getDCMICapabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
714 ipmi_request_t request, ipmi_response_t response,
715 ipmi_data_len_t data_len, ipmi_context_t context)
716{
717
Kirill Pakhomova2573622018-11-02 19:00:18 +0300718 std::ifstream dcmiCapFile(dcmi::gDCMICapabilitiesConfig);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600719 if (!dcmiCapFile.is_open())
720 {
721 log<level::ERR>("DCMI Capabilities file not found");
722 return IPMI_CC_UNSPECIFIED_ERROR;
723 }
724
725 auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false);
726 if (data.is_discarded())
727 {
728 log<level::ERR>("DCMI Capabilities JSON parser failure");
729 return IPMI_CC_UNSPECIFIED_ERROR;
730 }
731
Patrick Venture0b02be92018-08-31 11:55:55 -0700732 auto requestData =
733 reinterpret_cast<const dcmi::GetDCMICapRequest*>(request);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600734
Patrick Venture0b02be92018-08-31 11:55:55 -0700735 // get list of capabilities in a parameter
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600736 auto caps =
737 dcmiCaps.find(static_cast<dcmi::DCMICapParameters>(requestData->param));
738 if (caps == dcmiCaps.end())
739 {
740 log<level::ERR>("Invalid input parameter");
741 return IPMI_CC_INVALID_FIELD_REQUEST;
742 }
743
744 if (requestData->groupID != dcmi::groupExtId)
745 {
746 *data_len = 0;
747 return IPMI_CC_INVALID_FIELD_REQUEST;
748 }
749
Patrick Venture0b02be92018-08-31 11:55:55 -0700750 auto responseData = reinterpret_cast<dcmi::GetDCMICapResponse*>(response);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600751
Patrick Venture0b02be92018-08-31 11:55:55 -0700752 // For each capabilities in a parameter fill the data from
753 // the json file based on the capability name.
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600754 for (auto cap : caps->second.capList)
755 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700756 // If the data is beyond first byte boundary, insert in a
757 // 16bit pattern for example number of SEL entries are represented
758 // in 12bits.
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600759 if ((cap.length + cap.position) > 8)
760 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700761 // Read the value corresponding to capability name and assign to
762 // 16bit bitset.
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600763 std::bitset<16> val(data.value(cap.name.c_str(), 0));
764 val <<= cap.position;
Patrick Venture0b02be92018-08-31 11:55:55 -0700765 reinterpret_cast<uint16_t*>(
766 responseData
767 ->data)[(cap.bytePosition - 1) / sizeof(uint16_t)] |=
768 val.to_ulong();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600769 }
770 else
771 {
772 responseData->data[cap.bytePosition - 1] |=
773 data.value(cap.name.c_str(), 0) << cap.position;
774 }
775 }
776
777 responseData->groupID = dcmi::groupExtId;
778 responseData->major = DCMI_SPEC_MAJOR_VERSION;
779 responseData->minor = DCMI_SPEC_MINOR_VERSION;
780 responseData->paramRevision = DCMI_PARAMETER_REVISION;
781 *data_len = sizeof(*responseData) + caps->second.size;
782
783 return IPMI_CC_OK;
784}
785
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600786namespace dcmi
787{
788namespace temp_readings
789{
790
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600791Temperature readTemp(const std::string& dbusService,
792 const std::string& dbusPath)
793{
794 // Read the temperature value from d-bus object. Need some conversion.
795 // As per the interface xyz.openbmc_project.Sensor.Value, the temperature
James Feist9cc0ea52018-10-09 10:53:11 -0700796 // is an double and in degrees C. It needs to be scaled by using the
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600797 // formula Value * 10^Scale. The ipmi spec has the temperature as a uint8_t,
798 // with a separate single bit for the sign.
799
800 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700801 auto result = ipmi::getAllDbusProperties(
802 bus, dbusService, dbusPath, "xyz.openbmc_project.Sensor.Value");
James Feist9cc0ea52018-10-09 10:53:11 -0700803 auto temperature = sdbusplus::message::variant_ns::visit(
804 ipmi::VariantToDoubleVisitor(), result.at("Value"));
805 double absTemp = std::abs(temperature);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600806
James Feist9cc0ea52018-10-09 10:53:11 -0700807 auto findFactor = result.find("Scale");
808 double factor = 0.0;
809 if (findFactor != result.end())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600810 {
James Feist9cc0ea52018-10-09 10:53:11 -0700811 factor = sdbusplus::message::variant_ns::visit(
812 ipmi::VariantToDoubleVisitor(), findFactor->second);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600813 }
James Feist9cc0ea52018-10-09 10:53:11 -0700814 double scale = std::pow(10, factor);
815
816 auto tempDegrees = absTemp * scale;
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600817 // Max absolute temp as per ipmi spec is 128.
818 if (tempDegrees > maxTemp)
819 {
820 tempDegrees = maxTemp;
821 }
822
823 return std::make_tuple(static_cast<uint8_t>(tempDegrees),
824 (temperature < 0));
825}
826
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600827std::tuple<Response, NumInstances> read(const std::string& type,
828 uint8_t instance)
829{
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600830 Response response{};
831 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
832
833 if (!instance)
834 {
835 log<level::ERR>("Expected non-zero instance");
836 elog<InternalFailure>();
837 }
838
Kirill Pakhomova2573622018-11-02 19:00:18 +0300839 auto data = parseJSONConfig(gDCMISensorsConfig);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600840 static const std::vector<Json> empty{};
841 std::vector<Json> readings = data.value(type, empty);
842 size_t numInstances = readings.size();
843 for (const auto& j : readings)
844 {
845 uint8_t instanceNum = j.value("instance", 0);
846 // Not the instance we're interested in
847 if (instanceNum != instance)
848 {
849 continue;
850 }
851
852 std::string path = j.value("dbus", "");
853 std::string service;
854 try
855 {
856 service =
Patrick Venture0b02be92018-08-31 11:55:55 -0700857 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600858 }
859 catch (std::exception& e)
860 {
861 log<level::DEBUG>(e.what());
862 return std::make_tuple(response, numInstances);
863 }
864
865 response.instance = instance;
866 uint8_t temp{};
867 bool sign{};
868 std::tie(temp, sign) = readTemp(service, path);
869 response.temperature = temp;
870 response.sign = sign;
871
872 // Found the instance we're interested in
873 break;
874 }
875
876 if (numInstances > maxInstances)
877 {
878 numInstances = maxInstances;
879 }
880 return std::make_tuple(response, numInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600881}
882
883std::tuple<ResponseList, NumInstances> readAll(const std::string& type,
884 uint8_t instanceStart)
885{
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600886 ResponseList response{};
887 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
888
889 size_t numInstances = 0;
Kirill Pakhomova2573622018-11-02 19:00:18 +0300890 auto data = parseJSONConfig(gDCMISensorsConfig);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600891 static const std::vector<Json> empty{};
892 std::vector<Json> readings = data.value(type, empty);
893 numInstances = readings.size();
894 for (const auto& j : readings)
895 {
896 try
897 {
898 // Max of 8 response data sets
899 if (response.size() == maxDataSets)
900 {
901 break;
902 }
903
904 uint8_t instanceNum = j.value("instance", 0);
905 // Not in the instance range we're interested in
906 if (instanceNum < instanceStart)
907 {
908 continue;
909 }
910
911 std::string path = j.value("dbus", "");
912 auto service =
Patrick Venture0b02be92018-08-31 11:55:55 -0700913 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600914
915 Response r{};
916 r.instance = instanceNum;
917 uint8_t temp{};
918 bool sign{};
919 std::tie(temp, sign) = readTemp(service, path);
920 r.temperature = temp;
921 r.sign = sign;
922 response.push_back(r);
923 }
924 catch (std::exception& e)
925 {
926 log<level::DEBUG>(e.what());
927 continue;
928 }
929 }
930
931 if (numInstances > maxInstances)
932 {
933 numInstances = maxInstances;
934 }
935 return std::make_tuple(response, numInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600936}
937
Patrick Venture0b02be92018-08-31 11:55:55 -0700938} // namespace temp_readings
939} // namespace dcmi
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600940
941ipmi_ret_t getTempReadings(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700942 ipmi_request_t request, ipmi_response_t response,
943 ipmi_data_len_t data_len, ipmi_context_t context)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600944{
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600945 auto requestData =
946 reinterpret_cast<const dcmi::GetTempReadingsRequest*>(request);
947 auto responseData =
948 reinterpret_cast<dcmi::GetTempReadingsResponseHdr*>(response);
949
950 if (*data_len != sizeof(dcmi::GetTempReadingsRequest))
951 {
952 log<level::ERR>("Malformed request data",
953 entry("DATA_SIZE=%d", *data_len));
954 return IPMI_CC_REQ_DATA_LEN_INVALID;
955 }
956 *data_len = 0;
957
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600958 auto it = dcmi::entityIdToName.find(requestData->entityId);
959 if (it == dcmi::entityIdToName.end())
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600960 {
961 log<level::ERR>("Unknown Entity ID",
962 entry("ENTITY_ID=%d", requestData->entityId));
963 return IPMI_CC_INVALID_FIELD_REQUEST;
964 }
965
966 if (requestData->groupID != dcmi::groupExtId)
967 {
968 log<level::ERR>("Invalid Group ID",
969 entry("GROUP_ID=%d", requestData->groupID));
970 return IPMI_CC_INVALID_FIELD_REQUEST;
971 }
972
973 if (requestData->sensorType != dcmi::temperatureSensorType)
974 {
975 log<level::ERR>("Invalid sensor type",
976 entry("SENSOR_TYPE=%d", requestData->sensorType));
977 return IPMI_CC_INVALID_FIELD_REQUEST;
978 }
979
980 dcmi::temp_readings::ResponseList temps{};
981 try
982 {
983 if (!requestData->entityInstance)
984 {
985 // Read all instances
986 std::tie(temps, responseData->numInstances) =
987 dcmi::temp_readings::readAll(it->second,
988 requestData->instanceStart);
989 }
990 else
991 {
992 // Read one instance
993 temps.resize(1);
994 std::tie(temps[0], responseData->numInstances) =
995 dcmi::temp_readings::read(it->second,
996 requestData->entityInstance);
997 }
998 responseData->numDataSets = temps.size();
999 }
1000 catch (InternalFailure& e)
1001 {
1002 return IPMI_CC_UNSPECIFIED_ERROR;
1003 }
1004
1005 responseData->groupID = dcmi::groupExtId;
Patrick Venture0b02be92018-08-31 11:55:55 -07001006 size_t payloadSize = temps.size() * sizeof(dcmi::temp_readings::Response);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001007 if (!temps.empty())
1008 {
1009 memcpy(responseData + 1, // copy payload right after the response header
Patrick Venture0b02be92018-08-31 11:55:55 -07001010 temps.data(), payloadSize);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001011 }
1012 *data_len = sizeof(dcmi::GetTempReadingsResponseHdr) + payloadSize;
1013
1014 return IPMI_CC_OK;
1015}
1016
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001017int64_t getPowerReading(sdbusplus::bus::bus& bus)
1018{
1019 std::ifstream sensorFile(POWER_READING_SENSOR);
1020 std::string objectPath;
1021 if (!sensorFile.is_open())
1022 {
1023 log<level::ERR>("Power reading configuration file not found",
Patrick Venture0b02be92018-08-31 11:55:55 -07001024 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001025 elog<InternalFailure>();
1026 }
1027
1028 auto data = nlohmann::json::parse(sensorFile, nullptr, false);
1029 if (data.is_discarded())
1030 {
1031 log<level::ERR>("Error in parsing configuration file",
Patrick Venture0b02be92018-08-31 11:55:55 -07001032 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001033 elog<InternalFailure>();
1034 }
1035
1036 objectPath = data.value("path", "");
1037 if (objectPath.empty())
1038 {
1039 log<level::ERR>("Power sensor D-Bus object path is empty",
1040 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
1041 elog<InternalFailure>();
1042 }
1043
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001044 // Return default value if failed to read from D-Bus object
1045 int64_t power = 0;
1046 try
1047 {
1048 auto service = ipmi::getService(bus, SENSOR_VALUE_INTF, objectPath);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001049
Patrick Venture0b02be92018-08-31 11:55:55 -07001050 // Read the sensor value and scale properties
1051 auto properties = ipmi::getAllDbusProperties(bus, service, objectPath,
1052 SENSOR_VALUE_INTF);
William A. Kennington III4c008022018-10-12 17:18:14 -07001053 auto value = variant_ns::get<int64_t>(properties[SENSOR_VALUE_PROP]);
1054 auto scale = variant_ns::get<int64_t>(properties[SENSOR_SCALE_PROP]);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001055
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001056 // Power reading needs to be scaled with the Scale value using the
1057 // formula Value * 10^Scale.
1058 power = value * std::pow(10, scale);
1059 }
1060 catch (std::exception& e)
1061 {
1062 log<level::INFO>("Failure to read power value from D-Bus object",
Patrick Venture0b02be92018-08-31 11:55:55 -07001063 entry("OBJECT_PATH=%s", objectPath.c_str()),
1064 entry("INTERFACE=%s", SENSOR_VALUE_INTF));
Marri Devender Raoce6a7952018-02-11 08:45:00 -06001065 }
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001066 return power;
1067}
1068
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001069ipmi_ret_t setDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1070 ipmi_request_t request, ipmi_response_t response,
1071 ipmi_data_len_t data_len, ipmi_context_t context)
1072{
Patrick Venture0b02be92018-08-31 11:55:55 -07001073 auto requestData =
1074 reinterpret_cast<const dcmi::SetConfParamsRequest*>(request);
1075 auto responseData =
1076 reinterpret_cast<dcmi::SetConfParamsResponse*>(response);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001077
Patrick Venture0b02be92018-08-31 11:55:55 -07001078 if (requestData->groupID != dcmi::groupExtId ||
1079 *data_len < DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE ||
1080 *data_len > DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001081 {
Gunnar Mills8466b792018-03-23 12:18:12 -05001082 log<level::ERR>("Invalid Group ID or Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001083 entry("GROUP_ID=%d", requestData->groupID),
1084 entry("PACKET SIZE=%d", *data_len));
1085 return IPMI_CC_INVALID_FIELD_REQUEST;
1086 }
1087
1088 *data_len = 0;
1089
1090 try
1091 {
1092 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -07001093 switch (
1094 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001095 {
1096 case dcmi::DCMIConfigParameters::ActivateDHCP:
1097
1098 if ((requestData->data[0] & DCMI_ACTIVATE_DHCP_MASK) &&
Patrick Venture0b02be92018-08-31 11:55:55 -07001099 dcmi::getDHCPEnabled())
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001100 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001101 // When these conditions are met we have to trigger DHCP
1102 // protocol restart using the latest parameter settings, but
1103 // as per n/w manager design, each time when we update n/w
1104 // parameters, n/w service is restarted. So we no need to
1105 // take any action in this case.
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001106 }
1107 break;
1108
1109 case dcmi::DCMIConfigParameters::DiscoveryConfig:
1110
1111 if (requestData->data[0] & DCMI_OPTION_12_MASK)
1112 {
1113 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, true);
1114 }
1115 else
1116 {
1117 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, false);
1118 }
1119
1120 // Systemd-networkd doesn't support Random Back off
1121 if (requestData->data[0] & DCMI_RAND_BACK_OFF_MASK)
1122 {
1123 return IPMI_CC_INVALID;
1124 }
1125 break;
1126 // Systemd-networkd doesn't allow to configure DHCP timigs
1127 case dcmi::DCMIConfigParameters::DHCPTiming1:
1128 case dcmi::DCMIConfigParameters::DHCPTiming2:
1129 case dcmi::DCMIConfigParameters::DHCPTiming3:
1130 default:
1131 return IPMI_CC_INVALID;
1132 }
1133 }
1134 catch (std::exception& e)
1135 {
1136 log<level::ERR>(e.what());
1137 return IPMI_CC_UNSPECIFIED_ERROR;
1138 }
1139 responseData->groupID = dcmi::groupExtId;
1140 *data_len = sizeof(dcmi::SetConfParamsResponse);
1141
1142 return IPMI_CC_OK;
1143}
1144
1145ipmi_ret_t getDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1146 ipmi_request_t request, ipmi_response_t response,
1147 ipmi_data_len_t data_len, ipmi_context_t context)
1148{
1149
Patrick Venture0b02be92018-08-31 11:55:55 -07001150 auto requestData =
1151 reinterpret_cast<const dcmi::GetConfParamsRequest*>(request);
1152 auto responseData =
1153 reinterpret_cast<dcmi::GetConfParamsResponse*>(response);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001154
1155 responseData->data[0] = 0x00;
1156
Patrick Venture0b02be92018-08-31 11:55:55 -07001157 if (requestData->groupID != dcmi::groupExtId ||
1158 *data_len != sizeof(dcmi::GetConfParamsRequest))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001159 {
Gunnar Mills8466b792018-03-23 12:18:12 -05001160 log<level::ERR>("Invalid Group ID or Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001161 entry("GROUP_ID=%d", requestData->groupID),
1162 entry("PACKET SIZE=%d", *data_len));
1163 return IPMI_CC_INVALID_FIELD_REQUEST;
1164 }
1165
1166 *data_len = 0;
1167
1168 try
1169 {
1170 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -07001171 switch (
1172 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001173 {
1174 case dcmi::DCMIConfigParameters::ActivateDHCP:
1175 responseData->data[0] = DCMI_ACTIVATE_DHCP_REPLY;
1176 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1177 break;
1178 case dcmi::DCMIConfigParameters::DiscoveryConfig:
1179 if (dcmi::getDHCPOption(DHCP_OPT12_ENABLED))
1180 {
1181 responseData->data[0] |= DCMI_OPTION_12_MASK;
1182 }
1183 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1184 break;
1185 // Get below values from Systemd-networkd source code
1186 case dcmi::DCMIConfigParameters::DHCPTiming1:
1187 responseData->data[0] = DHCP_TIMING1;
1188 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
1189 break;
1190 case dcmi::DCMIConfigParameters::DHCPTiming2:
1191 responseData->data[0] = DHCP_TIMING2_LOWER;
1192 responseData->data[1] = DHCP_TIMING2_UPPER;
1193 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
1194 break;
1195 case dcmi::DCMIConfigParameters::DHCPTiming3:
1196 responseData->data[0] = DHCP_TIMING3_LOWER;
1197 responseData->data[1] = DHCP_TIMING3_UPPER;
1198 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
1199 break;
1200 default:
1201 *data_len = 0;
1202 return IPMI_CC_INVALID;
1203 }
1204 }
1205 catch (std::exception& e)
1206 {
1207 log<level::ERR>(e.what());
1208 return IPMI_CC_UNSPECIFIED_ERROR;
1209 }
1210
1211 responseData->groupID = dcmi::groupExtId;
1212 responseData->major = DCMI_SPEC_MAJOR_VERSION;
1213 responseData->minor = DCMI_SPEC_MINOR_VERSION;
1214 responseData->paramRevision = DCMI_CONFIG_PARAMETER_REVISION;
1215
1216 return IPMI_CC_OK;
1217}
1218
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001219ipmi_ret_t getPowerReading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -07001220 ipmi_request_t request, ipmi_response_t response,
1221 ipmi_data_len_t data_len, ipmi_context_t context)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001222{
1223 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001224 auto requestData =
1225 reinterpret_cast<const dcmi::GetPowerReadingRequest*>(request);
1226 auto responseData =
1227 reinterpret_cast<dcmi::GetPowerReadingResponse*>(response);
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001228
1229 if (requestData->groupID != dcmi::groupExtId)
1230 {
1231 *data_len = 0;
1232 return IPMI_CC_INVALID_FIELD_REQUEST;
1233 }
1234
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001235 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001236 int64_t power = 0;
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001237 try
1238 {
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001239 power = getPowerReading(bus);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001240 }
1241 catch (InternalFailure& e)
1242 {
1243 log<level::ERR>("Error in reading power sensor value",
1244 entry("INTERFACE=%s", SENSOR_VALUE_INTF),
1245 entry("PROPERTY=%s", SENSOR_VALUE_PROP));
1246 return IPMI_CC_UNSPECIFIED_ERROR;
1247 }
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001248 responseData->groupID = dcmi::groupExtId;
1249
1250 // TODO: openbmc/openbmc#2819
Gunnar Mills8466b792018-03-23 12:18:12 -05001251 // Minimum, Maximum, Average power, TimeFrame, TimeStamp,
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001252 // PowerReadingState readings need to be populated
1253 // after Telemetry changes.
1254 uint16_t totalPower = static_cast<uint16_t>(power);
1255 responseData->currentPower = totalPower;
1256 responseData->minimumPower = totalPower;
1257 responseData->maximumPower = totalPower;
1258 responseData->averagePower = totalPower;
1259
1260 *data_len = sizeof(*responseData);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001261 return rc;
1262}
1263
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001264namespace dcmi
1265{
1266namespace sensor_info
1267{
1268
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001269Response createFromJson(const Json& config)
1270{
1271 Response response{};
1272 uint16_t recordId = config.value("record_id", 0);
1273 response.recordIdLsb = recordId & 0xFF;
1274 response.recordIdMsb = (recordId >> 8) & 0xFF;
1275 return response;
1276}
1277
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001278std::tuple<Response, NumInstances> read(const std::string& type,
Patrick Venture0b02be92018-08-31 11:55:55 -07001279 uint8_t instance, const Json& config)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001280{
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001281 Response response{};
1282
1283 if (!instance)
1284 {
1285 log<level::ERR>("Expected non-zero instance");
1286 elog<InternalFailure>();
1287 }
1288
1289 static const std::vector<Json> empty{};
1290 std::vector<Json> readings = config.value(type, empty);
1291 size_t numInstances = readings.size();
1292 for (const auto& reading : readings)
1293 {
1294 uint8_t instanceNum = reading.value("instance", 0);
1295 // Not the instance we're interested in
1296 if (instanceNum != instance)
1297 {
1298 continue;
1299 }
1300
1301 response = createFromJson(reading);
1302
1303 // Found the instance we're interested in
1304 break;
1305 }
1306
1307 if (numInstances > maxInstances)
1308 {
1309 log<level::DEBUG>("Trimming IPMI num instances",
1310 entry("NUM_INSTANCES=%d", numInstances));
1311 numInstances = maxInstances;
1312 }
1313 return std::make_tuple(response, numInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001314}
1315
Patrick Venture0b02be92018-08-31 11:55:55 -07001316std::tuple<ResponseList, NumInstances>
1317 readAll(const std::string& type, uint8_t instanceStart, const Json& config)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001318{
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001319 ResponseList responses{};
1320
1321 size_t numInstances = 0;
1322 static const std::vector<Json> empty{};
1323 std::vector<Json> readings = config.value(type, empty);
1324 numInstances = readings.size();
1325 for (const auto& reading : readings)
1326 {
1327 try
1328 {
1329 // Max of 8 records
1330 if (responses.size() == maxRecords)
1331 {
1332 break;
1333 }
1334
1335 uint8_t instanceNum = reading.value("instance", 0);
1336 // Not in the instance range we're interested in
1337 if (instanceNum < instanceStart)
1338 {
1339 continue;
1340 }
1341
1342 Response response = createFromJson(reading);
1343 responses.push_back(response);
1344 }
1345 catch (std::exception& e)
1346 {
1347 log<level::DEBUG>(e.what());
1348 continue;
1349 }
1350 }
1351
1352 if (numInstances > maxInstances)
1353 {
1354 log<level::DEBUG>("Trimming IPMI num instances",
1355 entry("NUM_INSTANCES=%d", numInstances));
1356 numInstances = maxInstances;
1357 }
1358 return std::make_tuple(responses, numInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001359}
1360
1361} // namespace sensor_info
1362} // namespace dcmi
1363
1364ipmi_ret_t getSensorInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1365 ipmi_request_t request, ipmi_response_t response,
1366 ipmi_data_len_t data_len, ipmi_context_t context)
1367{
1368 auto requestData =
1369 reinterpret_cast<const dcmi::GetSensorInfoRequest*>(request);
1370 auto responseData =
1371 reinterpret_cast<dcmi::GetSensorInfoResponseHdr*>(response);
1372
1373 if (*data_len != sizeof(dcmi::GetSensorInfoRequest))
1374 {
1375 log<level::ERR>("Malformed request data",
1376 entry("DATA_SIZE=%d", *data_len));
1377 return IPMI_CC_REQ_DATA_LEN_INVALID;
1378 }
1379 *data_len = 0;
1380
1381 auto it = dcmi::entityIdToName.find(requestData->entityId);
1382 if (it == dcmi::entityIdToName.end())
1383 {
1384 log<level::ERR>("Unknown Entity ID",
1385 entry("ENTITY_ID=%d", requestData->entityId));
1386 return IPMI_CC_INVALID_FIELD_REQUEST;
1387 }
1388
1389 if (requestData->groupID != dcmi::groupExtId)
1390 {
1391 log<level::ERR>("Invalid Group ID",
1392 entry("GROUP_ID=%d", requestData->groupID));
1393 return IPMI_CC_INVALID_FIELD_REQUEST;
1394 }
1395
1396 if (requestData->sensorType != dcmi::temperatureSensorType)
1397 {
1398 log<level::ERR>("Invalid sensor type",
1399 entry("SENSOR_TYPE=%d", requestData->sensorType));
1400 return IPMI_CC_INVALID_FIELD_REQUEST;
1401 }
1402
1403 dcmi::sensor_info::ResponseList sensors{};
1404 static dcmi::Json config{};
1405 static bool parsed = false;
1406
1407 try
1408 {
1409 if (!parsed)
1410 {
Kirill Pakhomova2573622018-11-02 19:00:18 +03001411 config = dcmi::parseJSONConfig(dcmi::gDCMISensorsConfig);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001412 parsed = true;
1413 }
1414
1415 if (!requestData->entityInstance)
1416 {
1417 // Read all instances
1418 std::tie(sensors, responseData->numInstances) =
1419 dcmi::sensor_info::readAll(it->second,
Patrick Venture0b02be92018-08-31 11:55:55 -07001420 requestData->instanceStart, config);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001421 }
1422 else
1423 {
1424 // Read one instance
1425 sensors.resize(1);
1426 std::tie(sensors[0], responseData->numInstances) =
Patrick Venture0b02be92018-08-31 11:55:55 -07001427 dcmi::sensor_info::read(it->second, requestData->entityInstance,
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001428 config);
1429 }
1430 responseData->numRecords = sensors.size();
1431 }
1432 catch (InternalFailure& e)
1433 {
1434 return IPMI_CC_UNSPECIFIED_ERROR;
1435 }
1436
1437 responseData->groupID = dcmi::groupExtId;
1438 size_t payloadSize = sensors.size() * sizeof(dcmi::sensor_info::Response);
1439 if (!sensors.empty())
1440 {
1441 memcpy(responseData + 1, // copy payload right after the response header
Patrick Venture0b02be92018-08-31 11:55:55 -07001442 sensors.data(), payloadSize);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001443 }
1444 *data_len = sizeof(dcmi::GetSensorInfoResponseHdr) + payloadSize;
1445
1446 return IPMI_CC_OK;
1447}
1448
Chris Austen1810bec2015-10-13 12:12:39 -05001449void register_netfn_dcmi_functions()
1450{
Tom05732372016-09-06 17:21:23 +05301451 // <Get Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301452
Patrick Venture0b02be92018-08-31 11:55:55 -07001453 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_LIMIT, NULL,
1454 getPowerLimit, PRIVILEGE_USER);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301455
Tom Joseph46fa37d2017-07-26 18:11:55 +05301456 // <Set Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301457
Patrick Venture0b02be92018-08-31 11:55:55 -07001458 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_POWER_LIMIT, NULL,
1459 setPowerLimit, PRIVILEGE_OPERATOR);
Tom Joseph46fa37d2017-07-26 18:11:55 +05301460
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301461 // <Activate/Deactivate Power Limit>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301462
1463 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::APPLY_POWER_LIMIT,
1464 NULL, applyPowerLimit, PRIVILEGE_OPERATOR);
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301465
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301466 // <Get Asset Tag>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301467
Patrick Venture0b02be92018-08-31 11:55:55 -07001468 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_ASSET_TAG, NULL,
1469 getAssetTag, PRIVILEGE_USER);
Tom Joseph545dd232017-07-12 20:20:49 +05301470
1471 // <Set Asset Tag>
Ratan Gupta11ddbd22017-08-05 11:59:39 +05301472
Patrick Venture0b02be92018-08-31 11:55:55 -07001473 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_ASSET_TAG, NULL,
1474 setAssetTag, PRIVILEGE_OPERATOR);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001475
Gunnar Mills8991dd62017-10-25 17:11:29 -05001476 // <Get Management Controller Identifier String>
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001477
1478 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_MGMNT_CTRL_ID_STR,
Patrick Venture0b02be92018-08-31 11:55:55 -07001479 NULL, getMgmntCtrlIdStr, PRIVILEGE_USER);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001480
1481 // <Set Management Controller Identifier String>
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001482 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_MGMNT_CTRL_ID_STR,
Patrick Venture0b02be92018-08-31 11:55:55 -07001483 NULL, setMgmntCtrlIdStr, PRIVILEGE_ADMIN);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001484
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -06001485 // <Get DCMI capabilities>
1486 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CAPABILITIES,
Patrick Venture0b02be92018-08-31 11:55:55 -07001487 NULL, getDCMICapabilities, PRIVILEGE_USER);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001488
1489 // <Get Temperature Readings>
1490 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_TEMP_READINGS,
1491 NULL, getTempReadings, PRIVILEGE_USER);
1492
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001493 // <Get Power Reading>
1494 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_READING,
1495 NULL, getPowerReading, PRIVILEGE_USER);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001496
1497 // <Get Sensor Info>
Patrick Venture0b02be92018-08-31 11:55:55 -07001498 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_SENSOR_INFO, NULL,
1499 getSensorInfo, PRIVILEGE_USER);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001500
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001501 // <Get DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001502 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CONF_PARAMS, NULL,
1503 getDCMIConfParams, PRIVILEGE_USER);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001504
1505 // <Set DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001506 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_CONF_PARAMS, NULL,
1507 setDCMIConfParams, PRIVILEGE_ADMIN);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001508
Chris Austen1810bec2015-10-13 12:12:39 -05001509 return;
1510}
Tom05732372016-09-06 17:21:23 +05301511// 956379