blob: e45ea3fbfc0a7b99f23d344f9bd1e436e4852409 [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{
George Liucfd7fa82024-01-22 11:38:29 +0800298 ipmi::ObjectTree objectTree;
299 if (ipmi::getAllDbusObjects(ctx, networkRoot, dhcpIntf, objectTree))
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700300 {
301 return std::nullopt;
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600302 }
303
George Liucfd7fa82024-01-22 11:38:29 +0800304 for (const auto& [path, serviceMap] : objectTree)
305 {
306 for (const auto& [service, object] : serviceMap)
307 {
308 bool value{};
309 if (ipmi::getDbusProperty(ctx, service, path, dhcpIntf, prop,
310 value))
311 {
312 return std::nullopt;
313 }
314
315 if (value)
316 {
317 return true;
318 }
319 }
320 }
321
322 return false;
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700323}
324
325bool setDHCPOption(ipmi::Context::ptr& ctx, std::string prop, bool value)
326{
George Liucfd7fa82024-01-22 11:38:29 +0800327 ipmi::ObjectTree objectTree;
328 if (ipmi::getAllDbusObjects(ctx, networkRoot, dhcpIntf, objectTree))
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700329 {
George Liucfd7fa82024-01-22 11:38:29 +0800330 return false;
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700331 }
George Liucfd7fa82024-01-22 11:38:29 +0800332
333 for (const auto& [path, serviceMap] : objectTree)
334 {
335 for (const auto& [service, object] : serviceMap)
336 {
337 if (ipmi::setDbusProperty(ctx, service, path, dhcpIntf, prop,
338 value))
339 {
340 return false;
341 }
342 }
343 }
344
345 return true;
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600346}
347
Tom Josephbe5eaa12017-07-12 19:54:44 +0530348} // namespace dcmi
Chris Austen1810bec2015-10-13 12:12:39 -0500349
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700350constexpr uint8_t exceptionPowerOff = 0x01;
351ipmi::RspType<uint16_t, // reserved
352 uint8_t, // exception actions
353 uint16_t, // power limit requested in watts
354 uint32_t, // correction time in milliseconds
355 uint16_t, // reserved
356 uint16_t // statistics sampling period in seconds
357 >
358 getPowerLimit(ipmi::Context::ptr ctx, uint16_t reserved)
Tom Josephb9d86f42017-07-26 18:03:47 +0530359{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300360 if (!dcmi::isDCMIPowerMgmtSupported())
361 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700362 return ipmi::responseInvalidCommand();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300363 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700364 if (reserved)
Tom Josephb9d86f42017-07-26 18:03:47 +0530365 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700366 return ipmi::responseInvalidFieldRequest();
Tom Josephb9d86f42017-07-26 18:03:47 +0530367 }
368
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700369 std::optional<uint16_t> pcapValue = dcmi::getPcap(ctx);
370 std::optional<bool> pcapEnable = dcmi::getPcapEnabled(ctx);
371 if (!pcapValue || !pcapEnable)
372 {
373 return ipmi::responseUnspecifiedError();
374 }
375
376 constexpr uint16_t reserved1{};
377 constexpr uint16_t reserved2{};
Tom Josephb9d86f42017-07-26 18:03:47 +0530378 /*
379 * Exception action if power limit is exceeded and cannot be controlled
380 * with the correction time limit is hardcoded to Hard Power Off system
381 * and log event to SEL.
382 */
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700383 constexpr uint8_t exception = exceptionPowerOff;
Tom Josephb9d86f42017-07-26 18:03:47 +0530384 /*
385 * Correction time limit and Statistics sampling period is currently not
386 * populated.
387 */
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700388 constexpr uint32_t correctionTime{};
389 constexpr uint16_t statsPeriod{};
Thang Tranfd9c3612023-09-20 11:16:59 +0700390 if (*pcapEnable == false)
Tom Josephb9d86f42017-07-26 18:03:47 +0530391 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700392 constexpr ipmi::Cc responseNoPowerLimitSet = 0x80;
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700393 return ipmi::response(responseNoPowerLimitSet, reserved1, exception,
Thang Tranfd9c3612023-09-20 11:16:59 +0700394 *pcapValue, correctionTime, reserved2,
395 statsPeriod);
Tom Josephb9d86f42017-07-26 18:03:47 +0530396 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700397 return ipmi::responseSuccess(reserved1, exception, *pcapValue,
398 correctionTime, reserved2, statsPeriod);
Tom Josephb9d86f42017-07-26 18:03:47 +0530399}
400
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700401ipmi::RspType<> setPowerLimit(ipmi::Context::ptr& ctx, uint16_t reserved1,
Thang Tranfd9c3612023-09-20 11:16:59 +0700402 uint8_t reserved2, uint8_t exceptionAction,
403 uint16_t powerLimit, uint32_t correctionTime,
404 uint16_t reserved3, uint16_t statsPeriod)
Tom Joseph46fa37d2017-07-26 18:11:55 +0530405{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300406 if (!dcmi::isDCMIPowerMgmtSupported())
407 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300408 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700409 return ipmi::responseInvalidCommand();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300410 }
411
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700412 // Only process the power limit requested in watts. Return errors
413 // for other fields that are set
Thang Tranfd9c3612023-09-20 11:16:59 +0700414 if (reserved1 || reserved2 || reserved3 || correctionTime || statsPeriod ||
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700415 exceptionAction != exceptionPowerOff)
Tom Joseph46fa37d2017-07-26 18:11:55 +0530416 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700417 return ipmi::responseInvalidFieldRequest();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530418 }
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700419
420 if (!dcmi::setPcap(ctx, powerLimit))
Tom Joseph46fa37d2017-07-26 18:11:55 +0530421 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700422 return ipmi::responseUnspecifiedError();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530423 }
424
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700425 log<level::INFO>("Set Power Cap", entry("POWERCAP=%u", powerLimit));
Tom Joseph46fa37d2017-07-26 18:11:55 +0530426
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700427 return ipmi::responseSuccess();
Tom Joseph46fa37d2017-07-26 18:11:55 +0530428}
429
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700430ipmi::RspType<> applyPowerLimit(ipmi::Context::ptr& ctx, bool enabled,
431 uint7_t reserved1, uint16_t reserved2)
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530432{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300433 if (!dcmi::isDCMIPowerMgmtSupported())
434 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300435 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700436 return ipmi::responseInvalidCommand();
437 }
438 if (reserved1 || reserved2)
439 {
440 return ipmi::responseInvalidFieldRequest();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +0300441 }
442
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700443 if (!dcmi::setPcapEnable(ctx, enabled))
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530444 {
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700445 return ipmi::responseUnspecifiedError();
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530446 }
447
448 log<level::INFO>("Set Power Cap Enable",
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700449 entry("POWERCAPENABLE=%u", static_cast<uint8_t>(enabled)));
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530450
Vernon Maueryd4222fd2023-07-27 11:26:51 -0700451 return ipmi::responseSuccess();
Tom Joseph6c8d51b2017-07-26 18:18:06 +0530452}
453
Vernon Mauerydca47202023-07-27 11:32:01 -0700454ipmi::RspType<uint8_t, // total tag length
455 std::vector<char> // tag data
456 >
457 getAssetTag(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count)
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530458{
Vernon Mauerydca47202023-07-27 11:32:01 -0700459 // Verify offset to read and number of bytes to read are not exceeding
460 // the range.
461 if ((offset > dcmi::assetTagMaxOffset) || (count > dcmi::maxBytes) ||
462 ((offset + count) > dcmi::assetTagMaxSize))
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530463 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700464 return ipmi::responseParmOutOfRange();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530465 }
466
Vernon Mauerydca47202023-07-27 11:32:01 -0700467 std::optional<std::string> assetTagResp = dcmi::readAssetTag(ctx);
468 if (!assetTagResp)
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530469 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700470 return ipmi::responseUnspecifiedError();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530471 }
472
Vernon Mauerydca47202023-07-27 11:32:01 -0700473 std::string& assetTag = assetTagResp.value();
474 // If the asset tag is longer than 63 bytes, restrict it to 63 bytes to
475 // suit Get Asset Tag command.
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530476 if (assetTag.size() > dcmi::assetTagMaxSize)
477 {
478 assetTag.resize(dcmi::assetTagMaxSize);
479 }
480
Vernon Mauerydca47202023-07-27 11:32:01 -0700481 if (offset >= assetTag.size())
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530482 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700483 return ipmi::responseParmOutOfRange();
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530484 }
485
Vernon Mauerydca47202023-07-27 11:32:01 -0700486 // silently truncate reads beyond the end of assetTag
487 if ((offset + count) >= assetTag.size())
488 {
489 count = assetTag.size() - offset;
490 }
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530491
Vernon Mauerydca47202023-07-27 11:32:01 -0700492 auto totalTagSize = static_cast<uint8_t>(assetTag.size());
493 std::vector<char> data{assetTag.begin() + offset,
494 assetTag.begin() + offset + count};
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530495
Vernon Mauerydca47202023-07-27 11:32:01 -0700496 return ipmi::responseSuccess(totalTagSize, data);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +0530497}
498
Vernon Mauerydca47202023-07-27 11:32:01 -0700499ipmi::RspType<uint8_t // new asset tag length
500 >
501 setAssetTag(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count,
502 const std::vector<char>& data)
Tom Joseph545dd232017-07-12 20:20:49 +0530503{
Vernon Mauerydca47202023-07-27 11:32:01 -0700504 // Verify offset to read and number of bytes to read are not exceeding
505 // the range.
506 if ((offset > dcmi::assetTagMaxOffset) || (count > dcmi::maxBytes) ||
507 ((offset + count) > dcmi::assetTagMaxSize))
Tom Joseph545dd232017-07-12 20:20:49 +0530508 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700509 return ipmi::responseParmOutOfRange();
510 }
511 if (data.size() != count)
512 {
513 return ipmi::responseReqDataLenInvalid();
Tom Joseph545dd232017-07-12 20:20:49 +0530514 }
515
Vernon Mauerydca47202023-07-27 11:32:01 -0700516 std::optional<std::string> assetTagResp = dcmi::readAssetTag(ctx);
517 if (!assetTagResp)
Tom Joseph545dd232017-07-12 20:20:49 +0530518 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700519 return ipmi::responseUnspecifiedError();
Tom Joseph545dd232017-07-12 20:20:49 +0530520 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700521
522 std::string& assetTag = assetTagResp.value();
523
524 if (offset > assetTag.size())
Tom Joseph545dd232017-07-12 20:20:49 +0530525 {
Vernon Mauerydca47202023-07-27 11:32:01 -0700526 return ipmi::responseParmOutOfRange();
Tom Joseph545dd232017-07-12 20:20:49 +0530527 }
Vernon Mauerydca47202023-07-27 11:32:01 -0700528
529 // operation is to truncate at offset and append new data
530 assetTag.resize(offset);
531 assetTag.append(data.begin(), data.end());
532
533 if (!dcmi::writeAssetTag(ctx, assetTag))
534 {
535 return ipmi::responseUnspecifiedError();
536 }
537
538 auto totalTagSize = static_cast<uint8_t>(assetTag.size());
539 return ipmi::responseSuccess(totalTagSize);
Tom Joseph545dd232017-07-12 20:20:49 +0530540}
541
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700542ipmi::RspType<uint8_t, // length
543 std::vector<char> // data
544 >
545 getMgmntCtrlIdStr(ipmi::Context::ptr& ctx, uint8_t offset, uint8_t count)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300546{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700547 if (count > dcmi::maxBytes || offset + count > dcmi::maxCtrlIdStrLen)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300548 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700549 return ipmi::responseParmOutOfRange();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300550 }
551
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700552 std::optional<std::string> hostnameResp = dcmi::getHostName(ctx);
553 if (!hostnameResp)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300554 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700555 return ipmi::responseUnspecifiedError();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300556 }
557
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700558 std::string& hostname = hostnameResp.value();
559 // If the id string is longer than 63 bytes, restrict it to 63 bytes to
560 // suit set management ctrl str command.
561 if (hostname.size() > dcmi::maxCtrlIdStrLen)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300562 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700563 hostname.resize(dcmi::maxCtrlIdStrLen);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300564 }
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300565
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700566 if (offset >= hostname.size())
567 {
568 return ipmi::responseParmOutOfRange();
569 }
570
571 // silently truncate reads beyond the end of hostname
572 if ((offset + count) >= hostname.size())
573 {
574 count = hostname.size() - offset;
575 }
576
577 auto nameSize = static_cast<uint8_t>(hostname.size());
578 std::vector<char> data{hostname.begin() + offset,
579 hostname.begin() + offset + count};
580
581 return ipmi::responseSuccess(nameSize, data);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300582}
583
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700584ipmi::RspType<uint8_t> setMgmntCtrlIdStr(ipmi::Context::ptr& ctx,
585 uint8_t offset, uint8_t count,
586 std::vector<char> data)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300587{
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700588 if ((offset > dcmi::maxCtrlIdStrLen) || (count > dcmi::maxBytes) ||
589 ((offset + count) > dcmi::maxCtrlIdStrLen))
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300590 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700591 return ipmi::responseParmOutOfRange();
592 }
593 if (data.size() != count)
594 {
595 return ipmi::responseReqDataLenInvalid();
596 }
597 bool terminalWrite{data.back() == '\0'};
598 if (terminalWrite)
599 {
600 // remove the null termination from the data (no need with std::string)
601 data.resize(count - 1);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300602 }
603
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700604 static std::string hostname{};
605 // read in the current value if not starting at offset 0
606 if (hostname.size() == 0 && offset != 0)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300607 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700608 /* read old ctrlIdStr */
609 std::optional<std::string> hostnameResp = dcmi::getHostName(ctx);
610 if (!hostnameResp)
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300611 {
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700612 return ipmi::responseUnspecifiedError();
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300613 }
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700614 hostname = hostnameResp.value();
615 hostname.resize(offset);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300616 }
617
Vernon Maueryefb5ae52023-07-27 11:35:43 -0700618 // operation is to truncate at offset and append new data
619 hostname.append(data.begin(), data.end());
620
621 // do the update if this is the last write
622 if (terminalWrite)
623 {
624 boost::system::error_code ec = ipmi::setDbusProperty(
625 ctx, dcmi::networkServiceName, dcmi::networkConfigObj,
626 dcmi::networkConfigIntf, dcmi::hostNameProp, hostname);
627 hostname.clear();
628 if (ec.value())
629 {
630 return ipmi::responseUnspecifiedError();
631 }
632 }
633
634 auto totalIdSize = static_cast<uint8_t>(offset + count);
635 return ipmi::responseSuccess(totalIdSize);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +0300636}
637
Vernon Maueryf038dc02023-07-27 14:06:11 -0700638ipmi::RspType<ipmi::message::Payload> getDCMICapabilities(uint8_t parameter)
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600639{
Kirill Pakhomova2573622018-11-02 19:00:18 +0300640 std::ifstream dcmiCapFile(dcmi::gDCMICapabilitiesConfig);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600641 if (!dcmiCapFile.is_open())
642 {
643 log<level::ERR>("DCMI Capabilities file not found");
Vernon Maueryf038dc02023-07-27 14:06:11 -0700644 return ipmi::responseUnspecifiedError();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600645 }
646
647 auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false);
648 if (data.is_discarded())
649 {
650 log<level::ERR>("DCMI Capabilities JSON parser failure");
Vernon Maueryf038dc02023-07-27 14:06:11 -0700651 return ipmi::responseUnspecifiedError();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600652 }
653
Vernon Maueryf038dc02023-07-27 14:06:11 -0700654 constexpr bool reserved1{};
655 constexpr uint5_t reserved5{};
656 constexpr uint7_t reserved7{};
657 constexpr uint8_t reserved8{};
658 constexpr uint16_t reserved16{};
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600659
Vernon Maueryf038dc02023-07-27 14:06:11 -0700660 ipmi::message::Payload payload;
661 payload.pack(dcmi::specMajorVersion, dcmi::specMinorVersion,
662 dcmi::parameterRevision);
663
664 enum class DCMICapParameters : uint8_t
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600665 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700666 SupportedDcmiCaps = 0x01, // Supported DCMI Capabilities
667 MandatoryPlatAttributes = 0x02, // Mandatory Platform Attributes
668 OptionalPlatAttributes = 0x03, // Optional Platform Attributes
669 ManageabilityAccessAttributes = 0x04, // Manageability Access Attributes
670 };
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600671
Vernon Maueryf038dc02023-07-27 14:06:11 -0700672 switch (static_cast<DCMICapParameters>(parameter))
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600673 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700674 case DCMICapParameters::SupportedDcmiCaps:
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600675 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700676 bool powerManagement = data.value("PowerManagement", 0);
677 bool oobSecondaryLan = data.value("OOBSecondaryLan", 0);
678 bool serialTMode = data.value("SerialTMODE", 0);
679 bool inBandSystemInterfaceChannel =
680 data.value("InBandSystemInterfaceChannel", 0);
681 payload.pack(reserved8, powerManagement, reserved7,
682 inBandSystemInterfaceChannel, serialTMode,
683 oobSecondaryLan, reserved5);
684 break;
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600685 }
Vernon Maueryf038dc02023-07-27 14:06:11 -0700686 // Mandatory Platform Attributes
687 case DCMICapParameters::MandatoryPlatAttributes:
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600688 {
Vernon Maueryf038dc02023-07-27 14:06:11 -0700689 bool selAutoRollOver = data.value("SELAutoRollOver", 0);
690 bool flushEntireSELUponRollOver =
691 data.value("FlushEntireSELUponRollOver", 0);
692 bool recordLevelSELFlushUponRollOver =
693 data.value("RecordLevelSELFlushUponRollOver", 0);
694 uint12_t numberOfSELEntries = data.value("NumberOfSELEntries",
695 0xcac);
696 uint8_t tempMonitoringSamplingFreq =
697 data.value("TempMonitoringSamplingFreq", 0);
698 payload.pack(numberOfSELEntries, reserved1,
699 recordLevelSELFlushUponRollOver,
700 flushEntireSELUponRollOver, selAutoRollOver,
701 reserved16, tempMonitoringSamplingFreq);
702 break;
703 }
704 // Optional Platform Attributes
705 case DCMICapParameters::OptionalPlatAttributes:
706 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800707 uint7_t powerMgmtDeviceTargetAddress =
Vernon Maueryf038dc02023-07-27 14:06:11 -0700708 data.value("PowerMgmtDeviceSlaveAddress", 0);
709 uint4_t bmcChannelNumber = data.value("BMCChannelNumber", 0);
710 uint4_t deviceRivision = data.value("DeviceRivision", 0);
Matt Simmering68d9d402023-11-09 14:22:11 -0800711 payload.pack(powerMgmtDeviceTargetAddress, reserved1,
712 deviceRivision, bmcChannelNumber);
Vernon Maueryf038dc02023-07-27 14:06:11 -0700713 break;
714 }
715 // Manageability Access Attributes
716 case DCMICapParameters::ManageabilityAccessAttributes:
717 {
718 uint8_t mandatoryPrimaryLanOOBSupport =
719 data.value("MandatoryPrimaryLanOOBSupport", 0xff);
720 uint8_t optionalSecondaryLanOOBSupport =
721 data.value("OptionalSecondaryLanOOBSupport", 0xff);
722 uint8_t optionalSerialOOBMTMODECapability =
723 data.value("OptionalSerialOOBMTMODECapability", 0xff);
724 payload.pack(mandatoryPrimaryLanOOBSupport,
725 optionalSecondaryLanOOBSupport,
726 optionalSerialOOBMTMODECapability);
727 break;
728 }
729 default:
730 {
731 log<level::ERR>("Invalid input parameter");
732 return ipmi::responseInvalidFieldRequest();
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600733 }
734 }
735
Vernon Maueryf038dc02023-07-27 14:06:11 -0700736 return ipmi::responseSuccess(payload);
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -0600737}
738
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600739namespace dcmi
740{
741namespace temp_readings
742{
743
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700744std::tuple<bool, bool, uint8_t> readTemp(ipmi::Context::ptr& ctx,
745 const std::string& dbusService,
746 const std::string& dbusPath)
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600747{
748 // Read the temperature value from d-bus object. Need some conversion.
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700749 // As per the interface xyz.openbmc_project.Sensor.Value, the
750 // temperature is an double and in degrees C. It needs to be scaled by
751 // using the formula Value * 10^Scale. The ipmi spec has the temperature
752 // as a uint8_t, with a separate single bit for the sign.
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600753
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700754 ipmi::PropertyMap result{};
755 boost::system::error_code ec = ipmi::getAllDbusProperties(
756 ctx, dbusService, dbusPath, "xyz.openbmc_project.Sensor.Value", result);
757 if (ec.value())
758 {
759 return std::make_tuple(false, false, 0);
760 }
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500761 auto temperature = std::visit(ipmi::VariantToDoubleVisitor(),
762 result.at("Value"));
James Feist9cc0ea52018-10-09 10:53:11 -0700763 double absTemp = std::abs(temperature);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600764
James Feist9cc0ea52018-10-09 10:53:11 -0700765 auto findFactor = result.find("Scale");
766 double factor = 0.0;
767 if (findFactor != result.end())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600768 {
Vernon Maueryf442e112019-04-09 11:44:36 -0700769 factor = std::visit(ipmi::VariantToDoubleVisitor(), findFactor->second);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600770 }
James Feist9cc0ea52018-10-09 10:53:11 -0700771 double scale = std::pow(10, factor);
772
773 auto tempDegrees = absTemp * scale;
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700774 // Max absolute temp as per ipmi spec is 127.
775 constexpr auto maxTemp = 127;
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600776 if (tempDegrees > maxTemp)
777 {
778 tempDegrees = maxTemp;
779 }
780
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700781 return std::make_tuple(true, (temperature < 0),
782 static_cast<uint8_t>(tempDegrees));
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600783}
784
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700785std::tuple<std::vector<std::tuple<uint7_t, bool, uint8_t>>, uint8_t>
786 read(ipmi::Context::ptr& ctx, const std::string& type, uint8_t instance,
787 size_t count)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600788{
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700789 std::vector<std::tuple<uint7_t, bool, uint8_t>> response{};
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600790
Kirill Pakhomova2573622018-11-02 19:00:18 +0300791 auto data = parseJSONConfig(gDCMISensorsConfig);
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700792 static const std::vector<nlohmann::json> empty{};
793 std::vector<nlohmann::json> readings = data.value(type, empty);
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600794 for (const auto& j : readings)
795 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700796 // Max of 8 response data sets
797 if (response.size() == count)
798 {
799 break;
800 }
801
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600802 uint8_t instanceNum = j.value("instance", 0);
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700803 // Not in the instance range we're interested in
804 if (instanceNum < instance)
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600805 {
806 continue;
807 }
808
809 std::string path = j.value("dbus", "");
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700810 std::string service{};
811 boost::system::error_code ec = ipmi::getService(
812 ctx, "xyz.openbmc_project.Sensor.Value", path, service);
813 if (ec.value())
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600814 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700815 // not found on dbus
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600816 continue;
817 }
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700818
819 const auto& [ok, sign, temp] = readTemp(ctx, service, path);
820 if (ok)
821 {
822 response.emplace_back(uint7_t{temp}, sign, instanceNum);
823 }
Deepak Kodihallib1e8fba2018-01-24 04:57:10 -0600824 }
825
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700826 auto totalInstances =
827 static_cast<uint8_t>(std::min(readings.size(), maxInstances));
828 return std::make_tuple(response, totalInstances);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600829}
830
Patrick Venture0b02be92018-08-31 11:55:55 -0700831} // namespace temp_readings
832} // namespace dcmi
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600833
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700834ipmi::RspType<uint8_t, // total instances for entity id
835 uint8_t, // number of instances in this reply
836 std::vector< // zero or more of the following two bytes
837 std::tuple<uint7_t, // temperature value
838 bool, // sign bit
839 uint8_t // entity instance
840 >>>
841 getTempReadings(ipmi::Context::ptr& ctx, uint8_t sensorType,
842 uint8_t entityId, uint8_t entityInstance,
843 uint8_t instanceStart)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600844{
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700845 auto it = dcmi::entityIdToName.find(entityId);
Deepak Kodihalli0b459552018-02-06 06:25:12 -0600846 if (it == dcmi::entityIdToName.end())
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600847 {
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700848 log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
849 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600850 }
851
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700852 if (sensorType != dcmi::temperatureSensorType)
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600853 {
854 log<level::ERR>("Invalid sensor type",
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700855 entry("SENSOR_TYPE=%d", sensorType));
856 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600857 }
858
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700859 uint8_t requestedRecords = (entityInstance == 0) ? dcmi::maxRecords : 1;
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600860
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700861 // Read requested instances
862 const auto& [temps, totalInstances] = dcmi::temp_readings::read(
863 ctx, it->second, instanceStart, requestedRecords);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600864
Vernon Mauerycce9ffd2023-07-27 14:15:17 -0700865 auto numInstances = static_cast<uint8_t>(temps.size());
866
867 return ipmi::responseSuccess(totalInstances, numInstances, temps);
Deepak Kodihalliee717d72018-01-24 04:53:09 -0600868}
869
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700870ipmi::RspType<> setDCMIConfParams(ipmi::Context::ptr& ctx, uint8_t parameter,
871 uint8_t setSelector,
872 ipmi::message::Payload& payload)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600873{
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700874 if (setSelector)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600875 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700876 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600877 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700878 // Take action based on the Parameter Selector
879 switch (static_cast<dcmi::DCMIConfigParameters>(parameter))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600880 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700881 case dcmi::DCMIConfigParameters::ActivateDHCP:
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600882 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700883 uint7_t reserved{};
884 bool activate{};
885 if (payload.unpack(activate, reserved) || !payload.fullyUnpacked())
886 {
887 return ipmi::responseReqDataLenInvalid();
888 }
889 if (reserved)
890 {
891 return ipmi::responseInvalidFieldRequest();
892 }
893 std::optional<EthernetInterface::DHCPConf> dhcpEnabled =
894 dcmi::getDHCPEnabled(ctx);
895 if (!dhcpEnabled)
896 {
897 return ipmi::responseUnspecifiedError();
898 }
899 if (activate &&
900 (dhcpEnabled.value() != EthernetInterface::DHCPConf::none))
901 {
902 // When these conditions are met we have to trigger DHCP
903 // protocol restart using the latest parameter settings,
904 // but as per n/w manager design, each time when we
905 // update n/w parameters, n/w service is restarted. So
906 // we no need to take any action in this case.
907 }
908 break;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600909 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700910 case dcmi::DCMIConfigParameters::DiscoveryConfig:
911 {
912 bool option12{};
913 uint6_t reserved1{};
914 bool randBackOff{};
915 if (payload.unpack(option12, reserved1, randBackOff) ||
916 !payload.fullyUnpacked())
917 {
918 return ipmi::responseReqDataLenInvalid();
919 }
920 // Systemd-networkd doesn't support Random Back off
921 if (reserved1 || randBackOff)
922 {
923 return ipmi::responseInvalidFieldRequest();
924 }
925 dcmi::setDHCPOption(ctx, dcmi::dhcpOpt12Enabled, option12);
926 break;
927 }
928 // Systemd-networkd doesn't allow to configure DHCP timigs
929 case dcmi::DCMIConfigParameters::DHCPTiming1:
930 case dcmi::DCMIConfigParameters::DHCPTiming2:
931 case dcmi::DCMIConfigParameters::DHCPTiming3:
932 default:
933 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600934 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700935 return ipmi::responseSuccess();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600936}
937
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700938ipmi::RspType<ipmi::message::Payload> getDCMIConfParams(ipmi::Context::ptr& ctx,
939 uint8_t parameter,
940 uint8_t setSelector)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600941{
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700942 if (setSelector)
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600943 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700944 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600945 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700946 ipmi::message::Payload payload;
947 payload.pack(dcmi::specMajorVersion, dcmi::specMinorVersion,
948 dcmi::configParameterRevision);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600949
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700950 // Take action based on the Parameter Selector
951 switch (static_cast<dcmi::DCMIConfigParameters>(parameter))
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600952 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700953 case dcmi::DCMIConfigParameters::ActivateDHCP:
954 payload.pack(dcmi::activateDhcpReply);
955 break;
956 case dcmi::DCMIConfigParameters::DiscoveryConfig:
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600957 {
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700958 uint8_t discovery{};
959 std::optional<bool> enabled =
960 dcmi::getDHCPOption(ctx, dcmi::dhcpOpt12Enabled);
961 if (!enabled.has_value())
962 {
963 return ipmi::responseUnspecifiedError();
964 }
965 if (enabled.value())
966 {
967 discovery = dcmi::option12Mask;
968 }
969 payload.pack(discovery);
970 break;
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600971 }
Vernon Mauery6475b5c2023-07-27 14:52:51 -0700972 // Get below values from Systemd-networkd source code
973 case dcmi::DCMIConfigParameters::DHCPTiming1:
974 payload.pack(dcmi::dhcpTiming1);
975 break;
976 case dcmi::DCMIConfigParameters::DHCPTiming2:
977 payload.pack(dcmi::dhcpTiming2);
978 break;
979 case dcmi::DCMIConfigParameters::DHCPTiming3:
980 payload.pack(dcmi::dhcpTiming3);
981 break;
982 default:
983 return ipmi::responseInvalidFieldRequest();
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600984 }
985
Thang Tranaf762de2023-12-18 11:19:28 +0700986 return ipmi::responseSuccess(payload);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -0600987}
988
Vernon Mauery056fab12023-07-27 14:25:24 -0700989static std::optional<uint16_t> readPower(ipmi::Context::ptr& ctx)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -0600990{
Vernon Mauery056fab12023-07-27 14:25:24 -0700991 std::ifstream sensorFile(POWER_READING_SENSOR);
992 std::string objectPath;
993 if (!sensorFile.is_open())
994 {
995 log<level::ERR>("Power reading configuration file not found",
996 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
997 return std::nullopt;
998 }
999
1000 auto data = nlohmann::json::parse(sensorFile, nullptr, false);
1001 if (data.is_discarded())
1002 {
1003 log<level::ERR>("Error in parsing configuration file",
1004 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
1005 return std::nullopt;
1006 }
1007
1008 objectPath = data.value("path", "");
1009 if (objectPath.empty())
1010 {
1011 log<level::ERR>("Power sensor D-Bus object path is empty",
1012 entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
1013 return std::nullopt;
1014 }
1015
1016 // Return default value if failed to read from D-Bus object
1017 std::string service{};
1018 boost::system::error_code ec = ipmi::getService(ctx, dcmi::sensorValueIntf,
1019 objectPath, service);
1020 if (ec.value())
1021 {
1022 log<level::ERR>("Failed to fetch service for D-Bus object",
1023 entry("OBJECT_PATH=%s", objectPath.c_str()),
1024 entry("INTERFACE=%s", dcmi::sensorValueIntf));
1025 return std::nullopt;
1026 }
1027
1028 // Read the sensor value and scale properties
1029 double value{};
1030 ec = ipmi::getDbusProperty(ctx, service, objectPath, dcmi::sensorValueIntf,
1031 dcmi::sensorValueProp, value);
1032 if (ec.value())
1033 {
1034 log<level::ERR>("Failure to read power value from D-Bus object",
1035 entry("OBJECT_PATH=%s", objectPath.c_str()),
1036 entry("INTERFACE=%s", dcmi::sensorValueIntf));
1037 return std::nullopt;
1038 }
1039 auto power = static_cast<uint16_t>(value);
1040 return power;
1041}
1042
1043ipmi::RspType<uint16_t, // current power
1044 uint16_t, // minimum power
1045 uint16_t, // maximum power
1046 uint16_t, // average power
1047 uint32_t, // timestamp
1048 uint32_t, // sample period ms
1049 uint6_t, // reserved
1050 bool, // power measurement active
1051 bool // reserved
1052 >
1053 getPowerReading(ipmi::Context::ptr& ctx, uint8_t mode, uint8_t attributes,
1054 uint8_t reserved)
1055{
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001056 if (!dcmi::isDCMIPowerMgmtSupported())
1057 {
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001058 log<level::ERR>("DCMI Power management is unsupported!");
Vernon Mauery056fab12023-07-27 14:25:24 -07001059 return ipmi::responseInvalidCommand();
1060 }
1061 if (reserved)
1062 {
1063 return ipmi::responseInvalidFieldRequest();
Kirill Pakhomov2c2af2c2018-11-06 16:06:10 +03001064 }
1065
Vernon Mauery056fab12023-07-27 14:25:24 -07001066 enum class PowerMode : uint8_t
1067 {
1068 SystemPowerStatistics = 1,
1069 EnhancedSystemPowerStatistics = 2,
1070 };
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001071
Vernon Mauery056fab12023-07-27 14:25:24 -07001072 if (static_cast<PowerMode>(mode) != PowerMode::SystemPowerStatistics)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001073 {
Vernon Mauery056fab12023-07-27 14:25:24 -07001074 return ipmi::responseInvalidFieldRequest();
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001075 }
Vernon Mauery056fab12023-07-27 14:25:24 -07001076 if (attributes)
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001077 {
Vernon Mauery056fab12023-07-27 14:25:24 -07001078 return ipmi::responseInvalidFieldRequest();
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001079 }
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001080
Vernon Mauery056fab12023-07-27 14:25:24 -07001081 std::optional<uint16_t> powerResp = readPower(ctx);
1082 if (!powerResp)
1083 {
1084 return ipmi::responseUnspecifiedError();
1085 }
1086 auto& power = powerResp.value();
1087
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001088 // TODO: openbmc/openbmc#2819
Gunnar Mills8466b792018-03-23 12:18:12 -05001089 // Minimum, Maximum, Average power, TimeFrame, TimeStamp,
Marri Devender Rao9c966e02018-01-22 05:55:10 -06001090 // PowerReadingState readings need to be populated
1091 // after Telemetry changes.
Vernon Mauery056fab12023-07-27 14:25:24 -07001092 constexpr uint32_t samplePeriod = 1;
1093 constexpr uint6_t reserved1 = 0;
1094 constexpr bool measurementActive = true;
1095 constexpr bool reserved2 = false;
1096 auto timestamp = static_cast<uint32_t>(time(nullptr));
1097 return ipmi::responseSuccess(power, power, power, power, timestamp,
1098 samplePeriod, reserved1, measurementActive,
1099 reserved2);
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001100}
1101
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001102namespace dcmi
1103{
1104namespace sensor_info
1105{
1106
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001107std::tuple<std::vector<uint16_t>, uint8_t> read(const std::string& type,
1108 uint8_t instance,
1109 const nlohmann::json& config,
1110 uint8_t count)
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001111{
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001112 std::vector<uint16_t> responses{};
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001113
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001114 static const std::vector<nlohmann::json> empty{};
1115 std::vector<nlohmann::json> readings = config.value(type, empty);
1116 uint8_t totalInstances = std::min(readings.size(), maxInstances);
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001117 for (const auto& reading : readings)
1118 {
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001119 // limit to requested count
1120 if (responses.size() == count)
1121 {
1122 break;
1123 }
1124
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001125 uint8_t instanceNum = reading.value("instance", 0);
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001126 // Not in the instance range we're interested in
1127 if (instanceNum < instance)
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001128 {
1129 continue;
1130 }
1131
Thang Tran5ea83fa2023-10-16 14:37:56 +07001132 uint16_t recordId = reading.value("record_id", 0);
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001133 responses.emplace_back(recordId);
Deepak Kodihallidd4cff12018-02-06 06:48:29 -06001134 }
1135
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001136 return std::make_tuple(responses, totalInstances);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001137}
1138
1139} // namespace sensor_info
1140} // namespace dcmi
1141
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001142ipmi::RspType<uint8_t, // total available instances
1143 uint8_t, // number of records in this response
1144 std::vector<uint16_t> // records
1145 >
1146 getSensorInfo(uint8_t sensorType, uint8_t entityId, uint8_t entityInstance,
1147 uint8_t instanceStart)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001148{
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001149 auto it = dcmi::entityIdToName.find(entityId);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001150 if (it == dcmi::entityIdToName.end())
1151 {
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001152 log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
1153 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001154 }
1155
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001156 if (sensorType != dcmi::temperatureSensorType)
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001157 {
1158 log<level::ERR>("Invalid sensor type",
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001159 entry("SENSOR_TYPE=%d", sensorType));
1160 return ipmi::responseInvalidFieldRequest();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001161 }
1162
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001163 nlohmann::json config = dcmi::parseJSONConfig(dcmi::gDCMISensorsConfig);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001164
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001165 uint8_t requestedRecords = (entityInstance == 0) ? dcmi::maxRecords : 1;
1166 // Read requested instances
1167 const auto& [sensors, totalInstances] = dcmi::sensor_info::read(
1168 it->second, instanceStart, config, requestedRecords);
1169 uint8_t numRecords = sensors.size();
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001170
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001171 return ipmi::responseSuccess(totalInstances, numRecords, sensors);
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001172}
1173
Chris Austen1810bec2015-10-13 12:12:39 -05001174void register_netfn_dcmi_functions()
1175{
Tom05732372016-09-06 17:21:23 +05301176 // <Get Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001177 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1178 ipmi::dcmi::cmdGetPowerLimit, ipmi::Privilege::User,
1179 getPowerLimit);
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301180
Tom Joseph46fa37d2017-07-26 18:11:55 +05301181 // <Set Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001182 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1183 ipmi::dcmi::cmdSetPowerLimit,
1184 ipmi::Privilege::Operator, setPowerLimit);
Tom Joseph46fa37d2017-07-26 18:11:55 +05301185
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301186 // <Activate/Deactivate Power Limit>
Vernon Maueryd4222fd2023-07-27 11:26:51 -07001187 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1188 ipmi::dcmi::cmdActDeactivatePwrLimit,
1189 ipmi::Privilege::Operator, applyPowerLimit);
Tom Joseph6c8d51b2017-07-26 18:18:06 +05301190
Tom Joseph6f6dd4d2017-07-12 20:07:11 +05301191 // <Get Asset Tag>
Vernon Mauerydca47202023-07-27 11:32:01 -07001192 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1193 ipmi::dcmi::cmdGetAssetTag, ipmi::Privilege::User,
1194 getAssetTag);
Tom Joseph545dd232017-07-12 20:20:49 +05301195
1196 // <Set Asset Tag>
Vernon Mauerydca47202023-07-27 11:32:01 -07001197 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1198 ipmi::dcmi::cmdSetAssetTag, ipmi::Privilege::Operator,
1199 setAssetTag);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001200
Gunnar Mills8991dd62017-10-25 17:11:29 -05001201 // <Get Management Controller Identifier String>
Vernon Maueryefb5ae52023-07-27 11:35:43 -07001202 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1203 ipmi::dcmi::cmdGetMgmtCntlrIdString,
1204 ipmi::Privilege::User, getMgmntCtrlIdStr);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001205
1206 // <Set Management Controller Identifier String>
Vernon Maueryefb5ae52023-07-27 11:35:43 -07001207 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1208 ipmi::dcmi::cmdSetMgmtCntlrIdString,
1209 ipmi::Privilege::Admin, setMgmntCtrlIdStr);
Vladislav Vovchenko8f7a6f62017-08-17 00:31:14 +03001210
Dhruvaraj Subhashchandrane29be412018-01-16 05:11:56 -06001211 // <Get DCMI capabilities>
Vernon Maueryf038dc02023-07-27 14:06:11 -07001212 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1213 ipmi::dcmi::cmdGetDcmiCapabilitiesInfo,
1214 ipmi::Privilege::User, getDCMICapabilities);
Deepak Kodihalliee717d72018-01-24 04:53:09 -06001215
Marri Devender Rao66c5fda2018-01-18 10:48:37 -06001216 // <Get Power Reading>
Vernon Mauery056fab12023-07-27 14:25:24 -07001217 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1218 ipmi::dcmi::cmdGetPowerReading, ipmi::Privilege::User,
1219 getPowerReading);
1220
adarshgrami042e9db2022-09-15 10:34:34 +05301221// The Get sensor should get the senor details dynamically when
1222// FEATURE_DYNAMIC_SENSORS is enabled.
1223#ifndef FEATURE_DYNAMIC_SENSORS
Deepak Kodihalli0b459552018-02-06 06:25:12 -06001224 // <Get Sensor Info>
Vernon Mauery53d0cf12023-07-27 14:32:44 -07001225 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1226 ipmi::dcmi::cmdGetDcmiSensorInfo,
1227 ipmi::Privilege::Operator, getSensorInfo);
Thang Tran3dad8262023-08-17 15:20:56 +07001228
1229 // <Get Temperature Readings>
1230 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1231 ipmi::dcmi::cmdGetTemperatureReadings,
1232 ipmi::Privilege::User, getTempReadings);
adarshgrami042e9db2022-09-15 10:34:34 +05301233#endif
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001234 // <Get DCMI Configuration Parameters>
Vernon Mauery6475b5c2023-07-27 14:52:51 -07001235 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1236 ipmi::dcmi::cmdGetDcmiConfigParameters,
1237 ipmi::Privilege::User, getDCMIConfParams);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001238
1239 // <Set DCMI Configuration Parameters>
Vernon Mauery6475b5c2023-07-27 14:52:51 -07001240 registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
1241 ipmi::dcmi::cmdSetDcmiConfigParameters,
1242 ipmi::Privilege::Admin, setDCMIConfParams);
Nagaraju Goruganti22be97b2018-02-07 01:19:59 -06001243
Chris Austen1810bec2015-10-13 12:12:39 -05001244 return;
1245}