blob: 04035f0f2f6ecb9a3125b6e11f05fd3cb6f6e024 [file] [log] [blame]
Yuan Li60e7aaf2019-05-28 14:22:40 +08001/*
2// Copyright (c) 2019 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#include "xyz/openbmc_project/Common/error.hpp"
17
18#include <fstream>
Jason M. Billsb08f84e2019-06-10 12:59:42 -070019#include <iostream>
Yuan Li60e7aaf2019-05-28 14:22:40 +080020#include <ipmid/api.hpp>
21#include <ipmid/utils.hpp>
22#include <nlohmann/json.hpp>
23#include <phosphor-logging/elog-errors.hpp>
Jason M. Billsb08f84e2019-06-10 12:59:42 -070024#include <phosphor-logging/log.hpp>
Yuan Li60e7aaf2019-05-28 14:22:40 +080025#include <regex>
26#include <sdbusplus/timer.hpp>
Jason M. Billsb08f84e2019-06-10 12:59:42 -070027#include <stdexcept>
28#include <string_view>
29#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
Yuan Li60e7aaf2019-05-28 14:22:40 +080030
Jason M. Billsb08f84e2019-06-10 12:59:42 -070031using namespace phosphor::logging;
32
33namespace ipmi::chassis
Yuan Li60e7aaf2019-05-28 14:22:40 +080034{
Jason M. Billsb08f84e2019-06-10 12:59:42 -070035static constexpr const char* buttonIntf = "xyz.openbmc_project.Chassis.Buttons";
Yuan Li60e7aaf2019-05-28 14:22:40 +080036
Jason M. Billsb08f84e2019-06-10 12:59:42 -070037const static constexpr char* idButtonPath =
38 "/xyz/openbmc_project/chassis/buttons/id";
39static constexpr const char* powerButtonPath =
40 "/xyz/openbmc_project/chassis/buttons/power";
41static constexpr const char* resetButtonPath =
42 "/xyz/openbmc_project/chassis/buttons/reset";
43static constexpr const char* interruptButtonPath =
44 "/xyz/openbmc_project/chassis/buttons/nmi";
45
46const static constexpr char* idButtonProp = "ButtonPressed";
47
48const static constexpr char* ledService =
Yuan Li60e7aaf2019-05-28 14:22:40 +080049 "xyz.openbmc_project.LED.GroupManager";
Jason M. Billsb08f84e2019-06-10 12:59:42 -070050const static constexpr char* ledIDOnObj =
Yuan Li60e7aaf2019-05-28 14:22:40 +080051 "/xyz/openbmc_project/led/groups/enclosure_identify";
Jason M. Billsb08f84e2019-06-10 12:59:42 -070052const static constexpr char* ledIDBlinkObj =
Yuan Li60e7aaf2019-05-28 14:22:40 +080053 "/xyz/openbmc_project/led/groups/enclosure_identify_blink";
Jason M. Billsb08f84e2019-06-10 12:59:42 -070054const static constexpr char* ledInterface = "xyz.openbmc_project.Led.Group";
55const static constexpr char* ledProp = "Asserted";
Yuan Li60e7aaf2019-05-28 14:22:40 +080056
57constexpr size_t defaultIdentifyTimeOut = 15;
58
59std::unique_ptr<phosphor::Timer> identifyTimer
60 __attribute__((init_priority(101)));
61std::unique_ptr<sdbusplus::bus::match_t> matchPtr
62 __attribute__((init_priority(101)));
63
64static void registerChassisFunctions() __attribute__((constructor));
65
66static ipmi::ServiceCache LEDService(ledInterface, ledIDBlinkObj);
67
Jason M. Billsb08f84e2019-06-10 12:59:42 -070068void enclosureIdentifyLed(const char* objName, bool isIdLedOn)
Yuan Li60e7aaf2019-05-28 14:22:40 +080069{
70 auto bus = getSdBus();
71
72 try
73 {
74 std::string service = LEDService.getService(*bus);
75 setDbusProperty(*bus, service, objName, ledInterface, ledProp,
76 isIdLedOn);
77 }
Jason M. Billsb08f84e2019-06-10 12:59:42 -070078 catch (const std::exception& e)
Yuan Li60e7aaf2019-05-28 14:22:40 +080079 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -070080 log<level::ERR>("enclosureIdentifyLed: can't set property",
81 entry("ERR=%s", e.what()));
Yuan Li60e7aaf2019-05-28 14:22:40 +080082 }
83}
84
Jason M. Billsb08f84e2019-06-10 12:59:42 -070085bool getIDState(const char* objName, bool& state)
Yuan Li60e7aaf2019-05-28 14:22:40 +080086{
87 auto bus = getSdBus();
88
89 try
90 {
91 std::string service = LEDService.getService(*bus);
92 ipmi::Value enabled =
93 getDbusProperty(*bus, service, objName, ledInterface, ledProp);
94 state = std::get<bool>(enabled);
95 }
Jason M. Billsb08f84e2019-06-10 12:59:42 -070096 catch (sdbusplus::exception::SdBusError& e)
Yuan Li60e7aaf2019-05-28 14:22:40 +080097 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -070098 log<level::ERR>("Fail to get property", entry("PATH=%s", objName),
99 entry("ERROR=%s", e.what()));
Yuan Li60e7aaf2019-05-28 14:22:40 +0800100 return false;
101 }
102 return true;
103}
104
105void enclosureIdentifyLedBlinkOff()
106{
107 enclosureIdentifyLed(ledIDBlinkObj, false);
108}
109
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700110void idButtonPropChanged(sdbusplus::message::message& msg)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800111{
112 bool asserted = false;
113 bool buttonPressed = false;
114
115 std::map<std::string, ipmi::Value> props;
116 std::vector<std::string> inval;
117 std::string iface;
118 msg.read(iface, props, inval);
119
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700120 for (const auto& t : props)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800121 {
122 auto key = t.first;
123 auto value = t.second;
124
125 if (key == idButtonProp)
126 {
127 buttonPressed = std::get<bool>(value);
128 }
129 break;
130 }
131
132 if (buttonPressed)
133 {
134 if (identifyTimer->isRunning())
135 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700136 log<level::INFO>("ID timer is running");
Yuan Li60e7aaf2019-05-28 14:22:40 +0800137 }
138
139 // make sure timer is stopped
140 identifyTimer->stop();
141
142 if (!getIDState(ledIDBlinkObj, asserted))
143 {
144 return;
145 }
146
147 if (asserted)
148 {
149 // LED is blinking, turn off the LED
150 enclosureIdentifyLed(ledIDBlinkObj, false);
151 enclosureIdentifyLed(ledIDOnObj, false);
152 }
153 else
154 {
155 // toggle the IED on/off
156 if (!getIDState(ledIDOnObj, asserted))
157 {
158 return;
159 }
160 enclosureIdentifyLed(ledIDOnObj, !asserted);
161 }
162 }
163}
164
165void createIdentifyTimer()
166{
167 if (!identifyTimer)
168 {
169 identifyTimer =
170 std::make_unique<phosphor::Timer>(enclosureIdentifyLedBlinkOff);
171 }
172}
173
174ipmi::RspType<> ipmiChassisIdentify(std::optional<uint8_t> interval,
175 std::optional<uint8_t> force)
176{
177 uint8_t identifyInterval = interval.value_or(defaultIdentifyTimeOut);
178 bool forceIdentify = force.value_or(0) & 0x01;
179
180 enclosureIdentifyLed(ledIDOnObj, false);
181 identifyTimer->stop();
182
183 if (identifyInterval || forceIdentify)
184 {
185 enclosureIdentifyLed(ledIDBlinkObj, true);
186 if (forceIdentify)
187 {
188 return ipmi::responseSuccess();
189 }
190 // start the timer
191 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
192 std::chrono::seconds(identifyInterval));
193 identifyTimer->start(time);
194 }
195 else
196 {
197 enclosureIdentifyLed(ledIDBlinkObj, false);
198 }
199 return ipmi::responseSuccess();
200}
201
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700202namespace power_policy
203{
204/* helper function for Get Chassis Status Command
205 */
206std::optional<uint2_t> getPowerRestorePolicy()
207{
208 constexpr const char* powerRestorePath =
209 "/xyz/openbmc_project/control/host0/power_restore_policy";
210 constexpr const char* powerRestoreIntf =
211 "xyz.openbmc_project.Control.Power.RestorePolicy";
212 uint2_t restorePolicy = 0;
213 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
214
215 try
216 {
217 auto service =
218 ipmi::getService(*busp, powerRestoreIntf, powerRestorePath);
219
220 ipmi::Value result =
221 ipmi::getDbusProperty(*busp, service, powerRestorePath,
222 powerRestoreIntf, "PowerRestorePolicy");
223 auto powerRestore = sdbusplus::xyz::openbmc_project::Control::Power::
224 server::RestorePolicy::convertPolicyFromString(
225 std::get<std::string>(result));
226
227 using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
228 switch (powerRestore)
229 {
230 case RestorePolicy::Policy::AlwaysOff:
231 restorePolicy = 0x00;
232 break;
233 case RestorePolicy::Policy::Restore:
234 restorePolicy = 0x01;
235 break;
236 case RestorePolicy::Policy::AlwaysOn:
237 restorePolicy = 0x02;
238 break;
239 }
240 }
241 catch (const std::exception& e)
242 {
243 log<level::ERR>("Failed to fetch PowerRestorePolicy property",
244 entry("ERROR=%s", e.what()),
245 entry("PATH=%s", powerRestorePath),
246 entry("INTERFACE=%s", powerRestoreIntf));
247 return std::nullopt;
248 }
249 return std::make_optional(restorePolicy);
250}
251
252/*
253 * getPowerStatus
254 * helper function for Get Chassis Status Command
255 * return - optional value for pgood (no value on error)
256 */
257std::optional<bool> getPowerStatus()
258{
259 bool powerGood = false;
260 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
261 try
262 {
263 constexpr const char* chassisStatePath =
264 "/xyz/openbmc_project/state/chassis0";
265 constexpr const char* chassisStateIntf =
266 "xyz.openbmc_project.State.Chassis";
267 auto service =
268 ipmi::getService(*busp, chassisStateIntf, chassisStatePath);
269
270 ipmi::Value variant =
271 ipmi::getDbusProperty(*busp, service, chassisStatePath,
272 chassisStateIntf, "CurrentPowerState");
273 std::string powerState = std::get<std::string>(variant);
274 if (powerState == "xyz.openbmc_project.State.Chassis.PowerState.On")
275 {
276 powerGood = true;
277 }
278 }
279 catch (const std::exception& e)
280 {
281 log<level::ERR>("Failed to fetch power state property",
282 entry("ERROR=%s", e.what()));
283 return std::nullopt;
284 }
285 return std::make_optional(powerGood);
286}
287
288/*
289 * getACFailStatus
290 * helper function for Get Chassis Status Command
291 * return - bool value for ACFail (false on error)
292 */
293bool getACFailStatus()
294{
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700295 constexpr const char* acBootObj =
296 "/xyz/openbmc_project/control/host0/ac_boot";
297 constexpr const char* acBootIntf = "xyz.openbmc_project.Common.ACBoot";
298 std::string acFail;
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700299 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
300 try
301 {
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700302 auto service = ipmi::getService(*bus, acBootIntf, acBootObj);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700303
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700304 ipmi::Value variant = ipmi::getDbusProperty(*bus, service, acBootObj,
305 acBootIntf, "ACBoot");
306 acFail = std::get<std::string>(variant);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700307 }
308 catch (const std::exception& e)
309 {
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700310 log<level::ERR>(
311 "Failed to fetch ACBoot property", entry("ERROR=%s", e.what()),
312 entry("PATH=%s", acBootObj), entry("INTERFACE=%s", acBootIntf));
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700313 }
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700314 return acFail == "True";
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700315}
316} // namespace power_policy
317
318static std::optional<bool> getButtonEnabled(const std::string& buttonPath)
319{
320 bool buttonDisabled = false;
321 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
322 try
323 {
324 auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
325 ipmi::Value disabled = ipmi::getDbusProperty(
326 *busp, service, buttonPath, buttonIntf, "ButtonMasked");
327 buttonDisabled = std::get<bool>(disabled);
328 }
329 catch (sdbusplus::exception::SdBusError& e)
330 {
331 log<level::ERR>("Fail to get button disabled property",
332 entry("PATH=%s", buttonPath.c_str()),
333 entry("ERROR=%s", e.what()));
334 return std::nullopt;
335 }
336 return std::make_optional(buttonDisabled);
337}
338
339static bool setButtonEnabled(const std::string& buttonPath, const bool disabled)
340{
341 try
342 {
343 auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
344 ipmi::setDbusProperty(*getSdBus(), service, buttonPath, buttonIntf,
345 "ButtonMasked", disabled);
346 }
347 catch (std::exception& e)
348 {
349 log<level::ERR>("Failed to set button disabled",
350 entry("EXCEPTION=%s, REQUEST=%x", e.what(), disabled));
351 return -1;
352 }
353
354 return 0;
355}
356
357//----------------------------------------------------------------------
358// Get Chassis Status commands
359//----------------------------------------------------------------------
360ipmi::RspType<bool, // Power is on
361 bool, // Power overload
362 bool, // Interlock
363 bool, // power fault
364 bool, // power control fault
365 uint2_t, // power restore policy
366 bool, // reserved
367
368 bool, // AC failed
369 bool, // last power down caused by a Power overload
370 bool, // last power down caused by a power interlock
371 bool, // last power down caused by power fault
372 bool, // last ‘Power is on’ state was entered via IPMI command
373 uint3_t, // reserved
374
375 bool, // Chassis intrusion active
376 bool, // Front Panel Lockout active
377 bool, // Drive Fault
378 bool, // Cooling/fan fault detected
379 uint2_t, // Chassis Identify State
380 bool, // Chassis Identify command and state info supported
381 bool, // reserved
382
383 bool, // Power off button disabled
384 bool, // Reset button disabled
385 bool, // Diagnostic Interrupt button disabled
386 bool, // Standby (sleep) button disabled
387 bool, // Power off button disable allowed
388 bool, // Reset button disable allowed
389 bool, // Diagnostic Interrupt button disable allowed
390 bool // Standby (sleep) button disable allowed
391 >
392 ipmiGetChassisStatus()
393{
394 std::optional<uint2_t> restorePolicy =
395 power_policy::getPowerRestorePolicy();
396 std::optional<bool> powerGood = power_policy::getPowerStatus();
397 if (!restorePolicy || !powerGood)
398 {
399 return ipmi::responseUnspecifiedError();
400 }
401
402 // Front Panel Button Capabilities and disable/enable status(Optional)
403 std::optional<bool> powerButtonReading = getButtonEnabled(powerButtonPath);
404 // allow disable if the interface is present
405 bool powerButtonDisableAllow = static_cast<bool>(powerButtonReading);
406 // default return the button is enabled (not disabled)
407 bool powerButtonDisabled = false;
408 if (powerButtonDisableAllow)
409 {
410 // return the real value of the button status, if present
411 powerButtonDisabled = *powerButtonReading;
412 }
413
414 std::optional<bool> resetButtonReading = getButtonEnabled(resetButtonPath);
415 // allow disable if the interface is present
416 bool resetButtonDisableAllow = static_cast<bool>(resetButtonReading);
417 // default return the button is enabled (not disabled)
418 bool resetButtonDisabled = false;
419 if (resetButtonDisableAllow)
420 {
421 // return the real value of the button status, if present
422 resetButtonDisabled = *resetButtonReading;
423 }
424
425 std::optional<bool> interruptButtonReading =
426 getButtonEnabled(interruptButtonPath);
427 // allow disable if the interface is present
428 bool interruptButtonDisableAllow =
429 static_cast<bool>(interruptButtonReading);
430 // default return the button is enabled (not disabled)
431 bool interruptButtonDisabled = false;
432 if (interruptButtonDisableAllow)
433 {
434 // return the real value of the button status, if present
435 interruptButtonDisabled = *interruptButtonReading;
436 }
437
438 bool powerDownAcFailed = power_policy::getACFailStatus();
439
440 // This response has a lot of hard-coded, unsupported fields
441 // They are set to false or 0
442 constexpr bool powerOverload = false;
443 constexpr bool chassisInterlock = false;
444 constexpr bool powerFault = false;
445 constexpr bool powerControlFault = false;
446 constexpr bool powerDownOverload = false;
447 constexpr bool powerDownInterlock = false;
448 constexpr bool powerDownPowerFault = false;
449 constexpr bool powerStatusIPMI = false;
450 constexpr bool chassisIntrusionActive = false;
451 constexpr bool frontPanelLockoutActive = false;
452 constexpr bool driveFault = false;
453 constexpr bool coolingFanFault = false;
454 // chassisIdentifySupport set because this command is implemented
455 constexpr bool chassisIdentifySupport = true;
456 uint2_t chassisIdentifyState = 0;
457 constexpr bool sleepButtonDisabled = false;
458 constexpr bool sleepButtonDisableAllow = false;
459
460 return ipmi::responseSuccess(
461 *powerGood, powerOverload, chassisInterlock, powerFault,
462 powerControlFault, *restorePolicy,
463 false, // reserved
464
465 powerDownAcFailed, powerDownOverload, powerDownInterlock,
466 powerDownPowerFault, powerStatusIPMI,
467 uint3_t(0), // reserved
468
469 chassisIntrusionActive, frontPanelLockoutActive, driveFault,
470 coolingFanFault, chassisIdentifyState, chassisIdentifySupport,
471 false, // reserved
472
473 powerButtonDisabled, resetButtonDisabled, interruptButtonDisabled,
474 sleepButtonDisabled, powerButtonDisableAllow, resetButtonDisableAllow,
475 interruptButtonDisableAllow, sleepButtonDisableAllow);
476}
477
Jason M. Bills3efc6452019-06-20 15:51:47 -0700478static uint4_t getRestartCause(const std::string& cause)
479{
480 uint4_t restartCauseValue = 0;
481 if (cause == "xyz.openbmc_project.State.Host.RestartCause.Unknown")
482 {
483 restartCauseValue = 0x0;
484 }
485 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand")
486 {
487 restartCauseValue = 0x1;
488 }
489 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.ResetButton")
490 {
491 restartCauseValue = 0x2;
492 }
493 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PowerButton")
494 {
495 restartCauseValue = 0x3;
496 }
497 else if (cause ==
498 "xyz.openbmc_project.State.Host.RestartCause.WatchdogTimer")
499 {
500 restartCauseValue = 0x4;
501 }
502 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.OEM")
503 {
504 restartCauseValue = 0x5;
505 }
506 else if (cause ==
507 "xyz.openbmc_project.State.Host.RestartCause.PowerPolicyAlwaysOn")
508 {
509 restartCauseValue = 0x6;
510 }
511 else if (cause == "xyz.openbmc_project.State.Host.RestartCause."
512 "PowerPolicyPreviousState")
513 {
514 restartCauseValue = 0x7;
515 }
516 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PEFReset")
517 {
518 restartCauseValue = 0x8;
519 }
520 else if (cause ==
521 "xyz.openbmc_project.State.Host.RestartCause.PEFPowerCycle")
522 {
523 restartCauseValue = 0x9;
524 }
525 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.SoftReset")
526 {
527 restartCauseValue = 0xa;
528 }
529 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.RTCWakeup")
530 {
531 restartCauseValue = 0xb;
532 }
533 return restartCauseValue;
534}
535
536ipmi::RspType<uint4_t, // Restart Cause
537 uint4_t, // reserved
538 uint8_t // channel number (not supported)
539 >
540 ipmiGetSystemRestartCause()
541{
542 constexpr const char* restartCausePath =
543 "/xyz/openbmc_project/control/host0/restart_cause";
544 constexpr const char* restartCauseIntf =
545 "xyz.openbmc_project.Common.RestartCause";
546 std::string restartCauseStr;
547 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
548
549 try
550 {
551 auto service =
552 ipmi::getService(*busp, restartCauseIntf, restartCausePath);
553
554 ipmi::Value result = ipmi::getDbusProperty(
555 *busp, service, restartCausePath, restartCauseIntf, "RestartCause");
556 restartCauseStr = std::get<std::string>(result);
557 }
558 catch (const std::exception& e)
559 {
560 log<level::ERR>("Failed to fetch RestartCause property",
561 entry("ERROR=%s", e.what()),
562 entry("PATH=%s", restartCausePath),
563 entry("INTERFACE=%s", restartCauseIntf));
564 return ipmi::responseUnspecifiedError();
565 }
566
567 return ipmi::responseSuccess(getRestartCause(restartCauseStr), 0, 0);
568}
569
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700570ipmi::RspType<> ipmiSetFrontPanelButtonEnables(bool disablePowerButton,
571 bool disableResetButton,
572 bool disableInterruptButton,
573 bool disableSleepButton,
574 uint4_t reserved)
575{
576 bool error = false;
577
578 error |= setButtonEnabled(powerButtonPath, disablePowerButton);
579 error |= setButtonEnabled(resetButtonPath, disableResetButton);
580 error |= setButtonEnabled(interruptButtonPath, disableInterruptButton);
581
582 if (error)
583 {
584 return ipmi::responseUnspecifiedError();
585 }
586 return ipmi::responseSuccess();
587}
588
Yuan Li60e7aaf2019-05-28 14:22:40 +0800589static void registerChassisFunctions(void)
590{
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700591 log<level::INFO>("Registering Chassis commands");
Yuan Li60e7aaf2019-05-28 14:22:40 +0800592
593 createIdentifyTimer();
594
595 if (matchPtr == nullptr)
596 {
597 using namespace sdbusplus::bus::match::rules;
598 auto bus = getSdBus();
599
600 matchPtr = std::make_unique<sdbusplus::bus::match_t>(
601 *bus,
602 sdbusplus::bus::match::rules::propertiesChanged(idButtonPath,
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700603 buttonIntf),
Yuan Li60e7aaf2019-05-28 14:22:40 +0800604 std::bind(idButtonPropChanged, std::placeholders::_1));
605 }
606
607 // <Chassis Identify>
608 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
609 ipmi::chassis::cmdChassisIdentify,
610 ipmi::Privilege::Operator, ipmiChassisIdentify);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700611 // <Get Chassis Status>
612 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
613 ipmi::chassis::cmdGetChassisStatus,
614 ipmi::Privilege::User, ipmiGetChassisStatus);
Jason M. Bills3efc6452019-06-20 15:51:47 -0700615 // <Get System Restart Cause>
616 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
617 ipmi::chassis::cmdGetSystemRestartCause,
618 ipmi::Privilege::User, ipmiGetSystemRestartCause);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700619 // <Set Front Panel Enables>
620 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
621 ipmi::chassis::cmdSetFrontPanelButtonEnables,
622 ipmi::Privilege::User,
623 ipmiSetFrontPanelButtonEnables);
Yuan Li60e7aaf2019-05-28 14:22:40 +0800624}
625
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700626} // namespace ipmi::chassis