blob: 07f1b63b2e89881198b80da37cdc1b5447d8d29c [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;
Willy Tu523e2d12023-09-05 11:36:48 -070022using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
Thang Tran55cbf552023-01-31 14:43:02 +070023
Tom Josephbe5eaa12017-07-12 19:54:44 +053024using InternalFailure =
Willy Tu523e2d12023-09-05 11:36:48 -070025 sdbusplus::error::xyz::openbmc_project::common::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
35using namespace phosphor::logging;
36
Tom Josephb9d86f42017-07-26 18:03:47 +053037namespace dcmi
38{
Vernon Mauerydca47202023-07-27 11:32:01 -070039constexpr auto assetTagMaxOffset = 62;
40constexpr auto assetTagMaxSize = 63;
41constexpr auto maxBytes = 16;
42constexpr size_t maxCtrlIdStrLen = 63;
Tom Josephb9d86f42017-07-26 18:03:47 +053043
Vernon Maueryf038dc02023-07-27 14:06:11 -070044constexpr uint8_t parameterRevision = 2;
45constexpr uint8_t specMajorVersion = 1;
46constexpr uint8_t specMinorVersion = 5;
Vernon Mauerycce9ffd2023-07-27 14:15:17 -070047constexpr auto sensorValueIntf = "xyz.openbmc_project.Sensor.Value";
48constexpr auto sensorValueProp = "Value";
Vernon Mauery6475b5c2023-07-27 14:52:51 -070049constexpr uint8_t configParameterRevision = 1;
50constexpr auto option12Mask = 0x01;
51constexpr auto activateDhcpReply = 0x00;
52constexpr uint8_t dhcpTiming1 = 0x04; // 4 sec
53constexpr uint16_t dhcpTiming2 = 0x78; // 120 sec
54constexpr uint16_t dhcpTiming3 = 0x40; // 60 sec
55// When DHCP Option 12 is enabled the string "SendHostName=true" will be
56// added into n/w configuration file and the parameter
57// SendHostNameEnabled will set to true.
58constexpr auto dhcpOpt12Enabled = "SendHostNameEnabled";
59
60enum class DCMIConfigParameters : uint8_t
61{
62 ActivateDHCP = 1,
63 DiscoveryConfig,
64 DHCPTiming1,
65 DHCPTiming2,
66 DHCPTiming3,
67};
Vernon Maueryf038dc02023-07-27 14:06:11 -070068
Deepak Kodihalli0b459552018-02-06 06:25:12 -060069// Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
Patrick Venture0b02be92018-08-31 11:55:55 -070070static const std::map<uint8_t, std::string> entityIdToName{
71 {0x40, "inlet"}, {0x37, "inlet"}, {0x41, "cpu"},
72 {0x03, "cpu"}, {0x42, "baseboard"}, {0x07, "baseboard"}};
Deepak Kodihalli0b459552018-02-06 06:25:12 -060073
Vernon Mauery6475b5c2023-07-27 14:52:51 -070074nlohmann::json parseJSONConfig(const std::string& configFile)
75{
76 std::ifstream jsonFile(configFile);
77 if (!jsonFile.is_open())
78 {
79 log<level::ERR>("Temperature readings JSON file not found");
80 elog<InternalFailure>();
81 }
82
83 auto data = nlohmann::json::parse(jsonFile, nullptr, false);
84 if (data.is_discarded())
85 {
86 log<level::ERR>("Temperature readings JSON parser failure");
87 elog<InternalFailure>();
88 }
89
90 return data;
91}
92
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +030093bool isDCMIPowerMgmtSupported()
94{
Vernon Maueryf4eb35d2023-07-27 11:08:49 -070095 static bool parsed = false;
96 static bool supported = false;
97 if (!parsed)
98 {
99 auto data = parseJSONConfig(gDCMICapabilitiesConfig);
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300100
Vernon Maueryf4eb35d2023-07-27 11:08:49 -0700101 supported = (gDCMIPowerMgmtSupported ==
102 data.value(gDCMIPowerMgmtCapability, 0));
103 }
104 return supported;
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300105}
106
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700107std::optional<uint32_t> getPcap(ipmi::Context::ptr& ctx)
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500108{
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700109 std::string service{};
110 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
111 pcapPath, service);
112 if (ec.value())
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500113 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700114 return std::nullopt;
George Liu3e3cc352023-07-26 15:59:31 +0800115 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700116 uint32_t pcap{};
117 ec = ipmi::getDbusProperty(ctx, service, pcapPath, pcapInterface,
118 powerCapProp, pcap);
119 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800120 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700121 log<level::ERR>("Error in getPcap prop",
122 entry("ERROR=%s", ec.message().c_str()));
Tom Josephb9d86f42017-07-26 18:03:47 +0530123 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700124 return std::nullopt;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500125 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700126 return pcap;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500127}
128
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700129std::optional<bool> getPcapEnabled(ipmi::Context::ptr& ctx)
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500130{
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700131 std::string service{};
132 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
133 pcapPath, service);
134 if (ec.value())
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500135 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700136 return std::nullopt;
George Liu3e3cc352023-07-26 15:59:31 +0800137 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700138 bool pcapEnabled{};
139 ec = ipmi::getDbusProperty(ctx, service, pcapPath, pcapInterface,
140 powerCapEnableProp, pcapEnabled);
141 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800142 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700143 log<level::ERR>("Error in getPcap prop");
Tom Josephb9d86f42017-07-26 18:03:47 +0530144 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700145 return std::nullopt;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500146 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700147 return pcapEnabled;
Andrew Geissler50c0c8f2017-07-11 16:18:51 -0500148}
Chris Austen1810bec2015-10-13 12:12:39 -0500149
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700150bool setPcap(ipmi::Context::ptr& ctx, const uint32_t powerCap)
Tom Joseph46fa37d2017-07-26 18:11:55 +0530151{
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700152 std::string service{};
153 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
154 pcapPath, service);
155 if (ec.value())
Tom Joseph46fa37d2017-07-26 18:11:55 +0530156 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700157 return false;
George Liu3e3cc352023-07-26 15:59:31 +0800158 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700159
160 ec = ipmi::setDbusProperty(ctx, service, pcapPath, pcapInterface,
161 powerCapProp, powerCap);
162 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800163 {
164 log<level::ERR>("Error in setPcap property",
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700165 entry("ERROR=%s", ec.message().c_str()));
Tom Joseph46fa37d2017-07-26 18:11:55 +0530166 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700167 return false;
Tom Joseph46fa37d2017-07-26 18:11:55 +0530168 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700169 return true;
Tom Joseph46fa37d2017-07-26 18:11:55 +0530170}
171
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700172bool setPcapEnable(ipmi::Context::ptr& ctx, bool enabled)
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530173{
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700174 std::string service{};
175 boost::system::error_code ec = ipmi::getService(ctx, pcapInterface,
176 pcapPath, service);
177 if (ec.value())
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530178 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700179 return false;
George Liu3e3cc352023-07-26 15:59:31 +0800180 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700181
182 ec = ipmi::setDbusProperty(ctx, service, pcapPath, pcapInterface,
183 powerCapEnableProp, enabled);
184 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800185 {
186 log<level::ERR>("Error in setPcapEnabled property",
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700187 entry("ERROR=%s", ec.message().c_str()));
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530188 elog<InternalFailure>();
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700189 return false;
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530190 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700191 return true;
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530192}
193
Vernon Mauerydca47202023-07-27 11:32:01 -0700194std::optional<std::string> readAssetTag(ipmi::Context::ptr& ctx)
Tom Josephbe5eaa12017-07-12 19:54:44 +0530195{
Tom Josephbe5eaa12017-07-12 19:54:44 +0530196 // Read the object tree with the inventory root to figure out the object
197 // that has implemented the Asset tag interface.
Vernon Mauerydca47202023-07-27 11:32:01 -0700198 ipmi::DbusObjectInfo objectInfo;
199 boost::system::error_code ec = getDbusObject(
200 ctx, dcmi::assetTagIntf, ipmi::sensor::inventoryRoot, "", objectInfo);
201 if (ec.value())
Tom Josephbe5eaa12017-07-12 19:54:44 +0530202 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700203 return std::nullopt;
George Liu3e3cc352023-07-26 15:59:31 +0800204 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700205
206 std::string assetTag{};
207 ec = ipmi::getDbusProperty(ctx, objectInfo.second, objectInfo.first,
208 dcmi::assetTagIntf, dcmi::assetTagProp,
209 assetTag);
210 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800211 {
212 log<level::ERR>("Error in reading asset tag",
Vernon Mauerydca47202023-07-27 11:32:01 -0700213 entry("ERROR=%s", ec.message().c_str()));
Tom Josephbe5eaa12017-07-12 19:54:44 +0530214 elog<InternalFailure>();
Vernon Mauerydca47202023-07-27 11:32:01 -0700215 return std::nullopt;
Tom Josephbe5eaa12017-07-12 19:54:44 +0530216 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700217
218 return assetTag;
Tom Josephbe5eaa12017-07-12 19:54:44 +0530219}
220
Vernon Mauerydca47202023-07-27 11:32:01 -0700221bool writeAssetTag(ipmi::Context::ptr& ctx, const std::string& assetTag)
Tom Josephbe5b9892017-07-15 00:55:23 +0530222{
Tom Josephbe5b9892017-07-15 00:55:23 +0530223 // Read the object tree with the inventory root to figure out the object
224 // that has implemented the Asset tag interface.
Vernon Mauerydca47202023-07-27 11:32:01 -0700225 ipmi::DbusObjectInfo objectInfo;
226 boost::system::error_code ec = getDbusObject(
227 ctx, dcmi::assetTagIntf, ipmi::sensor::inventoryRoot, "", objectInfo);
228 if (ec.value())
Tom Josephbe5b9892017-07-15 00:55:23 +0530229 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700230 return false;
George Liu3e3cc352023-07-26 15:59:31 +0800231 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700232
233 ec = ipmi::setDbusProperty(ctx, objectInfo.second, objectInfo.first,
234 dcmi::assetTagIntf, dcmi::assetTagProp,
235 assetTag);
236 if (ec.value())
George Liu3e3cc352023-07-26 15:59:31 +0800237 {
238 log<level::ERR>("Error in writing asset tag",
Vernon Mauerydca47202023-07-27 11:32:01 -0700239 entry("ERROR=%s", ec.message().c_str()));
Tom Josephbe5b9892017-07-15 00:55:23 +0530240 elog<InternalFailure>();
Vernon Mauerydca47202023-07-27 11:32:01 -0700241 return false;
Tom Josephbe5b9892017-07-15 00:55:23 +0530242 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700243 return true;
Tom Josephbe5b9892017-07-15 00:55:23 +0530244}
245
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700246std::optional<std::string> getHostName(ipmi::Context::ptr& ctx)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300247{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700248 std::string service{};
249 boost::system::error_code ec = ipmi::getService(ctx, networkConfigIntf,
250 networkConfigObj, service);
251 if (ec.value())
252 {
253 return std::nullopt;
254 }
255 std::string hostname{};
256 ec = ipmi::getDbusProperty(ctx, service, networkConfigObj,
257 networkConfigIntf, hostNameProp, hostname);
258 if (ec.value())
259 {
260 log<level::ERR>("Error fetching hostname");
261 elog<InternalFailure>();
262 return std::nullopt;
263 }
264 return hostname;
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300265}
266
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700267std::optional<EthernetInterface::DHCPConf>
268 getDHCPEnabled(ipmi::Context::ptr& ctx)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600269{
Johnathan Mantey74a21022018-12-13 13:17:56 -0800270 auto ethdevice = ipmi::getChannelName(ethernetDefaultChannelNum);
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700271 ipmi::DbusObjectInfo ethernetObj{};
272 boost::system::error_code ec = ipmi::getDbusObject(
273 ctx, ethernetIntf, networkRoot, ethdevice, ethernetObj);
274 if (ec.value())
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600275 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700276 return std::nullopt;
277 }
278 std::string service{};
279 ec = ipmi::getService(ctx, ethernetIntf, ethernetObj.first, service);
280 if (ec.value())
281 {
282 return std::nullopt;
283 }
284 std::string dhcpVal{};
285 ec = ipmi::getDbusProperty(ctx, service, ethernetObj.first, ethernetIntf,
286 "DHCPEnabled", dhcpVal);
287 if (ec.value())
288 {
289 return std::nullopt;
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600290 }
291
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700292 return EthernetInterface::convertDHCPConfFromString(dhcpVal);
293}
294
295std::optional<bool> getDHCPOption(ipmi::Context::ptr& ctx,
296 const std::string& prop)
297{
298 std::string service;
299 boost::system::error_code ec = ipmi::getService(ctx, dhcpIntf, dhcpObj,
300 service);
301 if (ec.value())
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600302 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700303 return std::nullopt;
304 }
305 bool value{};
306 ec = ipmi::getDbusProperty(ctx, service, dhcpObj, dhcpIntf, prop, value);
307 if (ec.value())
308 {
309 return std::nullopt;
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600310 }
311
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700312 return value;
313}
314
315bool setDHCPOption(ipmi::Context::ptr& ctx, std::string prop, bool value)
316{
317 std::string service;
318 boost::system::error_code ec = ipmi::getService(ctx, dhcpIntf, dhcpObj,
319 service);
320 if (!ec.value())
321 {
322 ec = ipmi::setDbusProperty(ctx, service, dhcpObj, dhcpIntf, prop,
323 value);
324 }
325 return (!ec.value());
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600326}
327
Tom Josephbe5eaa12017-07-12 19:54:44 +0530328} // namespace dcmi
Chris Austen1810bec2015-10-13 12:12:39 -0500329
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700330constexpr uint8_t exceptionPowerOff = 0x01;
331ipmi::RspType<uint16_t, // reserved
332 uint8_t, // exception actions
333 uint16_t, // power limit requested in watts
334 uint32_t, // correction time in milliseconds
335 uint16_t, // reserved
336 uint16_t // statistics sampling period in seconds
337 >
338 getPowerLimit(ipmi::Context::ptr ctx, uint16_t reserved)
Tom Josephb9d86f42017-07-26 18:03:47 +0530339{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300340 if (!dcmi::isDCMIPowerMgmtSupported())
341 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700342 return ipmi::responseInvalidCommand();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300343 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700344 if (reserved)
Tom Josephb9d86f42017-07-26 18:03:47 +0530345 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700346 return ipmi::responseInvalidFieldRequest();
Tom Josephb9d86f42017-07-26 18:03:47 +0530347 }
348
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700349 std::optional<uint16_t> pcapValue = dcmi::getPcap(ctx);
350 std::optional<bool> pcapEnable = dcmi::getPcapEnabled(ctx);
351 if (!pcapValue || !pcapEnable)
352 {
353 return ipmi::responseUnspecifiedError();
354 }
355
356 constexpr uint16_t reserved1{};
357 constexpr uint16_t reserved2{};
Tom Josephb9d86f42017-07-26 18:03:47 +0530358 /*
359 * Exception action if power limit is exceeded and cannot be controlled
360 * with the correction time limit is hardcoded to Hard Power Off system
361 * and log event to SEL.
362 */
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700363 constexpr uint8_t exception = exceptionPowerOff;
Tom Josephb9d86f42017-07-26 18:03:47 +0530364 /*
365 * Correction time limit and Statistics sampling period is currently not
366 * populated.
367 */
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700368 constexpr uint32_t correctionTime{};
369 constexpr uint16_t statsPeriod{};
Thang Tranfd9c3612023-09-20 11:16:59 +0700370 if (*pcapEnable == false)
Tom Josephb9d86f42017-07-26 18:03:47 +0530371 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700372 constexpr ipmi::Cc responseNoPowerLimitSet = 0x80;
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700373 return ipmi::response(responseNoPowerLimitSet, reserved1, exception,
Thang Tranfd9c3612023-09-20 11:16:59 +0700374 *pcapValue, correctionTime, reserved2,
375 statsPeriod);
Tom Josephb9d86f42017-07-26 18:03:47 +0530376 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700377 return ipmi::responseSuccess(reserved1, exception, *pcapValue,
378 correctionTime, reserved2, statsPeriod);
Tom Josephb9d86f42017-07-26 18:03:47 +0530379}
380
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700381ipmi::RspType<> setPowerLimit(ipmi::Context::ptr& ctx, uint16_t reserved1,
Thang Tranfd9c3612023-09-20 11:16:59 +0700382 uint8_t reserved2, uint8_t exceptionAction,
383 uint16_t powerLimit, uint32_t correctionTime,
384 uint16_t reserved3, uint16_t statsPeriod)
Tom Joseph46fa37d2017-07-26 18:11:55 +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();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300390 }
391
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700392 // Only process the power limit requested in watts. Return errors
393 // for other fields that are set
Thang Tranfd9c3612023-09-20 11:16:59 +0700394 if (reserved1 || reserved2 || reserved3 || correctionTime || statsPeriod ||
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700395 exceptionAction != exceptionPowerOff)
Tom Joseph46fa37d2017-07-26 18:11:55 +0530396 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700397 return ipmi::responseInvalidFieldRequest();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530398 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700399
400 if (!dcmi::setPcap(ctx, powerLimit))
Tom Joseph46fa37d2017-07-26 18:11:55 +0530401 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700402 return ipmi::responseUnspecifiedError();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530403 }
404
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700405 log<level::INFO>("Set Power Cap", entry("POWERCAP=%u", powerLimit));
Tom Joseph46fa37d2017-07-26 18:11:55 +0530406
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700407 return ipmi::responseSuccess();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530408}
409
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700410ipmi::RspType<> applyPowerLimit(ipmi::Context::ptr& ctx, bool enabled,
411 uint7_t reserved1, uint16_t reserved2)
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530412{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300413 if (!dcmi::isDCMIPowerMgmtSupported())
414 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300415 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700416 return ipmi::responseInvalidCommand();
417 }
418 if (reserved1 || reserved2)
419 {
420 return ipmi::responseInvalidFieldRequest();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300421 }
422
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700423 if (!dcmi::setPcapEnable(ctx, enabled))
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530424 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700425 return ipmi::responseUnspecifiedError();
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530426 }
427
428 log<level::INFO>("Set Power Cap Enable",
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700429 entry("POWERCAPENABLE=%u", static_cast<uint8_t>(enabled)));
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530430
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700431 return ipmi::responseSuccess();
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530432}
433
Vernon Mauerydca47202023-07-27 11:32:01 -0700434ipmi::RspType<uint8_t, // total tag length
435 std::vector<char> // tag data
436 >
437 getAssetTag(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count)
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530438{
Vernon Mauerydca47202023-07-27 11:32:01 -0700439 // Verify offset to read and number of bytes to read are not exceeding
440 // the range.
441 if ((offset > dcmi::assetTagMaxOffset) || (count > dcmi::maxBytes) ||
442 ((offset + count) > dcmi::assetTagMaxSize))
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530443 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700444 return ipmi::responseParmOutOfRange();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530445 }
446
Vernon Mauerydca47202023-07-27 11:32:01 -0700447 std::optional<std::string> assetTagResp = dcmi::readAssetTag(ctx);
448 if (!assetTagResp)
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530449 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700450 return ipmi::responseUnspecifiedError();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530451 }
452
Vernon Mauerydca47202023-07-27 11:32:01 -0700453 std::string& assetTag = assetTagResp.value();
454 // If the asset tag is longer than 63 bytes, restrict it to 63 bytes to
455 // suit Get Asset Tag command.
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530456 if (assetTag.size() > dcmi::assetTagMaxSize)
457 {
458 assetTag.resize(dcmi::assetTagMaxSize);
459 }
460
Vernon Mauerydca47202023-07-27 11:32:01 -0700461 if (offset >= assetTag.size())
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530462 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700463 return ipmi::responseParmOutOfRange();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530464 }
465
Vernon Mauerydca47202023-07-27 11:32:01 -0700466 // silently truncate reads beyond the end of assetTag
467 if ((offset + count) >= assetTag.size())
468 {
469 count = assetTag.size() - offset;
470 }
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530471
Vernon Mauerydca47202023-07-27 11:32:01 -0700472 auto totalTagSize = static_cast<uint8_t>(assetTag.size());
473 std::vector<char> data{assetTag.begin() + offset,
474 assetTag.begin() + offset + count};
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530475
Vernon Mauerydca47202023-07-27 11:32:01 -0700476 return ipmi::responseSuccess(totalTagSize, data);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530477}
478
Vernon Mauerydca47202023-07-27 11:32:01 -0700479ipmi::RspType<uint8_t // new asset tag length
480 >
481 setAssetTag(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count,
482 const std::vector<char>& data)
Tom Joseph545dd232017-07-12 20:20:49 +0530483{
Vernon Mauerydca47202023-07-27 11:32:01 -0700484 // Verify offset to read and number of bytes to read are not exceeding
485 // the range.
486 if ((offset > dcmi::assetTagMaxOffset) || (count > dcmi::maxBytes) ||
487 ((offset + count) > dcmi::assetTagMaxSize))
Tom Joseph545dd232017-07-12 20:20:49 +0530488 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700489 return ipmi::responseParmOutOfRange();
490 }
491 if (data.size() != count)
492 {
493 return ipmi::responseReqDataLenInvalid();
Tom Joseph545dd232017-07-12 20:20:49 +0530494 }
495
Vernon Mauerydca47202023-07-27 11:32:01 -0700496 std::optional<std::string> assetTagResp = dcmi::readAssetTag(ctx);
497 if (!assetTagResp)
Tom Joseph545dd232017-07-12 20:20:49 +0530498 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700499 return ipmi::responseUnspecifiedError();
Tom Joseph545dd232017-07-12 20:20:49 +0530500 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700501
502 std::string& assetTag = assetTagResp.value();
503
504 if (offset > assetTag.size())
Tom Joseph545dd232017-07-12 20:20:49 +0530505 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700506 return ipmi::responseParmOutOfRange();
Tom Joseph545dd232017-07-12 20:20:49 +0530507 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700508
509 // operation is to truncate at offset and append new data
510 assetTag.resize(offset);
511 assetTag.append(data.begin(), data.end());
512
513 if (!dcmi::writeAssetTag(ctx, assetTag))
514 {
515 return ipmi::responseUnspecifiedError();
516 }
517
518 auto totalTagSize = static_cast<uint8_t>(assetTag.size());
519 return ipmi::responseSuccess(totalTagSize);
Tom Joseph545dd232017-07-12 20:20:49 +0530520}
521
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700522ipmi::RspType<uint8_t, // length
523 std::vector<char> // data
524 >
525 getMgmntCtrlIdStr(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300526{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700527 if (count > dcmi::maxBytes || offset + count > dcmi::maxCtrlIdStrLen)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300528 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700529 return ipmi::responseParmOutOfRange();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300530 }
531
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700532 std::optional<std::string> hostnameResp = dcmi::getHostName(ctx);
533 if (!hostnameResp)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300534 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700535 return ipmi::responseUnspecifiedError();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300536 }
537
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700538 std::string& hostname = hostnameResp.value();
539 // If the id string is longer than 63 bytes, restrict it to 63 bytes to
540 // suit set management ctrl str command.
541 if (hostname.size() > dcmi::maxCtrlIdStrLen)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300542 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700543 hostname.resize(dcmi::maxCtrlIdStrLen);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300544 }
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300545
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700546 if (offset >= hostname.size())
547 {
548 return ipmi::responseParmOutOfRange();
549 }
550
551 // silently truncate reads beyond the end of hostname
552 if ((offset + count) >= hostname.size())
553 {
554 count = hostname.size() - offset;
555 }
556
557 auto nameSize = static_cast<uint8_t>(hostname.size());
558 std::vector<char> data{hostname.begin() + offset,
559 hostname.begin() + offset + count};
560
561 return ipmi::responseSuccess(nameSize, data);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300562}
563
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700564ipmi::RspType<uint8_t> setMgmntCtrlIdStr(ipmi::Context::ptr& ctx,
565 uint8_t offset, uint8_t count,
566 std::vector<char> data)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300567{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700568 if ((offset > dcmi::maxCtrlIdStrLen) || (count > dcmi::maxBytes) ||
569 ((offset + count) > dcmi::maxCtrlIdStrLen))
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300570 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700571 return ipmi::responseParmOutOfRange();
572 }
573 if (data.size() != count)
574 {
575 return ipmi::responseReqDataLenInvalid();
576 }
577 bool terminalWrite{data.back() == '\0'};
578 if (terminalWrite)
579 {
580 // remove the null termination from the data (no need with std::string)
581 data.resize(count - 1);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300582 }
583
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700584 static std::string hostname{};
585 // read in the current value if not starting at offset 0
586 if (hostname.size() == 0 && offset != 0)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300587 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700588 /* read old ctrlIdStr */
589 std::optional<std::string> hostnameResp = dcmi::getHostName(ctx);
590 if (!hostnameResp)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300591 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700592 return ipmi::responseUnspecifiedError();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300593 }
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700594 hostname = hostnameResp.value();
595 hostname.resize(offset);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300596 }
597
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700598 // operation is to truncate at offset and append new data
599 hostname.append(data.begin(), data.end());
600
601 // do the update if this is the last write
602 if (terminalWrite)
603 {
604 boost::system::error_code ec = ipmi::setDbusProperty(
605 ctx, dcmi::networkServiceName, dcmi::networkConfigObj,
606 dcmi::networkConfigIntf, dcmi::hostNameProp, hostname);
607 hostname.clear();
608 if (ec.value())
609 {
610 return ipmi::responseUnspecifiedError();
611 }
612 }
613
614 auto totalIdSize = static_cast<uint8_t>(offset + count);
615 return ipmi::responseSuccess(totalIdSize);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300616}
617
Vernon Maueryf038dc02023-07-27 14:06:11 -0700618ipmi::RspType<ipmi::message::Payload> getDCMICapabilities(uint8_t parameter)
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600619{
Kirill Pakhomova2573622018-11-02 19:00:18 +0300620 std::ifstream dcmiCapFile(dcmi::gDCMICapabilitiesConfig);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600621 if (!dcmiCapFile.is_open())
622 {
623 log<level::ERR>("DCMI Capabilities file not found");
Vernon Maueryf038dc02023-07-27 14:06:11 -0700624 return ipmi::responseUnspecifiedError();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600625 }
626
627 auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false);
628 if (data.is_discarded())
629 {
630 log<level::ERR>("DCMI Capabilities JSON parser failure");
Vernon Maueryf038dc02023-07-27 14:06:11 -0700631 return ipmi::responseUnspecifiedError();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600632 }
633
Vernon Maueryf038dc02023-07-27 14:06:11 -0700634 constexpr bool reserved1{};
635 constexpr uint5_t reserved5{};
636 constexpr uint7_t reserved7{};
637 constexpr uint8_t reserved8{};
638 constexpr uint16_t reserved16{};
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600639
Vernon Maueryf038dc02023-07-27 14:06:11 -0700640 ipmi::message::Payload payload;
641 payload.pack(dcmi::specMajorVersion, dcmi::specMinorVersion,
642 dcmi::parameterRevision);
643
644 enum class DCMICapParameters : uint8_t
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600645 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700646 SupportedDcmiCaps = 0x01, // Supported DCMI Capabilities
647 MandatoryPlatAttributes = 0x02, // Mandatory Platform Attributes
648 OptionalPlatAttributes = 0x03, // Optional Platform Attributes
649 ManageabilityAccessAttributes = 0x04, // Manageability Access Attributes
650 };
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600651
Vernon Maueryf038dc02023-07-27 14:06:11 -0700652 switch (static_cast<DCMICapParameters>(parameter))
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600653 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700654 case DCMICapParameters::SupportedDcmiCaps:
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600655 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700656 bool powerManagement = data.value("PowerManagement", 0);
657 bool oobSecondaryLan = data.value("OOBSecondaryLan", 0);
658 bool serialTMode = data.value("SerialTMODE", 0);
659 bool inBandSystemInterfaceChannel =
660 data.value("InBandSystemInterfaceChannel", 0);
661 payload.pack(reserved8, powerManagement, reserved7,
662 inBandSystemInterfaceChannel, serialTMode,
663 oobSecondaryLan, reserved5);
664 break;
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600665 }
Vernon Maueryf038dc02023-07-27 14:06:11 -0700666 // Mandatory Platform Attributes
667 case DCMICapParameters::MandatoryPlatAttributes:
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600668 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700669 bool selAutoRollOver = data.value("SELAutoRollOver", 0);
670 bool flushEntireSELUponRollOver =
671 data.value("FlushEntireSELUponRollOver", 0);
672 bool recordLevelSELFlushUponRollOver =
673 data.value("RecordLevelSELFlushUponRollOver", 0);
674 uint12_t numberOfSELEntries = data.value("NumberOfSELEntries",
675 0xcac);
676 uint8_t tempMonitoringSamplingFreq =
677 data.value("TempMonitoringSamplingFreq", 0);
678 payload.pack(numberOfSELEntries, reserved1,
679 recordLevelSELFlushUponRollOver,
680 flushEntireSELUponRollOver, selAutoRollOver,
681 reserved16, tempMonitoringSamplingFreq);
682 break;
683 }
684 // Optional Platform Attributes
685 case DCMICapParameters::OptionalPlatAttributes:
686 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800687 uint7_t powerMgmtDeviceTargetAddress =
Vernon Maueryf038dc02023-07-27 14:06:11 -0700688 data.value("PowerMgmtDeviceSlaveAddress", 0);
689 uint4_t bmcChannelNumber = data.value("BMCChannelNumber", 0);
690 uint4_t deviceRivision = data.value("DeviceRivision", 0);
Matt Simmering68d9d402023-11-09 14:22:11 -0800691 payload.pack(powerMgmtDeviceTargetAddress, reserved1,
692 deviceRivision, bmcChannelNumber);
Vernon Maueryf038dc02023-07-27 14:06:11 -0700693 break;
694 }
695 // Manageability Access Attributes
696 case DCMICapParameters::ManageabilityAccessAttributes:
697 {
698 uint8_t mandatoryPrimaryLanOOBSupport =
699 data.value("MandatoryPrimaryLanOOBSupport", 0xff);
700 uint8_t optionalSecondaryLanOOBSupport =
701 data.value("OptionalSecondaryLanOOBSupport", 0xff);
702 uint8_t optionalSerialOOBMTMODECapability =
703 data.value("OptionalSerialOOBMTMODECapability", 0xff);
704 payload.pack(mandatoryPrimaryLanOOBSupport,
705 optionalSecondaryLanOOBSupport,
706 optionalSerialOOBMTMODECapability);
707 break;
708 }
709 default:
710 {
711 log<level::ERR>("Invalid input parameter");
712 return ipmi::responseInvalidFieldRequest();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600713 }
714 }
715
Vernon Maueryf038dc02023-07-27 14:06:11 -0700716 return ipmi::responseSuccess(payload);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600717}
718
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600719namespace dcmi
720{
721namespace temp_readings
722{
723
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700724std::tuple<bool, bool, uint8_t> readTemp(ipmi::Context::ptr& ctx,
725 const std::string& dbusService,
726 const std::string& dbusPath)
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600727{
728 // Read the temperature value from d-bus object. Need some conversion.
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700729 // As per the interface xyz.openbmc_project.Sensor.Value, the
730 // temperature is an double and in degrees C. It needs to be scaled by
731 // using the formula Value * 10^Scale. The ipmi spec has the temperature
732 // as a uint8_t, with a separate single bit for the sign.
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600733
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700734 ipmi::PropertyMap result{};
735 boost::system::error_code ec = ipmi::getAllDbusProperties(
736 ctx, dbusService, dbusPath, "xyz.openbmc_project.Sensor.Value", result);
737 if (ec.value())
738 {
739 return std::make_tuple(false, false, 0);
740 }
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500741 auto temperature = std::visit(ipmi::VariantToDoubleVisitor(),
742 result.at("Value"));
James Feist9cc0ea52018-10-09 10:53:11 -0700743 double absTemp = std::abs(temperature);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600744
James Feist9cc0ea52018-10-09 10:53:11 -0700745 auto findFactor = result.find("Scale");
746 double factor = 0.0;
747 if (findFactor != result.end())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600748 {
Vernon Maueryf442e112019-04-09 11:44:36 -0700749 factor = std::visit(ipmi::VariantToDoubleVisitor(), findFactor->second);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600750 }
James Feist9cc0ea52018-10-09 10:53:11 -0700751 double scale = std::pow(10, factor);
752
753 auto tempDegrees = absTemp * scale;
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700754 // Max absolute temp as per ipmi spec is 127.
755 constexpr auto maxTemp = 127;
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600756 if (tempDegrees > maxTemp)
757 {
758 tempDegrees = maxTemp;
759 }
760
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700761 return std::make_tuple(true, (temperature < 0),
762 static_cast<uint8_t>(tempDegrees));
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600763}
764
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700765std::tuple<std::vector<std::tuple<uint7_t, bool, uint8_t>>, uint8_t>
766 read(ipmi::Context::ptr& ctx, const std::string& type, uint8_t instance,
767 size_t count)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600768{
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700769 std::vector<std::tuple<uint7_t, bool, uint8_t>> response{};
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600770
Kirill Pakhomova2573622018-11-02 19:00:18 +0300771 auto data = parseJSONConfig(gDCMISensorsConfig);
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700772 static const std::vector<nlohmann::json> empty{};
773 std::vector<nlohmann::json> readings = data.value(type, empty);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600774 for (const auto& j : readings)
775 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700776 // Max of 8 response data sets
777 if (response.size() == count)
778 {
779 break;
780 }
781
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600782 uint8_t instanceNum = j.value("instance", 0);
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700783 // Not in the instance range we're interested in
784 if (instanceNum < instance)
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600785 {
786 continue;
787 }
788
789 std::string path = j.value("dbus", "");
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700790 std::string service{};
791 boost::system::error_code ec = ipmi::getService(
792 ctx, "xyz.openbmc_project.Sensor.Value", path, service);
793 if (ec.value())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600794 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700795 // not found on dbus
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600796 continue;
797 }
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700798
799 const auto& [ok, sign, temp] = readTemp(ctx, service, path);
800 if (ok)
801 {
802 response.emplace_back(uint7_t{temp}, sign, instanceNum);
803 }
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600804 }
805
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700806 auto totalInstances =
807 static_cast<uint8_t>(std::min(readings.size(), maxInstances));
808 return std::make_tuple(response, totalInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600809}
810
Patrick Venture0b02be92018-08-31 11:55:55 -0700811} // namespace temp_readings
812} // namespace dcmi
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600813
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700814ipmi::RspType<uint8_t, // total instances for entity id
815 uint8_t, // number of instances in this reply
816 std::vector< // zero or more of the following two bytes
817 std::tuple<uint7_t, // temperature value
818 bool, // sign bit
819 uint8_t // entity instance
820 >>>
821 getTempReadings(ipmi::Context::ptr& ctx, uint8_t sensorType,
822 uint8_t entityId, uint8_t entityInstance,
823 uint8_t instanceStart)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600824{
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700825 auto it = dcmi::entityIdToName.find(entityId);
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600826 if (it == dcmi::entityIdToName.end())
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600827 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700828 log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
829 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600830 }
831
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700832 if (sensorType != dcmi::temperatureSensorType)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600833 {
834 log<level::ERR>("Invalid sensor type",
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700835 entry("SENSOR_TYPE=%d", sensorType));
836 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600837 }
838
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700839 uint8_t requestedRecords = (entityInstance == 0) ? dcmi::maxRecords : 1;
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600840
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700841 // Read requested instances
842 const auto& [temps, totalInstances] = dcmi::temp_readings::read(
843 ctx, it->second, instanceStart, requestedRecords);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600844
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700845 auto numInstances = static_cast<uint8_t>(temps.size());
846
847 return ipmi::responseSuccess(totalInstances, numInstances, temps);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600848}
849
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700850ipmi::RspType<> setDCMIConfParams(ipmi::Context::ptr& ctx, uint8_t parameter,
851 uint8_t setSelector,
852 ipmi::message::Payload& payload)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600853{
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700854 if (setSelector)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600855 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700856 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600857 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700858 // Take action based on the Parameter Selector
859 switch (static_cast<dcmi::DCMIConfigParameters>(parameter))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600860 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700861 case dcmi::DCMIConfigParameters::ActivateDHCP:
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600862 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700863 uint7_t reserved{};
864 bool activate{};
865 if (payload.unpack(activate, reserved) || !payload.fullyUnpacked())
866 {
867 return ipmi::responseReqDataLenInvalid();
868 }
869 if (reserved)
870 {
871 return ipmi::responseInvalidFieldRequest();
872 }
873 std::optional<EthernetInterface::DHCPConf> dhcpEnabled =
874 dcmi::getDHCPEnabled(ctx);
875 if (!dhcpEnabled)
876 {
877 return ipmi::responseUnspecifiedError();
878 }
879 if (activate &&
880 (dhcpEnabled.value() != EthernetInterface::DHCPConf::none))
881 {
882 // When these conditions are met we have to trigger DHCP
883 // protocol restart using the latest parameter settings,
884 // but as per n/w manager design, each time when we
885 // update n/w parameters, n/w service is restarted. So
886 // we no need to take any action in this case.
887 }
888 break;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600889 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700890 case dcmi::DCMIConfigParameters::DiscoveryConfig:
891 {
892 bool option12{};
893 uint6_t reserved1{};
894 bool randBackOff{};
895 if (payload.unpack(option12, reserved1, randBackOff) ||
896 !payload.fullyUnpacked())
897 {
898 return ipmi::responseReqDataLenInvalid();
899 }
900 // Systemd-networkd doesn't support Random Back off
901 if (reserved1 || randBackOff)
902 {
903 return ipmi::responseInvalidFieldRequest();
904 }
905 dcmi::setDHCPOption(ctx, dcmi::dhcpOpt12Enabled, option12);
906 break;
907 }
908 // Systemd-networkd doesn't allow to configure DHCP timigs
909 case dcmi::DCMIConfigParameters::DHCPTiming1:
910 case dcmi::DCMIConfigParameters::DHCPTiming2:
911 case dcmi::DCMIConfigParameters::DHCPTiming3:
912 default:
913 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600914 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700915 return ipmi::responseSuccess();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600916}
917
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700918ipmi::RspType<ipmi::message::Payload> getDCMIConfParams(ipmi::Context::ptr& ctx,
919 uint8_t parameter,
920 uint8_t setSelector)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600921{
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700922 if (setSelector)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600923 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700924 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600925 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700926 ipmi::message::Payload payload;
927 payload.pack(dcmi::specMajorVersion, dcmi::specMinorVersion,
928 dcmi::configParameterRevision);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600929
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700930 // Take action based on the Parameter Selector
931 switch (static_cast<dcmi::DCMIConfigParameters>(parameter))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600932 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700933 case dcmi::DCMIConfigParameters::ActivateDHCP:
934 payload.pack(dcmi::activateDhcpReply);
935 break;
936 case dcmi::DCMIConfigParameters::DiscoveryConfig:
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600937 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700938 uint8_t discovery{};
939 std::optional<bool> enabled =
940 dcmi::getDHCPOption(ctx, dcmi::dhcpOpt12Enabled);
941 if (!enabled.has_value())
942 {
943 return ipmi::responseUnspecifiedError();
944 }
945 if (enabled.value())
946 {
947 discovery = dcmi::option12Mask;
948 }
949 payload.pack(discovery);
950 break;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600951 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700952 // Get below values from Systemd-networkd source code
953 case dcmi::DCMIConfigParameters::DHCPTiming1:
954 payload.pack(dcmi::dhcpTiming1);
955 break;
956 case dcmi::DCMIConfigParameters::DHCPTiming2:
957 payload.pack(dcmi::dhcpTiming2);
958 break;
959 case dcmi::DCMIConfigParameters::DHCPTiming3:
960 payload.pack(dcmi::dhcpTiming3);
961 break;
962 default:
963 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600964 }
965
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700966 return ipmi::responseSuccess();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600967}
968
Vernon Mauery056fab12023-07-27 14:25:24 -0700969static std::optional<uint16_t> readPower(ipmi::Context::ptr& ctx)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -0600970{
Vernon Mauery056fab12023-07-27 14:25:24 -0700971 std::ifstream sensorFile(POWER_READING_SENSOR);
972 std::string objectPath;
973 if (!sensorFile.is_open())
974 {
975 log<level::ERR>("Power reading configuration file not found",
976 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
977 return std::nullopt;
978 }
979
980 auto data = nlohmann::json::parse(sensorFile, nullptr, false);
981 if (data.is_discarded())
982 {
983 log<level::ERR>("Error in parsing configuration file",
984 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
985 return std::nullopt;
986 }
987
988 objectPath = data.value("path", "");
989 if (objectPath.empty())
990 {
991 log<level::ERR>("Power sensor D-Bus object path is empty",
992 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
993 return std::nullopt;
994 }
995
996 // Return default value if failed to read from D-Bus object
997 std::string service{};
998 boost::system::error_code ec = ipmi::getService(ctx, dcmi::sensorValueIntf,
999 objectPath, service);
1000 if (ec.value())
1001 {
1002 log<level::ERR>("Failed to fetch service for D-Bus object",
1003 entry("OBJECT_PATH=%s", objectPath.c_str()),
1004 entry("INTERFACE=%s", dcmi::sensorValueIntf));
1005 return std::nullopt;
1006 }
1007
1008 // Read the sensor value and scale properties
1009 double value{};
1010 ec = ipmi::getDbusProperty(ctx, service, objectPath, dcmi::sensorValueIntf,
1011 dcmi::sensorValueProp, value);
1012 if (ec.value())
1013 {
1014 log<level::ERR>("Failure to read power value from D-Bus object",
1015 entry("OBJECT_PATH=%s", objectPath.c_str()),
1016 entry("INTERFACE=%s", dcmi::sensorValueIntf));
1017 return std::nullopt;
1018 }
1019 auto power = static_cast<uint16_t>(value);
1020 return power;
1021}
1022
1023ipmi::RspType<uint16_t, // current power
1024 uint16_t, // minimum power
1025 uint16_t, // maximum power
1026 uint16_t, // average power
1027 uint32_t, // timestamp
1028 uint32_t, // sample period ms
1029 uint6_t, // reserved
1030 bool, // power measurement active
1031 bool // reserved
1032 >
1033 getPowerReading(ipmi::Context::ptr& ctx, uint8_t mode, uint8_t attributes,
1034 uint8_t reserved)
1035{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001036 if (!dcmi::isDCMIPowerMgmtSupported())
1037 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001038 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Mauery056fab12023-07-27 14:25:24 -07001039 return ipmi::responseInvalidCommand();
1040 }
1041 if (reserved)
1042 {
1043 return ipmi::responseInvalidFieldRequest();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001044 }
1045
Vernon Mauery056fab12023-07-27 14:25:24 -07001046 enum class PowerMode : uint8_t
1047 {
1048 SystemPowerStatistics = 1,
1049 EnhancedSystemPowerStatistics = 2,
1050 };
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001051
Vernon Mauery056fab12023-07-27 14:25:24 -07001052 if (static_cast<PowerMode>(mode) != PowerMode::SystemPowerStatistics)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001053 {
Vernon Mauery056fab12023-07-27 14:25:24 -07001054 return ipmi::responseInvalidFieldRequest();
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001055 }
Vernon Mauery056fab12023-07-27 14:25:24 -07001056 if (attributes)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001057 {
Vernon Mauery056fab12023-07-27 14:25:24 -07001058 return ipmi::responseInvalidFieldRequest();
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001059 }
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001060
Vernon Mauery056fab12023-07-27 14:25:24 -07001061 std::optional<uint16_t> powerResp = readPower(ctx);
1062 if (!powerResp)
1063 {
1064 return ipmi::responseUnspecifiedError();
1065 }
1066 auto& power = powerResp.value();
1067
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001068 // TODO: openbmc/openbmc#2819
Gunnar Mills8466b792018-03-23 12:18:12 -05001069 // Minimum, Maximum, Average power, TimeFrame, TimeStamp,
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001070 // PowerReadingState readings need to be populated
1071 // after Telemetry changes.
Vernon Mauery056fab12023-07-27 14:25:24 -07001072 constexpr uint32_t samplePeriod = 1;
1073 constexpr uint6_t reserved1 = 0;
1074 constexpr bool measurementActive = true;
1075 constexpr bool reserved2 = false;
1076 auto timestamp = static_cast<uint32_t>(time(nullptr));
1077 return ipmi::responseSuccess(power, power, power, power, timestamp,
1078 samplePeriod, reserved1, measurementActive,
1079 reserved2);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001080}
1081
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001082namespace dcmi
1083{
1084namespace sensor_info
1085{
1086
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001087std::tuple<std::vector<uint16_t>, uint8_t> read(const std::string& type,
1088 uint8_t instance,
1089 const nlohmann::json& config,
1090 uint8_t count)
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001091{
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001092 std::vector<uint16_t> responses{};
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001093
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001094 static const std::vector<nlohmann::json> empty{};
1095 std::vector<nlohmann::json> readings = config.value(type, empty);
1096 uint8_t totalInstances = std::min(readings.size(), maxInstances);
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001097 for (const auto& reading : readings)
1098 {
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001099 // limit to requested count
1100 if (responses.size() == count)
1101 {
1102 break;
1103 }
1104
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001105 uint8_t instanceNum = reading.value("instance", 0);
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001106 // Not in the instance range we're interested in
1107 if (instanceNum < instance)
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001108 {
1109 continue;
1110 }
1111
Thang Tran5ea83fa2023-10-16 14:37:56 +07001112 uint16_t recordId = reading.value("record_id", 0);
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001113 responses.emplace_back(recordId);
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001114 }
1115
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001116 return std::make_tuple(responses, totalInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001117}
1118
1119} // namespace sensor_info
1120} // namespace dcmi
1121
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001122ipmi::RspType<uint8_t, // total available instances
1123 uint8_t, // number of records in this response
1124 std::vector<uint16_t> // records
1125 >
1126 getSensorInfo(uint8_t sensorType, uint8_t entityId, uint8_t entityInstance,
1127 uint8_t instanceStart)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001128{
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001129 auto it = dcmi::entityIdToName.find(entityId);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001130 if (it == dcmi::entityIdToName.end())
1131 {
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001132 log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
1133 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001134 }
1135
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001136 if (sensorType != dcmi::temperatureSensorType)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001137 {
1138 log<level::ERR>("Invalid sensor type",
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001139 entry("SENSOR_TYPE=%d", sensorType));
1140 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001141 }
1142
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001143 nlohmann::json config = dcmi::parseJSONConfig(dcmi::gDCMISensorsConfig);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001144
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001145 uint8_t requestedRecords = (entityInstance == 0) ? dcmi::maxRecords : 1;
1146 // Read requested instances
1147 const auto& [sensors, totalInstances] = dcmi::sensor_info::read(
1148 it->second, instanceStart, config, requestedRecords);
1149 uint8_t numRecords = sensors.size();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001150
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001151 return ipmi::responseSuccess(totalInstances, numRecords, sensors);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001152}
1153
Chris Austen1810bec2015-10-13 12:12:39 -05001154void register_netfn_dcmi_functions()
1155{
Tom05732372016-09-06 17:21:23 +05301156 // <Get Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001157 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1158 ipmi::dcmi::cmdGetPowerLimit, ipmi::Privilege::User,
1159 getPowerLimit);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301160
Tom Joseph46fa37d2017-07-26 18:11:55 +05301161 // <Set Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001162 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1163 ipmi::dcmi::cmdSetPowerLimit,
1164 ipmi::Privilege::Operator, setPowerLimit);
Tom Joseph46fa37d2017-07-26 18:11:55 +05301165
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301166 // <Activate/Deactivate Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001167 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1168 ipmi::dcmi::cmdActDeactivatePwrLimit,
1169 ipmi::Privilege::Operator, applyPowerLimit);
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301170
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301171 // <Get Asset Tag>
Vernon Mauerydca47202023-07-27 11:32:01 -07001172 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1173 ipmi::dcmi::cmdGetAssetTag, ipmi::Privilege::User,
1174 getAssetTag);
Tom Joseph545dd232017-07-12 20:20:49 +05301175
1176 // <Set Asset Tag>
Vernon Mauerydca47202023-07-27 11:32:01 -07001177 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1178 ipmi::dcmi::cmdSetAssetTag, ipmi::Privilege::Operator,
1179 setAssetTag);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001180
Gunnar Mills8991dd62017-10-25 17:11:29 -05001181 // <Get Management Controller Identifier String>
Vernon Maueryefb5ae52023-07-27 11:35:43 -07001182 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1183 ipmi::dcmi::cmdGetMgmtCntlrIdString,
1184 ipmi::Privilege::User, getMgmntCtrlIdStr);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001185
1186 // <Set Management Controller Identifier String>
Vernon Maueryefb5ae52023-07-27 11:35:43 -07001187 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1188 ipmi::dcmi::cmdSetMgmtCntlrIdString,
1189 ipmi::Privilege::Admin, setMgmntCtrlIdStr);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001190
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -06001191 // <Get DCMI capabilities>
Vernon Maueryf038dc02023-07-27 14:06:11 -07001192 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1193 ipmi::dcmi::cmdGetDcmiCapabilitiesInfo,
1194 ipmi::Privilege::User, getDCMICapabilities);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001195
1196 // <Get Temperature Readings>
Vernon Mauerycce9ffd2023-07-27 14:15:17 -07001197 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1198 ipmi::dcmi::cmdGetTemperatureReadings,
1199 ipmi::Privilege::User, getTempReadings);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001200
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001201 // <Get Power Reading>
Vernon Mauery056fab12023-07-27 14:25:24 -07001202 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1203 ipmi::dcmi::cmdGetPowerReading, ipmi::Privilege::User,
1204 getPowerReading);
1205
adarshgrami042e9db2022-09-15 10:34:34 +05301206// The Get sensor should get the senor details dynamically when
1207// FEATURE_DYNAMIC_SENSORS is enabled.
1208#ifndef FEATURE_DYNAMIC_SENSORS
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001209 // <Get Sensor Info>
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001210 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1211 ipmi::dcmi::cmdGetDcmiSensorInfo,
1212 ipmi::Privilege::Operator, getSensorInfo);
adarshgrami042e9db2022-09-15 10:34:34 +05301213#endif
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001214 // <Get DCMI Configuration Parameters>
Vernon Mauery6475b5c2023-07-27 14:52:51 -07001215 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1216 ipmi::dcmi::cmdGetDcmiConfigParameters,
1217 ipmi::Privilege::User, getDCMIConfParams);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001218
1219 // <Set DCMI Configuration Parameters>
Vernon Mauery6475b5c2023-07-27 14:52:51 -07001220 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1221 ipmi::dcmi::cmdSetDcmiConfigParameters,
1222 ipmi::Privilege::Admin, setDCMIConfParams);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001223
Chris Austen1810bec2015-10-13 12:12:39 -05001224 return;
1225}