blob: 540c9b3b5f6779d147cf577fee054e77c721166c [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
Vernon Mauerye08fbff2019-04-03 09:19:34 -07007#include <ipmid/api.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -07008#include <ipmid/utils.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -07009#include <nlohmann/json.hpp>
Tom Josephbe5eaa12017-07-12 19:54:44 +053010#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050011#include <phosphor-logging/log.hpp>
12#include <sdbusplus/bus.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070013#include <xyz/openbmc_project/Common/error.hpp>
Thang Tran55cbf552023-01-31 14:43:02 +070014#include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070015
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050016#include <bitset>
17#include <cmath>
18#include <fstream>
19#include <variant>
20
Tom Josephbe5eaa12017-07-12 19:54:44 +053021using namespace phosphor::logging;
Thang Tran55cbf552023-01-31 14:43:02 +070022using sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
23
Tom Josephbe5eaa12017-07-12 19:54:44 +053024using InternalFailure =
Patrick Venture0b02be92018-08-31 11:55:55 -070025 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Chris Austen1810bec2015-10-13 12:12:39 -050026
27void register_netfn_dcmi_functions() __attribute__((constructor));
28
Vernon Maueryd4222fd2023-07-27 11:26:51 -070029constexpr auto pcapPath = "/xyz/openbmc_project/control/host0/power_cap";
30constexpr auto pcapInterface = "xyz.openbmc_project.Control.Power.Cap";
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050031
Vernon Maueryd4222fd2023-07-27 11:26:51 -070032constexpr auto powerCapProp = "PowerCap";
33constexpr auto powerCapEnableProp = "PowerCapEnable";
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050034
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -060035constexpr auto DCMI_SPEC_MAJOR_VERSION = 1;
36constexpr auto DCMI_SPEC_MINOR_VERSION = 5;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060037constexpr auto DCMI_CONFIG_PARAMETER_REVISION = 1;
38constexpr auto DCMI_RAND_BACK_OFF_MASK = 0x80;
39constexpr auto DCMI_OPTION_60_43_MASK = 0x02;
40constexpr auto DCMI_OPTION_12_MASK = 0x01;
41constexpr auto DCMI_ACTIVATE_DHCP_MASK = 0x01;
42constexpr auto DCMI_ACTIVATE_DHCP_REPLY = 0x00;
William A. Kennington III5d06cc62019-04-25 02:10:55 -070043constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE = 0x04;
44constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE = 0x03;
Patrick Venture0b02be92018-08-31 11:55:55 -070045constexpr auto DHCP_TIMING1 = 0x04; // 4 sec
46constexpr auto DHCP_TIMING2_UPPER = 0x00; // 2 min
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060047constexpr auto DHCP_TIMING2_LOWER = 0x78;
Patrick Venture0b02be92018-08-31 11:55:55 -070048constexpr auto DHCP_TIMING3_UPPER = 0x00; // 64 sec
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -060049constexpr auto DHCP_TIMING3_LOWER = 0x40;
50// When DHCP Option 12 is enabled the string "SendHostName=true" will be
51// added into n/w configuration file and the parameter
52// SendHostNameEnabled will set to true.
53constexpr auto DHCP_OPT12_ENABLED = "SendHostNameEnabled";
54
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050055using namespace phosphor::logging;
56
Tom Josephb9d86f42017-07-26 18:03:47 +053057namespace dcmi
58{
Vernon Mauerydca47202023-07-27 11:32:01 -070059constexpr auto assetTagMaxOffset = 62;
60constexpr auto assetTagMaxSize = 63;
61constexpr auto maxBytes = 16;
62constexpr size_t maxCtrlIdStrLen = 63;
Tom Josephb9d86f42017-07-26 18:03:47 +053063
Vernon Maueryf038dc02023-07-27 14:06:11 -070064constexpr uint8_t parameterRevision = 2;
65constexpr uint8_t specMajorVersion = 1;
66constexpr uint8_t specMinorVersion = 5;
Vernon Mauerycce9ffd2023-07-27 14:15:17 -070067constexpr auto sensorValueIntf = "xyz.openbmc_project.Sensor.Value";
68constexpr auto sensorValueProp = "Value";
Vernon Maueryf038dc02023-07-27 14:06:11 -070069
Deepak Kodihalli0b459552018-02-06 06:25:12 -060070// Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
Patrick Venture0b02be92018-08-31 11:55:55 -070071static const std::map<uint8_t, std::string> entityIdToName{
72 {0x40, "inlet"}, {0x37, "inlet"}, {0x41, "cpu"},
73 {0x03, "cpu"}, {0x42, "baseboard"}, {0x07, "baseboard"}};
Deepak Kodihalli0b459552018-02-06 06:25:12 -060074
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +030075bool isDCMIPowerMgmtSupported()
76{
Vernon Maueryf4eb35d2023-07-27 11:08:49 -070077 static bool parsed = false;
78 static bool supported = false;
79 if (!parsed)
80 {
81 auto data = parseJSONConfig(gDCMICapabilitiesConfig);
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +030082
Vernon Maueryf4eb35d2023-07-27 11:08:49 -070083 supported = (gDCMIPowerMgmtSupported ==
84 data.value(gDCMIPowerMgmtCapability, 0));
85 }
86 return supported;
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +030087}
88
Vernon Maueryd4222fd2023-07-27 11:26:51 -070089std::optional<uint32_t> getPcap(ipmi::Context::ptr& ctx)
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050090{
Vernon Maueryd4222fd2023-07-27 11:26:51 -070091 std::string service{};
92 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
93 pcapPath, service);
94 if (ec.value())
Andrew Geissler50c0c8f2017-07-11 16:18:51 -050095 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -070096 return std::nullopt;
George Liu3e3cc352023-07-26 15:59:31 +080097 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -070098 uint32_t pcap{};
99 ec = ipmi::getDbusProperty(ctx, service, pcapPath, pcapInterface,
100 powerCapProp, pcap);
101 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800102 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700103 log<level::ERR>("Error in getPcap prop",
104 entry("ERROR=%s", ec.message().c_str()));
Tom Josephb9d86f42017-07-26 18:03:47 +0530105 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700106 return std::nullopt;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500107 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700108 return pcap;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500109}
110
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700111std::optional<bool> getPcapEnabled(ipmi::Context::ptr& ctx)
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500112{
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700113 std::string service{};
114 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
115 pcapPath, service);
116 if (ec.value())
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500117 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700118 return std::nullopt;
George Liu3e3cc352023-07-26 15:59:31 +0800119 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700120 bool pcapEnabled{};
121 ec = ipmi::getDbusProperty(ctx, service, pcapPath, pcapInterface,
122 powerCapEnableProp, pcapEnabled);
123 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800124 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700125 log<level::ERR>("Error in getPcap prop");
Tom Josephb9d86f42017-07-26 18:03:47 +0530126 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700127 return std::nullopt;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500128 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700129 return pcapEnabled;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500130}
Chris Austen1810bec2015-10-13 12:12:39 -0500131
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700132bool setPcap(ipmi::Context::ptr& ctx, const uint32_t powerCap)
Tom Joseph46fa37d2017-07-26 18:11:55 +0530133{
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700134 std::string service{};
135 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
136 pcapPath, service);
137 if (ec.value())
Tom Joseph46fa37d2017-07-26 18:11:55 +0530138 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700139 return false;
George Liu3e3cc352023-07-26 15:59:31 +0800140 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700141
142 ec = ipmi::setDbusProperty(ctx, service, pcapPath, pcapInterface,
143 powerCapProp, powerCap);
144 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800145 {
146 log<level::ERR>("Error in setPcap property",
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700147 entry("ERROR=%s", ec.message().c_str()));
Tom Joseph46fa37d2017-07-26 18:11:55 +0530148 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700149 return false;
Tom Joseph46fa37d2017-07-26 18:11:55 +0530150 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700151 return true;
Tom Joseph46fa37d2017-07-26 18:11:55 +0530152}
153
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700154bool setPcapEnable(ipmi::Context::ptr& ctx, bool enabled)
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530155{
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700156 std::string service{};
157 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
158 pcapPath, service);
159 if (ec.value())
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530160 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700161 return false;
George Liu3e3cc352023-07-26 15:59:31 +0800162 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700163
164 ec = ipmi::setDbusProperty(ctx, service, pcapPath, pcapInterface,
165 powerCapEnableProp, enabled);
166 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800167 {
168 log<level::ERR>("Error in setPcapEnabled property",
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700169 entry("ERROR=%s", ec.message().c_str()));
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530170 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700171 return false;
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530172 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700173 return true;
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530174}
175
Vernon Mauerydca47202023-07-27 11:32:01 -0700176std::optional<std::string> readAssetTag(ipmi::Context::ptr& ctx)
Tom Josephbe5eaa12017-07-12 19:54:44 +0530177{
Tom Josephbe5eaa12017-07-12 19:54:44 +0530178 // Read the object tree with the inventory root to figure out the object
179 // that has implemented the Asset tag interface.
Vernon Mauerydca47202023-07-27 11:32:01 -0700180 ipmi::DbusObjectInfo objectInfo;
181 boost::system::error_code ec = getDbusObject(
182 ctx, dcmi::assetTagIntf, ipmi::sensor::inventoryRoot, "", objectInfo);
183 if (ec.value())
Tom Josephbe5eaa12017-07-12 19:54:44 +0530184 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700185 return std::nullopt;
George Liu3e3cc352023-07-26 15:59:31 +0800186 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700187
188 std::string assetTag{};
189 ec = ipmi::getDbusProperty(ctx, objectInfo.second, objectInfo.first,
190 dcmi::assetTagIntf, dcmi::assetTagProp,
191 assetTag);
192 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800193 {
194 log<level::ERR>("Error in reading asset tag",
Vernon Mauerydca47202023-07-27 11:32:01 -0700195 entry("ERROR=%s", ec.message().c_str()));
Tom Josephbe5eaa12017-07-12 19:54:44 +0530196 elog<InternalFailure>();
Vernon Mauerydca47202023-07-27 11:32:01 -0700197 return std::nullopt;
Tom Josephbe5eaa12017-07-12 19:54:44 +0530198 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700199
200 return assetTag;
Tom Josephbe5eaa12017-07-12 19:54:44 +0530201}
202
Vernon Mauerydca47202023-07-27 11:32:01 -0700203bool writeAssetTag(ipmi::Context::ptr& ctx, const std::string& assetTag)
Tom Josephbe5b9892017-07-15 00:55:23 +0530204{
Tom Josephbe5b9892017-07-15 00:55:23 +0530205 // Read the object tree with the inventory root to figure out the object
206 // that has implemented the Asset tag interface.
Vernon Mauerydca47202023-07-27 11:32:01 -0700207 ipmi::DbusObjectInfo objectInfo;
208 boost::system::error_code ec = getDbusObject(
209 ctx, dcmi::assetTagIntf, ipmi::sensor::inventoryRoot, "", objectInfo);
210 if (ec.value())
Tom Josephbe5b9892017-07-15 00:55:23 +0530211 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700212 return false;
George Liu3e3cc352023-07-26 15:59:31 +0800213 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700214
215 ec = ipmi::setDbusProperty(ctx, objectInfo.second, objectInfo.first,
216 dcmi::assetTagIntf, dcmi::assetTagProp,
217 assetTag);
218 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800219 {
220 log<level::ERR>("Error in writing asset tag",
Vernon Mauerydca47202023-07-27 11:32:01 -0700221 entry("ERROR=%s", ec.message().c_str()));
Tom Josephbe5b9892017-07-15 00:55:23 +0530222 elog<InternalFailure>();
Vernon Mauerydca47202023-07-27 11:32:01 -0700223 return false;
Tom Josephbe5b9892017-07-15 00:55:23 +0530224 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700225 return true;
Tom Josephbe5b9892017-07-15 00:55:23 +0530226}
227
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700228std::optional<std::string> getHostName(ipmi::Context::ptr& ctx)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300229{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700230 std::string service{};
231 boost::system::error_code ec = ipmi::getService(ctx, networkConfigIntf,
232 networkConfigObj, service);
233 if (ec.value())
234 {
235 return std::nullopt;
236 }
237 std::string hostname{};
238 ec = ipmi::getDbusProperty(ctx, service, networkConfigObj,
239 networkConfigIntf, hostNameProp, hostname);
240 if (ec.value())
241 {
242 log<level::ERR>("Error fetching hostname");
243 elog<InternalFailure>();
244 return std::nullopt;
245 }
246 return hostname;
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300247}
248
Thang Tran55cbf552023-01-31 14:43:02 +0700249EthernetInterface::DHCPConf getDHCPEnabled()
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600250{
Patrick Williams5d82f472022-07-22 19:26:53 -0500251 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600252
Johnathan Mantey74a21022018-12-13 13:17:56 -0800253 auto ethdevice = ipmi::getChannelName(ethernetDefaultChannelNum);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500254 auto ethernetObj = ipmi::getDbusObject(bus, ethernetIntf, networkRoot,
255 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
Thang Tran55cbf552023-01-31 14:43:02 +0700260 return EthernetInterface::convertDHCPConfFromString(
261 std::get<std::string>(value));
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600262}
263
264bool getDHCPOption(std::string prop)
265{
Patrick Williams5d82f472022-07-22 19:26:53 -0500266 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600267
268 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
269 auto value = ipmi::getDbusProperty(bus, service, dhcpObj, dhcpIntf, prop);
270
Vernon Maueryf442e112019-04-09 11:44:36 -0700271 return std::get<bool>(value);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600272}
273
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600274void setDHCPOption(std::string prop, bool value)
275{
Patrick Williams5d82f472022-07-22 19:26:53 -0500276 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600277
278 auto service = ipmi::getService(bus, dhcpIntf, dhcpObj);
279 ipmi::setDbusProperty(bus, service, dhcpObj, dhcpIntf, prop, value);
280}
281
Kirill Pakhomova2573622018-11-02 19:00:18 +0300282Json parseJSONConfig(const std::string& configFile)
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600283{
284 std::ifstream jsonFile(configFile);
285 if (!jsonFile.is_open())
286 {
287 log<level::ERR>("Temperature readings JSON file not found");
288 elog<InternalFailure>();
289 }
290
291 auto data = Json::parse(jsonFile, nullptr, false);
292 if (data.is_discarded())
293 {
294 log<level::ERR>("Temperature readings JSON parser failure");
295 elog<InternalFailure>();
296 }
297
298 return data;
299}
300
Tom Josephbe5eaa12017-07-12 19:54:44 +0530301} // namespace dcmi
Chris Austen1810bec2015-10-13 12:12:39 -0500302
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700303constexpr uint8_t exceptionPowerOff = 0x01;
304ipmi::RspType<uint16_t, // reserved
305 uint8_t, // exception actions
306 uint16_t, // power limit requested in watts
307 uint32_t, // correction time in milliseconds
308 uint16_t, // reserved
309 uint16_t // statistics sampling period in seconds
310 >
311 getPowerLimit(ipmi::Context::ptr ctx, uint16_t reserved)
Tom Josephb9d86f42017-07-26 18:03:47 +0530312{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300313 if (!dcmi::isDCMIPowerMgmtSupported())
314 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700315 return ipmi::responseInvalidCommand();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300316 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700317 if (reserved)
Tom Josephb9d86f42017-07-26 18:03:47 +0530318 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700319 return ipmi::responseInvalidFieldRequest();
Tom Josephb9d86f42017-07-26 18:03:47 +0530320 }
321
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700322 std::optional<uint16_t> pcapValue = dcmi::getPcap(ctx);
323 std::optional<bool> pcapEnable = dcmi::getPcapEnabled(ctx);
324 if (!pcapValue || !pcapEnable)
325 {
326 return ipmi::responseUnspecifiedError();
327 }
328
329 constexpr uint16_t reserved1{};
330 constexpr uint16_t reserved2{};
Tom Josephb9d86f42017-07-26 18:03:47 +0530331 /*
332 * Exception action if power limit is exceeded and cannot be controlled
333 * with the correction time limit is hardcoded to Hard Power Off system
334 * and log event to SEL.
335 */
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700336 constexpr uint8_t exception = exceptionPowerOff;
Tom Josephb9d86f42017-07-26 18:03:47 +0530337 /*
338 * Correction time limit and Statistics sampling period is currently not
339 * populated.
340 */
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700341 constexpr uint32_t correctionTime{};
342 constexpr uint16_t statsPeriod{};
343 if (!pcapEnable)
Tom Josephb9d86f42017-07-26 18:03:47 +0530344 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700345 constexpr ipmi::Cc responseNoPowerLimitSet = 0x80;
346 constexpr uint16_t noPcap{};
347 return ipmi::response(responseNoPowerLimitSet, reserved1, exception,
348 noPcap, correctionTime, reserved2, statsPeriod);
Tom Josephb9d86f42017-07-26 18:03:47 +0530349 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700350 return ipmi::responseSuccess(reserved1, exception, *pcapValue,
351 correctionTime, reserved2, statsPeriod);
Tom Josephb9d86f42017-07-26 18:03:47 +0530352}
353
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700354ipmi::RspType<> setPowerLimit(ipmi::Context::ptr& ctx, uint16_t reserved1,
355 uint8_t exceptionAction, uint16_t powerLimit,
356 uint32_t correctionTime, uint16_t reserved2,
357 uint16_t statsPeriod)
Tom Joseph46fa37d2017-07-26 18:11:55 +0530358{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300359 if (!dcmi::isDCMIPowerMgmtSupported())
360 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300361 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700362 return ipmi::responseInvalidCommand();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300363 }
364
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700365 // Only process the power limit requested in watts. Return errors
366 // for other fields that are set
367 if (reserved1 || reserved2 || correctionTime || statsPeriod ||
368 exceptionAction != exceptionPowerOff)
Tom Joseph46fa37d2017-07-26 18:11:55 +0530369 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700370 return ipmi::responseInvalidFieldRequest();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530371 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700372
373 if (!dcmi::setPcap(ctx, powerLimit))
Tom Joseph46fa37d2017-07-26 18:11:55 +0530374 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700375 return ipmi::responseUnspecifiedError();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530376 }
377
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700378 log<level::INFO>("Set Power Cap", entry("POWERCAP=%u", powerLimit));
Tom Joseph46fa37d2017-07-26 18:11:55 +0530379
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700380 return ipmi::responseSuccess();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530381}
382
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700383ipmi::RspType<> applyPowerLimit(ipmi::Context::ptr& ctx, bool enabled,
384 uint7_t reserved1, uint16_t reserved2)
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530385{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300386 if (!dcmi::isDCMIPowerMgmtSupported())
387 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300388 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700389 return ipmi::responseInvalidCommand();
390 }
391 if (reserved1 || reserved2)
392 {
393 return ipmi::responseInvalidFieldRequest();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300394 }
395
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700396 if (!dcmi::setPcapEnable(ctx, enabled))
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530397 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700398 return ipmi::responseUnspecifiedError();
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530399 }
400
401 log<level::INFO>("Set Power Cap Enable",
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700402 entry("POWERCAPENABLE=%u", static_cast<uint8_t>(enabled)));
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530403
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700404 return ipmi::responseSuccess();
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530405}
406
Vernon Mauerydca47202023-07-27 11:32:01 -0700407ipmi::RspType<uint8_t, // total tag length
408 std::vector<char> // tag data
409 >
410 getAssetTag(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count)
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530411{
Vernon Mauerydca47202023-07-27 11:32:01 -0700412 // Verify offset to read and number of bytes to read are not exceeding
413 // the range.
414 if ((offset > dcmi::assetTagMaxOffset) || (count > dcmi::maxBytes) ||
415 ((offset + count) > dcmi::assetTagMaxSize))
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530416 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700417 return ipmi::responseParmOutOfRange();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530418 }
419
Vernon Mauerydca47202023-07-27 11:32:01 -0700420 std::optional<std::string> assetTagResp = dcmi::readAssetTag(ctx);
421 if (!assetTagResp)
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530422 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700423 return ipmi::responseUnspecifiedError();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530424 }
425
Vernon Mauerydca47202023-07-27 11:32:01 -0700426 std::string& assetTag = assetTagResp.value();
427 // If the asset tag is longer than 63 bytes, restrict it to 63 bytes to
428 // suit Get Asset Tag command.
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530429 if (assetTag.size() > dcmi::assetTagMaxSize)
430 {
431 assetTag.resize(dcmi::assetTagMaxSize);
432 }
433
Vernon Mauerydca47202023-07-27 11:32:01 -0700434 if (offset >= assetTag.size())
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530435 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700436 return ipmi::responseParmOutOfRange();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530437 }
438
Vernon Mauerydca47202023-07-27 11:32:01 -0700439 // silently truncate reads beyond the end of assetTag
440 if ((offset + count) >= assetTag.size())
441 {
442 count = assetTag.size() - offset;
443 }
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530444
Vernon Mauerydca47202023-07-27 11:32:01 -0700445 auto totalTagSize = static_cast<uint8_t>(assetTag.size());
446 std::vector<char> data{assetTag.begin() + offset,
447 assetTag.begin() + offset + count};
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530448
Vernon Mauerydca47202023-07-27 11:32:01 -0700449 return ipmi::responseSuccess(totalTagSize, data);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530450}
451
Vernon Mauerydca47202023-07-27 11:32:01 -0700452ipmi::RspType<uint8_t // new asset tag length
453 >
454 setAssetTag(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count,
455 const std::vector<char>& data)
Tom Joseph545dd232017-07-12 20:20:49 +0530456{
Vernon Mauerydca47202023-07-27 11:32:01 -0700457 // Verify offset to read and number of bytes to read are not exceeding
458 // the range.
459 if ((offset > dcmi::assetTagMaxOffset) || (count > dcmi::maxBytes) ||
460 ((offset + count) > dcmi::assetTagMaxSize))
Tom Joseph545dd232017-07-12 20:20:49 +0530461 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700462 return ipmi::responseParmOutOfRange();
463 }
464 if (data.size() != count)
465 {
466 return ipmi::responseReqDataLenInvalid();
Tom Joseph545dd232017-07-12 20:20:49 +0530467 }
468
Vernon Mauerydca47202023-07-27 11:32:01 -0700469 std::optional<std::string> assetTagResp = dcmi::readAssetTag(ctx);
470 if (!assetTagResp)
Tom Joseph545dd232017-07-12 20:20:49 +0530471 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700472 return ipmi::responseUnspecifiedError();
Tom Joseph545dd232017-07-12 20:20:49 +0530473 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700474
475 std::string& assetTag = assetTagResp.value();
476
477 if (offset > assetTag.size())
Tom Joseph545dd232017-07-12 20:20:49 +0530478 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700479 return ipmi::responseParmOutOfRange();
Tom Joseph545dd232017-07-12 20:20:49 +0530480 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700481
482 // operation is to truncate at offset and append new data
483 assetTag.resize(offset);
484 assetTag.append(data.begin(), data.end());
485
486 if (!dcmi::writeAssetTag(ctx, assetTag))
487 {
488 return ipmi::responseUnspecifiedError();
489 }
490
491 auto totalTagSize = static_cast<uint8_t>(assetTag.size());
492 return ipmi::responseSuccess(totalTagSize);
Tom Joseph545dd232017-07-12 20:20:49 +0530493}
494
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700495ipmi::RspType<uint8_t, // length
496 std::vector<char> // data
497 >
498 getMgmntCtrlIdStr(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300499{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700500 if (count > dcmi::maxBytes || offset + count > dcmi::maxCtrlIdStrLen)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300501 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700502 return ipmi::responseParmOutOfRange();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300503 }
504
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700505 std::optional<std::string> hostnameResp = dcmi::getHostName(ctx);
506 if (!hostnameResp)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300507 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700508 return ipmi::responseUnspecifiedError();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300509 }
510
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700511 std::string& hostname = hostnameResp.value();
512 // If the id string is longer than 63 bytes, restrict it to 63 bytes to
513 // suit set management ctrl str command.
514 if (hostname.size() > dcmi::maxCtrlIdStrLen)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300515 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700516 hostname.resize(dcmi::maxCtrlIdStrLen);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300517 }
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300518
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700519 if (offset >= hostname.size())
520 {
521 return ipmi::responseParmOutOfRange();
522 }
523
524 // silently truncate reads beyond the end of hostname
525 if ((offset + count) >= hostname.size())
526 {
527 count = hostname.size() - offset;
528 }
529
530 auto nameSize = static_cast<uint8_t>(hostname.size());
531 std::vector<char> data{hostname.begin() + offset,
532 hostname.begin() + offset + count};
533
534 return ipmi::responseSuccess(nameSize, data);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300535}
536
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700537ipmi::RspType<uint8_t> setMgmntCtrlIdStr(ipmi::Context::ptr& ctx,
538 uint8_t offset, uint8_t count,
539 std::vector<char> data)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300540{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700541 if ((offset > dcmi::maxCtrlIdStrLen) || (count > dcmi::maxBytes) ||
542 ((offset + count) > dcmi::maxCtrlIdStrLen))
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300543 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700544 return ipmi::responseParmOutOfRange();
545 }
546 if (data.size() != count)
547 {
548 return ipmi::responseReqDataLenInvalid();
549 }
550 bool terminalWrite{data.back() == '\0'};
551 if (terminalWrite)
552 {
553 // remove the null termination from the data (no need with std::string)
554 data.resize(count - 1);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300555 }
556
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700557 static std::string hostname{};
558 // read in the current value if not starting at offset 0
559 if (hostname.size() == 0 && offset != 0)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300560 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700561 /* read old ctrlIdStr */
562 std::optional<std::string> hostnameResp = dcmi::getHostName(ctx);
563 if (!hostnameResp)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300564 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700565 return ipmi::responseUnspecifiedError();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300566 }
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700567 hostname = hostnameResp.value();
568 hostname.resize(offset);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300569 }
570
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700571 // operation is to truncate at offset and append new data
572 hostname.append(data.begin(), data.end());
573
574 // do the update if this is the last write
575 if (terminalWrite)
576 {
577 boost::system::error_code ec = ipmi::setDbusProperty(
578 ctx, dcmi::networkServiceName, dcmi::networkConfigObj,
579 dcmi::networkConfigIntf, dcmi::hostNameProp, hostname);
580 hostname.clear();
581 if (ec.value())
582 {
583 return ipmi::responseUnspecifiedError();
584 }
585 }
586
587 auto totalIdSize = static_cast<uint8_t>(offset + count);
588 return ipmi::responseSuccess(totalIdSize);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300589}
590
Vernon Maueryf038dc02023-07-27 14:06:11 -0700591ipmi::RspType<ipmi::message::Payload> getDCMICapabilities(uint8_t parameter)
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600592{
Kirill Pakhomova2573622018-11-02 19:00:18 +0300593 std::ifstream dcmiCapFile(dcmi::gDCMICapabilitiesConfig);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600594 if (!dcmiCapFile.is_open())
595 {
596 log<level::ERR>("DCMI Capabilities file not found");
Vernon Maueryf038dc02023-07-27 14:06:11 -0700597 return ipmi::responseUnspecifiedError();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600598 }
599
600 auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false);
601 if (data.is_discarded())
602 {
603 log<level::ERR>("DCMI Capabilities JSON parser failure");
Vernon Maueryf038dc02023-07-27 14:06:11 -0700604 return ipmi::responseUnspecifiedError();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600605 }
606
Vernon Maueryf038dc02023-07-27 14:06:11 -0700607 constexpr bool reserved1{};
608 constexpr uint5_t reserved5{};
609 constexpr uint7_t reserved7{};
610 constexpr uint8_t reserved8{};
611 constexpr uint16_t reserved16{};
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600612
Vernon Maueryf038dc02023-07-27 14:06:11 -0700613 ipmi::message::Payload payload;
614 payload.pack(dcmi::specMajorVersion, dcmi::specMinorVersion,
615 dcmi::parameterRevision);
616
617 enum class DCMICapParameters : uint8_t
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600618 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700619 SupportedDcmiCaps = 0x01, // Supported DCMI Capabilities
620 MandatoryPlatAttributes = 0x02, // Mandatory Platform Attributes
621 OptionalPlatAttributes = 0x03, // Optional Platform Attributes
622 ManageabilityAccessAttributes = 0x04, // Manageability Access Attributes
623 };
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600624
Vernon Maueryf038dc02023-07-27 14:06:11 -0700625 switch (static_cast<DCMICapParameters>(parameter))
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600626 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700627 case DCMICapParameters::SupportedDcmiCaps:
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600628 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700629 bool powerManagement = data.value("PowerManagement", 0);
630 bool oobSecondaryLan = data.value("OOBSecondaryLan", 0);
631 bool serialTMode = data.value("SerialTMODE", 0);
632 bool inBandSystemInterfaceChannel =
633 data.value("InBandSystemInterfaceChannel", 0);
634 payload.pack(reserved8, powerManagement, reserved7,
635 inBandSystemInterfaceChannel, serialTMode,
636 oobSecondaryLan, reserved5);
637 break;
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600638 }
Vernon Maueryf038dc02023-07-27 14:06:11 -0700639 // Mandatory Platform Attributes
640 case DCMICapParameters::MandatoryPlatAttributes:
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600641 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700642 bool selAutoRollOver = data.value("SELAutoRollOver", 0);
643 bool flushEntireSELUponRollOver =
644 data.value("FlushEntireSELUponRollOver", 0);
645 bool recordLevelSELFlushUponRollOver =
646 data.value("RecordLevelSELFlushUponRollOver", 0);
647 uint12_t numberOfSELEntries = data.value("NumberOfSELEntries",
648 0xcac);
649 uint8_t tempMonitoringSamplingFreq =
650 data.value("TempMonitoringSamplingFreq", 0);
651 payload.pack(numberOfSELEntries, reserved1,
652 recordLevelSELFlushUponRollOver,
653 flushEntireSELUponRollOver, selAutoRollOver,
654 reserved16, tempMonitoringSamplingFreq);
655 break;
656 }
657 // Optional Platform Attributes
658 case DCMICapParameters::OptionalPlatAttributes:
659 {
660 uint7_t powerMgmtDeviceSlaveAddress =
661 data.value("PowerMgmtDeviceSlaveAddress", 0);
662 uint4_t bmcChannelNumber = data.value("BMCChannelNumber", 0);
663 uint4_t deviceRivision = data.value("DeviceRivision", 0);
664 payload.pack(powerMgmtDeviceSlaveAddress, reserved1, deviceRivision,
665 bmcChannelNumber);
666 break;
667 }
668 // Manageability Access Attributes
669 case DCMICapParameters::ManageabilityAccessAttributes:
670 {
671 uint8_t mandatoryPrimaryLanOOBSupport =
672 data.value("MandatoryPrimaryLanOOBSupport", 0xff);
673 uint8_t optionalSecondaryLanOOBSupport =
674 data.value("OptionalSecondaryLanOOBSupport", 0xff);
675 uint8_t optionalSerialOOBMTMODECapability =
676 data.value("OptionalSerialOOBMTMODECapability", 0xff);
677 payload.pack(mandatoryPrimaryLanOOBSupport,
678 optionalSecondaryLanOOBSupport,
679 optionalSerialOOBMTMODECapability);
680 break;
681 }
682 default:
683 {
684 log<level::ERR>("Invalid input parameter");
685 return ipmi::responseInvalidFieldRequest();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600686 }
687 }
688
Vernon Maueryf038dc02023-07-27 14:06:11 -0700689 return ipmi::responseSuccess(payload);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600690}
691
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600692namespace dcmi
693{
694namespace temp_readings
695{
696
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700697std::tuple<bool, bool, uint8_t> readTemp(ipmi::Context::ptr& ctx,
698 const std::string& dbusService,
699 const std::string& dbusPath)
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600700{
701 // Read the temperature value from d-bus object. Need some conversion.
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700702 // As per the interface xyz.openbmc_project.Sensor.Value, the
703 // temperature is an double and in degrees C. It needs to be scaled by
704 // using the formula Value * 10^Scale. The ipmi spec has the temperature
705 // as a uint8_t, with a separate single bit for the sign.
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600706
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700707 ipmi::PropertyMap result{};
708 boost::system::error_code ec = ipmi::getAllDbusProperties(
709 ctx, dbusService, dbusPath, "xyz.openbmc_project.Sensor.Value", result);
710 if (ec.value())
711 {
712 return std::make_tuple(false, false, 0);
713 }
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500714 auto temperature = std::visit(ipmi::VariantToDoubleVisitor(),
715 result.at("Value"));
James Feist9cc0ea52018-10-09 10:53:11 -0700716 double absTemp = std::abs(temperature);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600717
James Feist9cc0ea52018-10-09 10:53:11 -0700718 auto findFactor = result.find("Scale");
719 double factor = 0.0;
720 if (findFactor != result.end())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600721 {
Vernon Maueryf442e112019-04-09 11:44:36 -0700722 factor = std::visit(ipmi::VariantToDoubleVisitor(), findFactor->second);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600723 }
James Feist9cc0ea52018-10-09 10:53:11 -0700724 double scale = std::pow(10, factor);
725
726 auto tempDegrees = absTemp * scale;
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700727 // Max absolute temp as per ipmi spec is 127.
728 constexpr auto maxTemp = 127;
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600729 if (tempDegrees > maxTemp)
730 {
731 tempDegrees = maxTemp;
732 }
733
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700734 return std::make_tuple(true, (temperature < 0),
735 static_cast<uint8_t>(tempDegrees));
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600736}
737
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700738std::tuple<std::vector<std::tuple<uint7_t, bool, uint8_t>>, uint8_t>
739 read(ipmi::Context::ptr& ctx, const std::string& type, uint8_t instance,
740 size_t count)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600741{
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700742 std::vector<std::tuple<uint7_t, bool, uint8_t>> response{};
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600743
Kirill Pakhomova2573622018-11-02 19:00:18 +0300744 auto data = parseJSONConfig(gDCMISensorsConfig);
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700745 static const std::vector<nlohmann::json> empty{};
746 std::vector<nlohmann::json> readings = data.value(type, empty);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600747 for (const auto& j : readings)
748 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700749 // Max of 8 response data sets
750 if (response.size() == count)
751 {
752 break;
753 }
754
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600755 uint8_t instanceNum = j.value("instance", 0);
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700756 // Not in the instance range we're interested in
757 if (instanceNum < instance)
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600758 {
759 continue;
760 }
761
762 std::string path = j.value("dbus", "");
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700763 std::string service{};
764 boost::system::error_code ec = ipmi::getService(
765 ctx, "xyz.openbmc_project.Sensor.Value", path, service);
766 if (ec.value())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600767 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700768 // not found on dbus
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600769 continue;
770 }
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700771
772 const auto& [ok, sign, temp] = readTemp(ctx, service, path);
773 if (ok)
774 {
775 response.emplace_back(uint7_t{temp}, sign, instanceNum);
776 }
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600777 }
778
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700779 auto totalInstances =
780 static_cast<uint8_t>(std::min(readings.size(), maxInstances));
781 return std::make_tuple(response, totalInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600782}
783
Patrick Venture0b02be92018-08-31 11:55:55 -0700784} // namespace temp_readings
785} // namespace dcmi
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600786
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700787ipmi::RspType<uint8_t, // total instances for entity id
788 uint8_t, // number of instances in this reply
789 std::vector< // zero or more of the following two bytes
790 std::tuple<uint7_t, // temperature value
791 bool, // sign bit
792 uint8_t // entity instance
793 >>>
794 getTempReadings(ipmi::Context::ptr& ctx, uint8_t sensorType,
795 uint8_t entityId, uint8_t entityInstance,
796 uint8_t instanceStart)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600797{
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700798 auto it = dcmi::entityIdToName.find(entityId);
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600799 if (it == dcmi::entityIdToName.end())
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600800 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700801 log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
802 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600803 }
804
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700805 if (sensorType != dcmi::temperatureSensorType)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600806 {
807 log<level::ERR>("Invalid sensor type",
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700808 entry("SENSOR_TYPE=%d", sensorType));
809 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600810 }
811
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700812 uint8_t requestedRecords = (entityInstance == 0) ? dcmi::maxRecords : 1;
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600813
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700814 // Read requested instances
815 const auto& [temps, totalInstances] = dcmi::temp_readings::read(
816 ctx, it->second, instanceStart, requestedRecords);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600817
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700818 auto numInstances = static_cast<uint8_t>(temps.size());
819
820 return ipmi::responseSuccess(totalInstances, numInstances, temps);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600821}
822
Willy Tu11d68892022-01-20 10:37:34 -0800823ipmi_ret_t setDCMIConfParams(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
824 ipmi_response_t, ipmi_data_len_t data_len,
825 ipmi_context_t)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600826{
Patrick Venture0b02be92018-08-31 11:55:55 -0700827 auto requestData =
828 reinterpret_cast<const dcmi::SetConfParamsRequest*>(request);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600829
William A. Kennington III5d06cc62019-04-25 02:10:55 -0700830 if (*data_len < DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE ||
Patrick Venture0b02be92018-08-31 11:55:55 -0700831 *data_len > DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600832 {
William A. Kennington III5d06cc62019-04-25 02:10:55 -0700833 log<level::ERR>("Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600834 entry("PACKET SIZE=%d", *data_len));
William A. Kennington III5d06cc62019-04-25 02:10:55 -0700835 *data_len = 0;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600836 return IPMI_CC_INVALID_FIELD_REQUEST;
837 }
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600838 *data_len = 0;
839
840 try
841 {
842 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -0700843 switch (
844 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600845 {
846 case dcmi::DCMIConfigParameters::ActivateDHCP:
847
848 if ((requestData->data[0] & DCMI_ACTIVATE_DHCP_MASK) &&
Thang Tran55cbf552023-01-31 14:43:02 +0700849 (dcmi::getDHCPEnabled() !=
850 EthernetInterface::DHCPConf::none))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600851 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700852 // When these conditions are met we have to trigger DHCP
853 // protocol restart using the latest parameter settings, but
854 // as per n/w manager design, each time when we update n/w
855 // parameters, n/w service is restarted. So we no need to
856 // take any action in this case.
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600857 }
858 break;
859
860 case dcmi::DCMIConfigParameters::DiscoveryConfig:
861
862 if (requestData->data[0] & DCMI_OPTION_12_MASK)
863 {
864 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, true);
865 }
866 else
867 {
868 dcmi::setDHCPOption(DHCP_OPT12_ENABLED, false);
869 }
870
871 // Systemd-networkd doesn't support Random Back off
872 if (requestData->data[0] & DCMI_RAND_BACK_OFF_MASK)
873 {
874 return IPMI_CC_INVALID;
875 }
876 break;
877 // Systemd-networkd doesn't allow to configure DHCP timigs
878 case dcmi::DCMIConfigParameters::DHCPTiming1:
879 case dcmi::DCMIConfigParameters::DHCPTiming2:
880 case dcmi::DCMIConfigParameters::DHCPTiming3:
881 default:
882 return IPMI_CC_INVALID;
883 }
884 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500885 catch (const std::exception& e)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600886 {
887 log<level::ERR>(e.what());
888 return IPMI_CC_UNSPECIFIED_ERROR;
889 }
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600890 return IPMI_CC_OK;
891}
892
Willy Tu11d68892022-01-20 10:37:34 -0800893ipmi_ret_t getDCMIConfParams(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
894 ipmi_response_t response, ipmi_data_len_t data_len,
895 ipmi_context_t)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600896{
Patrick Venture0b02be92018-08-31 11:55:55 -0700897 auto requestData =
898 reinterpret_cast<const dcmi::GetConfParamsRequest*>(request);
899 auto responseData =
900 reinterpret_cast<dcmi::GetConfParamsResponse*>(response);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600901
902 responseData->data[0] = 0x00;
903
William A. Kennington III5d06cc62019-04-25 02:10:55 -0700904 if (*data_len != sizeof(dcmi::GetConfParamsRequest))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600905 {
William A. Kennington III5d06cc62019-04-25 02:10:55 -0700906 log<level::ERR>("Invalid Requested Packet size",
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600907 entry("PACKET SIZE=%d", *data_len));
908 return IPMI_CC_INVALID_FIELD_REQUEST;
909 }
910
911 *data_len = 0;
912
913 try
914 {
915 // Take action based on the Parameter Selector
Patrick Venture0b02be92018-08-31 11:55:55 -0700916 switch (
917 static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600918 {
919 case dcmi::DCMIConfigParameters::ActivateDHCP:
920 responseData->data[0] = DCMI_ACTIVATE_DHCP_REPLY;
921 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
922 break;
923 case dcmi::DCMIConfigParameters::DiscoveryConfig:
924 if (dcmi::getDHCPOption(DHCP_OPT12_ENABLED))
925 {
926 responseData->data[0] |= DCMI_OPTION_12_MASK;
927 }
928 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
929 break;
930 // Get below values from Systemd-networkd source code
931 case dcmi::DCMIConfigParameters::DHCPTiming1:
932 responseData->data[0] = DHCP_TIMING1;
933 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1;
934 break;
935 case dcmi::DCMIConfigParameters::DHCPTiming2:
936 responseData->data[0] = DHCP_TIMING2_LOWER;
937 responseData->data[1] = DHCP_TIMING2_UPPER;
938 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
939 break;
940 case dcmi::DCMIConfigParameters::DHCPTiming3:
941 responseData->data[0] = DHCP_TIMING3_LOWER;
942 responseData->data[1] = DHCP_TIMING3_UPPER;
943 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2;
944 break;
945 default:
946 *data_len = 0;
947 return IPMI_CC_INVALID;
948 }
949 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500950 catch (const std::exception& e)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600951 {
952 log<level::ERR>(e.what());
953 return IPMI_CC_UNSPECIFIED_ERROR;
954 }
955
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600956 responseData->major = DCMI_SPEC_MAJOR_VERSION;
957 responseData->minor = DCMI_SPEC_MINOR_VERSION;
958 responseData->paramRevision = DCMI_CONFIG_PARAMETER_REVISION;
959
960 return IPMI_CC_OK;
961}
962
Vernon Mauery056fab12023-07-27 14:25:24 -0700963static std::optional<uint16_t> readPower(ipmi::Context::ptr& ctx)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -0600964{
Vernon Mauery056fab12023-07-27 14:25:24 -0700965 std::ifstream sensorFile(POWER_READING_SENSOR);
966 std::string objectPath;
967 if (!sensorFile.is_open())
968 {
969 log<level::ERR>("Power reading configuration file not found",
970 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
971 return std::nullopt;
972 }
973
974 auto data = nlohmann::json::parse(sensorFile, nullptr, false);
975 if (data.is_discarded())
976 {
977 log<level::ERR>("Error in parsing configuration file",
978 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
979 return std::nullopt;
980 }
981
982 objectPath = data.value("path", "");
983 if (objectPath.empty())
984 {
985 log<level::ERR>("Power sensor D-Bus object path is empty",
986 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
987 return std::nullopt;
988 }
989
990 // Return default value if failed to read from D-Bus object
991 std::string service{};
992 boost::system::error_code ec = ipmi::getService(ctx, dcmi::sensorValueIntf,
993 objectPath, service);
994 if (ec.value())
995 {
996 log<level::ERR>("Failed to fetch service for D-Bus object",
997 entry("OBJECT_PATH=%s", objectPath.c_str()),
998 entry("INTERFACE=%s", dcmi::sensorValueIntf));
999 return std::nullopt;
1000 }
1001
1002 // Read the sensor value and scale properties
1003 double value{};
1004 ec = ipmi::getDbusProperty(ctx, service, objectPath, dcmi::sensorValueIntf,
1005 dcmi::sensorValueProp, value);
1006 if (ec.value())
1007 {
1008 log<level::ERR>("Failure to read power value from D-Bus object",
1009 entry("OBJECT_PATH=%s", objectPath.c_str()),
1010 entry("INTERFACE=%s", dcmi::sensorValueIntf));
1011 return std::nullopt;
1012 }
1013 auto power = static_cast<uint16_t>(value);
1014 return power;
1015}
1016
1017ipmi::RspType<uint16_t, // current power
1018 uint16_t, // minimum power
1019 uint16_t, // maximum power
1020 uint16_t, // average power
1021 uint32_t, // timestamp
1022 uint32_t, // sample period ms
1023 uint6_t, // reserved
1024 bool, // power measurement active
1025 bool // reserved
1026 >
1027 getPowerReading(ipmi::Context::ptr& ctx, uint8_t mode, uint8_t attributes,
1028 uint8_t reserved)
1029{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001030 if (!dcmi::isDCMIPowerMgmtSupported())
1031 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001032 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Mauery056fab12023-07-27 14:25:24 -07001033 return ipmi::responseInvalidCommand();
1034 }
1035 if (reserved)
1036 {
1037 return ipmi::responseInvalidFieldRequest();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001038 }
1039
Vernon Mauery056fab12023-07-27 14:25:24 -07001040 enum class PowerMode : uint8_t
1041 {
1042 SystemPowerStatistics = 1,
1043 EnhancedSystemPowerStatistics = 2,
1044 };
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001045
Vernon Mauery056fab12023-07-27 14:25:24 -07001046 if (static_cast<PowerMode>(mode) != PowerMode::SystemPowerStatistics)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001047 {
Vernon Mauery056fab12023-07-27 14:25:24 -07001048 return ipmi::responseInvalidFieldRequest();
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001049 }
Vernon Mauery056fab12023-07-27 14:25:24 -07001050 if (attributes)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001051 {
Vernon Mauery056fab12023-07-27 14:25:24 -07001052 return ipmi::responseInvalidFieldRequest();
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001053 }
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001054
Vernon Mauery056fab12023-07-27 14:25:24 -07001055 std::optional<uint16_t> powerResp = readPower(ctx);
1056 if (!powerResp)
1057 {
1058 return ipmi::responseUnspecifiedError();
1059 }
1060 auto& power = powerResp.value();
1061
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001062 // TODO: openbmc/openbmc#2819
Gunnar Mills8466b792018-03-23 12:18:12 -05001063 // Minimum, Maximum, Average power, TimeFrame, TimeStamp,
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001064 // PowerReadingState readings need to be populated
1065 // after Telemetry changes.
Vernon Mauery056fab12023-07-27 14:25:24 -07001066 constexpr uint32_t samplePeriod = 1;
1067 constexpr uint6_t reserved1 = 0;
1068 constexpr bool measurementActive = true;
1069 constexpr bool reserved2 = false;
1070 auto timestamp = static_cast<uint32_t>(time(nullptr));
1071 return ipmi::responseSuccess(power, power, power, power, timestamp,
1072 samplePeriod, reserved1, measurementActive,
1073 reserved2);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001074}
1075
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001076namespace dcmi
1077{
1078namespace sensor_info
1079{
1080
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001081std::tuple<std::vector<uint16_t>, uint8_t> read(const std::string& type,
1082 uint8_t instance,
1083 const nlohmann::json& config,
1084 uint8_t count)
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001085{
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001086 std::vector<uint16_t> responses{};
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001087
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001088 static const std::vector<nlohmann::json> empty{};
1089 std::vector<nlohmann::json> readings = config.value(type, empty);
1090 uint8_t totalInstances = std::min(readings.size(), maxInstances);
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001091 for (const auto& reading : readings)
1092 {
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001093 // limit to requested count
1094 if (responses.size() == count)
1095 {
1096 break;
1097 }
1098
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001099 uint8_t instanceNum = reading.value("instance", 0);
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001100 // Not in the instance range we're interested in
1101 if (instanceNum < instance)
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001102 {
1103 continue;
1104 }
1105
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001106 uint16_t recordId = config.value("record_id", 0);
1107 responses.emplace_back(recordId);
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001108 }
1109
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001110 return std::make_tuple(responses, totalInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001111}
1112
1113} // namespace sensor_info
1114} // namespace dcmi
1115
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001116ipmi::RspType<uint8_t, // total available instances
1117 uint8_t, // number of records in this response
1118 std::vector<uint16_t> // records
1119 >
1120 getSensorInfo(uint8_t sensorType, uint8_t entityId, uint8_t entityInstance,
1121 uint8_t instanceStart)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001122{
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001123 auto it = dcmi::entityIdToName.find(entityId);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001124 if (it == dcmi::entityIdToName.end())
1125 {
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001126 log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
1127 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001128 }
1129
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001130 if (sensorType != dcmi::temperatureSensorType)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001131 {
1132 log<level::ERR>("Invalid sensor type",
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001133 entry("SENSOR_TYPE=%d", sensorType));
1134 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001135 }
1136
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001137 nlohmann::json config = dcmi::parseJSONConfig(dcmi::gDCMISensorsConfig);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001138
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001139 uint8_t requestedRecords = (entityInstance == 0) ? dcmi::maxRecords : 1;
1140 // Read requested instances
1141 const auto& [sensors, totalInstances] = dcmi::sensor_info::read(
1142 it->second, instanceStart, config, requestedRecords);
1143 uint8_t numRecords = sensors.size();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001144
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001145 return ipmi::responseSuccess(totalInstances, numRecords, sensors);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001146}
1147
Chris Austen1810bec2015-10-13 12:12:39 -05001148void register_netfn_dcmi_functions()
1149{
Tom05732372016-09-06 17:21:23 +05301150 // <Get Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001151 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1152 ipmi::dcmi::cmdGetPowerLimit, ipmi::Privilege::User,
1153 getPowerLimit);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301154
Tom Joseph46fa37d2017-07-26 18:11:55 +05301155 // <Set Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001156 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1157 ipmi::dcmi::cmdSetPowerLimit,
1158 ipmi::Privilege::Operator, setPowerLimit);
Tom Joseph46fa37d2017-07-26 18:11:55 +05301159
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301160 // <Activate/Deactivate Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001161 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1162 ipmi::dcmi::cmdActDeactivatePwrLimit,
1163 ipmi::Privilege::Operator, applyPowerLimit);
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301164
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301165 // <Get Asset Tag>
Vernon Mauerydca47202023-07-27 11:32:01 -07001166 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1167 ipmi::dcmi::cmdGetAssetTag, ipmi::Privilege::User,
1168 getAssetTag);
Tom Joseph545dd232017-07-12 20:20:49 +05301169
1170 // <Set Asset Tag>
Vernon Mauerydca47202023-07-27 11:32:01 -07001171 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1172 ipmi::dcmi::cmdSetAssetTag, ipmi::Privilege::Operator,
1173 setAssetTag);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001174
Gunnar Mills8991dd62017-10-25 17:11:29 -05001175 // <Get Management Controller Identifier String>
Vernon Maueryefb5ae52023-07-27 11:35:43 -07001176 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1177 ipmi::dcmi::cmdGetMgmtCntlrIdString,
1178 ipmi::Privilege::User, getMgmntCtrlIdStr);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001179
1180 // <Set Management Controller Identifier String>
Vernon Maueryefb5ae52023-07-27 11:35:43 -07001181 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1182 ipmi::dcmi::cmdSetMgmtCntlrIdString,
1183 ipmi::Privilege::Admin, setMgmntCtrlIdStr);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001184
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -06001185 // <Get DCMI capabilities>
Vernon Maueryf038dc02023-07-27 14:06:11 -07001186 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1187 ipmi::dcmi::cmdGetDcmiCapabilitiesInfo,
1188 ipmi::Privilege::User, getDCMICapabilities);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001189
1190 // <Get Temperature Readings>
Vernon Mauerycce9ffd2023-07-27 14:15:17 -07001191 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1192 ipmi::dcmi::cmdGetTemperatureReadings,
1193 ipmi::Privilege::User, getTempReadings);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001194
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001195 // <Get Power Reading>
Vernon Mauery056fab12023-07-27 14:25:24 -07001196 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1197 ipmi::dcmi::cmdGetPowerReading, ipmi::Privilege::User,
1198 getPowerReading);
1199
adarshgrami042e9db2022-09-15 10:34:34 +05301200// The Get sensor should get the senor details dynamically when
1201// FEATURE_DYNAMIC_SENSORS is enabled.
1202#ifndef FEATURE_DYNAMIC_SENSORS
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001203 // <Get Sensor Info>
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001204 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1205 ipmi::dcmi::cmdGetDcmiSensorInfo,
1206 ipmi::Privilege::Operator, getSensorInfo);
adarshgrami042e9db2022-09-15 10:34:34 +05301207#endif
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001208 // <Get DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001209 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CONF_PARAMS, NULL,
1210 getDCMIConfParams, PRIVILEGE_USER);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001211
1212 // <Set DCMI Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001213 ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_CONF_PARAMS, NULL,
1214 setDCMIConfParams, PRIVILEGE_ADMIN);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001215
Chris Austen1810bec2015-10-13 12:12:39 -05001216 return;
1217}
Tom05732372016-09-06 17:21:23 +05301218// 956379