blob: 1ff29c293c0e59eca3a80d68adb9a819a434364f [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
Yuan Li60e7aaf2019-05-28 14:22:40 +080018#include <ipmid/api.hpp>
19#include <ipmid/utils.hpp>
20#include <nlohmann/json.hpp>
21#include <phosphor-logging/elog-errors.hpp>
Jason M. Billsb08f84e2019-06-10 12:59:42 -070022#include <phosphor-logging/log.hpp>
Yuan Li60e7aaf2019-05-28 14:22:40 +080023#include <sdbusplus/timer.hpp>
James Feistfcd2d3a2020-05-28 10:38:15 -070024#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
25
26#include <fstream>
27#include <iostream>
28#include <regex>
Jason M. Billsb08f84e2019-06-10 12:59:42 -070029#include <stdexcept>
30#include <string_view>
Yuan Li60e7aaf2019-05-28 14:22:40 +080031
Jason M. Billsb08f84e2019-06-10 12:59:42 -070032using namespace phosphor::logging;
33
34namespace ipmi::chassis
Yuan Li60e7aaf2019-05-28 14:22:40 +080035{
Jason M. Billsb08f84e2019-06-10 12:59:42 -070036static constexpr const char* buttonIntf = "xyz.openbmc_project.Chassis.Buttons";
Yuan Li60e7aaf2019-05-28 14:22:40 +080037
Jason M. Billsb08f84e2019-06-10 12:59:42 -070038const static constexpr char* idButtonPath =
39 "/xyz/openbmc_project/chassis/buttons/id";
40static constexpr const char* powerButtonPath =
41 "/xyz/openbmc_project/chassis/buttons/power";
42static constexpr const char* resetButtonPath =
43 "/xyz/openbmc_project/chassis/buttons/reset";
44static constexpr const char* interruptButtonPath =
45 "/xyz/openbmc_project/chassis/buttons/nmi";
46
47const static constexpr char* idButtonProp = "ButtonPressed";
48
49const static constexpr char* ledService =
Yuan Li60e7aaf2019-05-28 14:22:40 +080050 "xyz.openbmc_project.LED.GroupManager";
Jason M. Billsb08f84e2019-06-10 12:59:42 -070051const static constexpr char* ledIDOnObj =
Yuan Li60e7aaf2019-05-28 14:22:40 +080052 "/xyz/openbmc_project/led/groups/enclosure_identify";
Jason M. Billsb08f84e2019-06-10 12:59:42 -070053const static constexpr char* ledIDBlinkObj =
Yuan Li60e7aaf2019-05-28 14:22:40 +080054 "/xyz/openbmc_project/led/groups/enclosure_identify_blink";
Jason M. Billsb08f84e2019-06-10 12:59:42 -070055const static constexpr char* ledInterface = "xyz.openbmc_project.Led.Group";
56const static constexpr char* ledProp = "Asserted";
Jason M. Bills09221d72019-07-26 13:38:28 -070057enum class ChassisIDState
58{
59 off = 0,
60 temporary = 1,
61 indefinite = 2,
62};
63static ChassisIDState chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +080064
65constexpr size_t defaultIdentifyTimeOut = 15;
66
67std::unique_ptr<phosphor::Timer> identifyTimer
68 __attribute__((init_priority(101)));
69std::unique_ptr<sdbusplus::bus::match_t> matchPtr
70 __attribute__((init_priority(101)));
71
72static void registerChassisFunctions() __attribute__((constructor));
73
74static ipmi::ServiceCache LEDService(ledInterface, ledIDBlinkObj);
75
Jason M. Billsb08f84e2019-06-10 12:59:42 -070076void enclosureIdentifyLed(const char* objName, bool isIdLedOn)
Yuan Li60e7aaf2019-05-28 14:22:40 +080077{
78 auto bus = getSdBus();
79
80 try
81 {
82 std::string service = LEDService.getService(*bus);
83 setDbusProperty(*bus, service, objName, ledInterface, ledProp,
84 isIdLedOn);
85 }
Jason M. Billsb08f84e2019-06-10 12:59:42 -070086 catch (const std::exception& e)
Yuan Li60e7aaf2019-05-28 14:22:40 +080087 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -070088 log<level::ERR>("enclosureIdentifyLed: can't set property",
89 entry("ERR=%s", e.what()));
Yuan Li60e7aaf2019-05-28 14:22:40 +080090 }
91}
92
Jason M. Billsb08f84e2019-06-10 12:59:42 -070093bool getIDState(const char* objName, bool& state)
Yuan Li60e7aaf2019-05-28 14:22:40 +080094{
95 auto bus = getSdBus();
96
97 try
98 {
99 std::string service = LEDService.getService(*bus);
100 ipmi::Value enabled =
101 getDbusProperty(*bus, service, objName, ledInterface, ledProp);
102 state = std::get<bool>(enabled);
103 }
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700104 catch (sdbusplus::exception::SdBusError& e)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800105 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700106 log<level::ERR>("Fail to get property", entry("PATH=%s", objName),
107 entry("ERROR=%s", e.what()));
Yuan Li60e7aaf2019-05-28 14:22:40 +0800108 return false;
109 }
110 return true;
111}
112
113void enclosureIdentifyLedBlinkOff()
114{
Jason M. Bills09221d72019-07-26 13:38:28 -0700115 chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800116 enclosureIdentifyLed(ledIDBlinkObj, false);
117}
118
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700119void idButtonPropChanged(sdbusplus::message::message& msg)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800120{
121 bool asserted = false;
122 bool buttonPressed = false;
123
124 std::map<std::string, ipmi::Value> props;
125 std::vector<std::string> inval;
126 std::string iface;
127 msg.read(iface, props, inval);
128
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700129 for (const auto& t : props)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800130 {
131 auto key = t.first;
132 auto value = t.second;
133
134 if (key == idButtonProp)
135 {
136 buttonPressed = std::get<bool>(value);
137 }
138 break;
139 }
140
141 if (buttonPressed)
142 {
143 if (identifyTimer->isRunning())
144 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700145 log<level::INFO>("ID timer is running");
Yuan Li60e7aaf2019-05-28 14:22:40 +0800146 }
147
148 // make sure timer is stopped
149 identifyTimer->stop();
150
151 if (!getIDState(ledIDBlinkObj, asserted))
152 {
153 return;
154 }
155
156 if (asserted)
157 {
158 // LED is blinking, turn off the LED
Jason M. Bills09221d72019-07-26 13:38:28 -0700159 chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800160 enclosureIdentifyLed(ledIDBlinkObj, false);
161 enclosureIdentifyLed(ledIDOnObj, false);
162 }
163 else
164 {
165 // toggle the IED on/off
166 if (!getIDState(ledIDOnObj, asserted))
167 {
168 return;
169 }
170 enclosureIdentifyLed(ledIDOnObj, !asserted);
171 }
172 }
173}
174
175void createIdentifyTimer()
176{
177 if (!identifyTimer)
178 {
179 identifyTimer =
180 std::make_unique<phosphor::Timer>(enclosureIdentifyLedBlinkOff);
181 }
182}
183
184ipmi::RspType<> ipmiChassisIdentify(std::optional<uint8_t> interval,
185 std::optional<uint8_t> force)
186{
187 uint8_t identifyInterval = interval.value_or(defaultIdentifyTimeOut);
188 bool forceIdentify = force.value_or(0) & 0x01;
189
190 enclosureIdentifyLed(ledIDOnObj, false);
191 identifyTimer->stop();
192
193 if (identifyInterval || forceIdentify)
194 {
195 enclosureIdentifyLed(ledIDBlinkObj, true);
196 if (forceIdentify)
197 {
Jason M. Bills09221d72019-07-26 13:38:28 -0700198 chassisIDState = ChassisIDState::indefinite;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800199 return ipmi::responseSuccess();
200 }
Jason M. Bills09221d72019-07-26 13:38:28 -0700201 chassisIDState = ChassisIDState::temporary;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800202 // start the timer
203 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
204 std::chrono::seconds(identifyInterval));
205 identifyTimer->start(time);
206 }
207 else
208 {
Jason M. Bills09221d72019-07-26 13:38:28 -0700209 chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800210 enclosureIdentifyLed(ledIDBlinkObj, false);
211 }
212 return ipmi::responseSuccess();
213}
214
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700215namespace power_policy
216{
217/* helper function for Get Chassis Status Command
218 */
219std::optional<uint2_t> getPowerRestorePolicy()
220{
221 constexpr const char* powerRestorePath =
222 "/xyz/openbmc_project/control/host0/power_restore_policy";
223 constexpr const char* powerRestoreIntf =
224 "xyz.openbmc_project.Control.Power.RestorePolicy";
225 uint2_t restorePolicy = 0;
226 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
227
228 try
229 {
230 auto service =
231 ipmi::getService(*busp, powerRestoreIntf, powerRestorePath);
232
233 ipmi::Value result =
234 ipmi::getDbusProperty(*busp, service, powerRestorePath,
235 powerRestoreIntf, "PowerRestorePolicy");
236 auto powerRestore = sdbusplus::xyz::openbmc_project::Control::Power::
237 server::RestorePolicy::convertPolicyFromString(
238 std::get<std::string>(result));
239
240 using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
241 switch (powerRestore)
242 {
243 case RestorePolicy::Policy::AlwaysOff:
244 restorePolicy = 0x00;
245 break;
246 case RestorePolicy::Policy::Restore:
247 restorePolicy = 0x01;
248 break;
249 case RestorePolicy::Policy::AlwaysOn:
250 restorePolicy = 0x02;
251 break;
252 }
253 }
254 catch (const std::exception& e)
255 {
256 log<level::ERR>("Failed to fetch PowerRestorePolicy property",
257 entry("ERROR=%s", e.what()),
258 entry("PATH=%s", powerRestorePath),
259 entry("INTERFACE=%s", powerRestoreIntf));
260 return std::nullopt;
261 }
262 return std::make_optional(restorePolicy);
263}
264
265/*
266 * getPowerStatus
267 * helper function for Get Chassis Status Command
268 * return - optional value for pgood (no value on error)
269 */
270std::optional<bool> getPowerStatus()
271{
272 bool powerGood = false;
273 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
274 try
275 {
276 constexpr const char* chassisStatePath =
277 "/xyz/openbmc_project/state/chassis0";
278 constexpr const char* chassisStateIntf =
279 "xyz.openbmc_project.State.Chassis";
280 auto service =
281 ipmi::getService(*busp, chassisStateIntf, chassisStatePath);
282
283 ipmi::Value variant =
284 ipmi::getDbusProperty(*busp, service, chassisStatePath,
285 chassisStateIntf, "CurrentPowerState");
286 std::string powerState = std::get<std::string>(variant);
287 if (powerState == "xyz.openbmc_project.State.Chassis.PowerState.On")
288 {
289 powerGood = true;
290 }
291 }
292 catch (const std::exception& e)
293 {
294 log<level::ERR>("Failed to fetch power state property",
295 entry("ERROR=%s", e.what()));
296 return std::nullopt;
297 }
298 return std::make_optional(powerGood);
299}
300
301/*
302 * getACFailStatus
303 * helper function for Get Chassis Status Command
304 * return - bool value for ACFail (false on error)
305 */
306bool getACFailStatus()
307{
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700308 constexpr const char* acBootObj =
309 "/xyz/openbmc_project/control/host0/ac_boot";
310 constexpr const char* acBootIntf = "xyz.openbmc_project.Common.ACBoot";
311 std::string acFail;
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700312 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
313 try
314 {
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700315 auto service = ipmi::getService(*bus, acBootIntf, acBootObj);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700316
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700317 ipmi::Value variant = ipmi::getDbusProperty(*bus, service, acBootObj,
318 acBootIntf, "ACBoot");
319 acFail = std::get<std::string>(variant);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700320 }
321 catch (const std::exception& e)
322 {
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700323 log<level::ERR>(
324 "Failed to fetch ACBoot property", entry("ERROR=%s", e.what()),
325 entry("PATH=%s", acBootObj), entry("INTERFACE=%s", acBootIntf));
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700326 }
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700327 return acFail == "True";
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700328}
329} // namespace power_policy
330
331static std::optional<bool> getButtonEnabled(const std::string& buttonPath)
332{
333 bool buttonDisabled = false;
334 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
335 try
336 {
337 auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
338 ipmi::Value disabled = ipmi::getDbusProperty(
339 *busp, service, buttonPath, buttonIntf, "ButtonMasked");
340 buttonDisabled = std::get<bool>(disabled);
341 }
342 catch (sdbusplus::exception::SdBusError& e)
343 {
344 log<level::ERR>("Fail to get button disabled property",
345 entry("PATH=%s", buttonPath.c_str()),
346 entry("ERROR=%s", e.what()));
347 return std::nullopt;
348 }
349 return std::make_optional(buttonDisabled);
350}
351
352static bool setButtonEnabled(const std::string& buttonPath, const bool disabled)
353{
354 try
355 {
356 auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
357 ipmi::setDbusProperty(*getSdBus(), service, buttonPath, buttonIntf,
358 "ButtonMasked", disabled);
359 }
360 catch (std::exception& e)
361 {
362 log<level::ERR>("Failed to set button disabled",
363 entry("EXCEPTION=%s, REQUEST=%x", e.what(), disabled));
364 return -1;
365 }
366
367 return 0;
368}
369
Jason M. Bills8c615392019-07-26 13:45:41 -0700370static bool getRestartCause(std::string& restartCause)
371{
372 constexpr const char* restartCausePath =
373 "/xyz/openbmc_project/control/host0/restart_cause";
374 constexpr const char* restartCauseIntf =
Jason M. Billsbf124d42019-10-04 10:50:43 -0700375 "xyz.openbmc_project.Control.Host.RestartCause";
Jason M. Bills8c615392019-07-26 13:45:41 -0700376 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
377
378 try
379 {
380 auto service =
381 ipmi::getService(*busp, restartCauseIntf, restartCausePath);
382
383 ipmi::Value result = ipmi::getDbusProperty(
384 *busp, service, restartCausePath, restartCauseIntf, "RestartCause");
385 restartCause = std::get<std::string>(result);
386 }
387 catch (const std::exception& e)
388 {
389 log<level::ERR>("Failed to fetch RestartCause property",
390 entry("ERROR=%s", e.what()),
391 entry("PATH=%s", restartCausePath),
392 entry("INTERFACE=%s", restartCauseIntf));
393 return false;
394 }
395 return true;
396}
397
398static bool checkIPMIRestartCause(bool& ipmiRestartCause)
399{
400 std::string restartCause;
401 if (!getRestartCause(restartCause))
402 {
403 return false;
404 }
405 ipmiRestartCause =
406 (restartCause ==
407 "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand");
408 return true;
409}
410
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700411//----------------------------------------------------------------------
412// Get Chassis Status commands
413//----------------------------------------------------------------------
414ipmi::RspType<bool, // Power is on
415 bool, // Power overload
416 bool, // Interlock
417 bool, // power fault
418 bool, // power control fault
419 uint2_t, // power restore policy
420 bool, // reserved
421
422 bool, // AC failed
423 bool, // last power down caused by a Power overload
424 bool, // last power down caused by a power interlock
425 bool, // last power down caused by power fault
426 bool, // last ‘Power is on’ state was entered via IPMI command
427 uint3_t, // reserved
428
429 bool, // Chassis intrusion active
430 bool, // Front Panel Lockout active
431 bool, // Drive Fault
432 bool, // Cooling/fan fault detected
433 uint2_t, // Chassis Identify State
434 bool, // Chassis Identify command and state info supported
435 bool, // reserved
436
437 bool, // Power off button disabled
438 bool, // Reset button disabled
439 bool, // Diagnostic Interrupt button disabled
440 bool, // Standby (sleep) button disabled
441 bool, // Power off button disable allowed
442 bool, // Reset button disable allowed
443 bool, // Diagnostic Interrupt button disable allowed
444 bool // Standby (sleep) button disable allowed
445 >
446 ipmiGetChassisStatus()
447{
448 std::optional<uint2_t> restorePolicy =
449 power_policy::getPowerRestorePolicy();
450 std::optional<bool> powerGood = power_policy::getPowerStatus();
451 if (!restorePolicy || !powerGood)
452 {
453 return ipmi::responseUnspecifiedError();
454 }
455
456 // Front Panel Button Capabilities and disable/enable status(Optional)
457 std::optional<bool> powerButtonReading = getButtonEnabled(powerButtonPath);
458 // allow disable if the interface is present
459 bool powerButtonDisableAllow = static_cast<bool>(powerButtonReading);
460 // default return the button is enabled (not disabled)
461 bool powerButtonDisabled = false;
462 if (powerButtonDisableAllow)
463 {
464 // return the real value of the button status, if present
465 powerButtonDisabled = *powerButtonReading;
466 }
467
468 std::optional<bool> resetButtonReading = getButtonEnabled(resetButtonPath);
469 // allow disable if the interface is present
470 bool resetButtonDisableAllow = static_cast<bool>(resetButtonReading);
471 // default return the button is enabled (not disabled)
472 bool resetButtonDisabled = false;
473 if (resetButtonDisableAllow)
474 {
475 // return the real value of the button status, if present
476 resetButtonDisabled = *resetButtonReading;
477 }
478
479 std::optional<bool> interruptButtonReading =
480 getButtonEnabled(interruptButtonPath);
481 // allow disable if the interface is present
482 bool interruptButtonDisableAllow =
483 static_cast<bool>(interruptButtonReading);
484 // default return the button is enabled (not disabled)
485 bool interruptButtonDisabled = false;
486 if (interruptButtonDisableAllow)
487 {
488 // return the real value of the button status, if present
489 interruptButtonDisabled = *interruptButtonReading;
490 }
491
492 bool powerDownAcFailed = power_policy::getACFailStatus();
493
Jason M. Bills8c615392019-07-26 13:45:41 -0700494 bool powerStatusIPMI = false;
495 if (!checkIPMIRestartCause(powerStatusIPMI))
496 {
497 return ipmi::responseUnspecifiedError();
498 }
499
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700500 // This response has a lot of hard-coded, unsupported fields
501 // They are set to false or 0
502 constexpr bool powerOverload = false;
503 constexpr bool chassisInterlock = false;
504 constexpr bool powerFault = false;
505 constexpr bool powerControlFault = false;
506 constexpr bool powerDownOverload = false;
507 constexpr bool powerDownInterlock = false;
508 constexpr bool powerDownPowerFault = false;
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700509 constexpr bool chassisIntrusionActive = false;
510 constexpr bool frontPanelLockoutActive = false;
511 constexpr bool driveFault = false;
512 constexpr bool coolingFanFault = false;
513 // chassisIdentifySupport set because this command is implemented
514 constexpr bool chassisIdentifySupport = true;
Jason M. Bills09221d72019-07-26 13:38:28 -0700515 uint2_t chassisIdentifyState = chassisIDState;
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700516 constexpr bool sleepButtonDisabled = false;
517 constexpr bool sleepButtonDisableAllow = false;
518
519 return ipmi::responseSuccess(
520 *powerGood, powerOverload, chassisInterlock, powerFault,
521 powerControlFault, *restorePolicy,
522 false, // reserved
523
524 powerDownAcFailed, powerDownOverload, powerDownInterlock,
525 powerDownPowerFault, powerStatusIPMI,
526 uint3_t(0), // reserved
527
528 chassisIntrusionActive, frontPanelLockoutActive, driveFault,
529 coolingFanFault, chassisIdentifyState, chassisIdentifySupport,
530 false, // reserved
531
532 powerButtonDisabled, resetButtonDisabled, interruptButtonDisabled,
533 sleepButtonDisabled, powerButtonDisableAllow, resetButtonDisableAllow,
534 interruptButtonDisableAllow, sleepButtonDisableAllow);
535}
536
Jason M. Bills8c615392019-07-26 13:45:41 -0700537static uint4_t getRestartCauseValue(const std::string& cause)
Jason M. Bills3efc6452019-06-20 15:51:47 -0700538{
539 uint4_t restartCauseValue = 0;
540 if (cause == "xyz.openbmc_project.State.Host.RestartCause.Unknown")
541 {
542 restartCauseValue = 0x0;
543 }
544 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand")
545 {
546 restartCauseValue = 0x1;
547 }
548 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.ResetButton")
549 {
550 restartCauseValue = 0x2;
551 }
552 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PowerButton")
553 {
554 restartCauseValue = 0x3;
555 }
556 else if (cause ==
557 "xyz.openbmc_project.State.Host.RestartCause.WatchdogTimer")
558 {
559 restartCauseValue = 0x4;
560 }
561 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.OEM")
562 {
563 restartCauseValue = 0x5;
564 }
565 else if (cause ==
566 "xyz.openbmc_project.State.Host.RestartCause.PowerPolicyAlwaysOn")
567 {
568 restartCauseValue = 0x6;
569 }
570 else if (cause == "xyz.openbmc_project.State.Host.RestartCause."
571 "PowerPolicyPreviousState")
572 {
573 restartCauseValue = 0x7;
574 }
575 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PEFReset")
576 {
577 restartCauseValue = 0x8;
578 }
579 else if (cause ==
580 "xyz.openbmc_project.State.Host.RestartCause.PEFPowerCycle")
581 {
582 restartCauseValue = 0x9;
583 }
584 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.SoftReset")
585 {
586 restartCauseValue = 0xa;
587 }
588 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.RTCWakeup")
589 {
590 restartCauseValue = 0xb;
591 }
592 return restartCauseValue;
593}
594
595ipmi::RspType<uint4_t, // Restart Cause
596 uint4_t, // reserved
597 uint8_t // channel number (not supported)
598 >
599 ipmiGetSystemRestartCause()
600{
Jason M. Bills3efc6452019-06-20 15:51:47 -0700601 std::string restartCauseStr;
Jason M. Bills8c615392019-07-26 13:45:41 -0700602 if (!getRestartCause(restartCauseStr))
Jason M. Bills3efc6452019-06-20 15:51:47 -0700603 {
Jason M. Bills3efc6452019-06-20 15:51:47 -0700604 return ipmi::responseUnspecifiedError();
605 }
606
Jason M. Bills8c615392019-07-26 13:45:41 -0700607 return ipmi::responseSuccess(getRestartCauseValue(restartCauseStr), 0, 0);
Jason M. Bills3efc6452019-06-20 15:51:47 -0700608}
609
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700610ipmi::RspType<> ipmiSetFrontPanelButtonEnables(bool disablePowerButton,
611 bool disableResetButton,
612 bool disableInterruptButton,
613 bool disableSleepButton,
614 uint4_t reserved)
615{
616 bool error = false;
617
618 error |= setButtonEnabled(powerButtonPath, disablePowerButton);
619 error |= setButtonEnabled(resetButtonPath, disableResetButton);
620 error |= setButtonEnabled(interruptButtonPath, disableInterruptButton);
621
622 if (error)
623 {
624 return ipmi::responseUnspecifiedError();
625 }
626 return ipmi::responseSuccess();
627}
628
Yuan Li60e7aaf2019-05-28 14:22:40 +0800629static void registerChassisFunctions(void)
630{
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700631 log<level::INFO>("Registering Chassis commands");
Yuan Li60e7aaf2019-05-28 14:22:40 +0800632
633 createIdentifyTimer();
634
635 if (matchPtr == nullptr)
636 {
637 using namespace sdbusplus::bus::match::rules;
638 auto bus = getSdBus();
639
640 matchPtr = std::make_unique<sdbusplus::bus::match_t>(
641 *bus,
642 sdbusplus::bus::match::rules::propertiesChanged(idButtonPath,
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700643 buttonIntf),
Yuan Li60e7aaf2019-05-28 14:22:40 +0800644 std::bind(idButtonPropChanged, std::placeholders::_1));
645 }
646
647 // <Chassis Identify>
648 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
649 ipmi::chassis::cmdChassisIdentify,
650 ipmi::Privilege::Operator, ipmiChassisIdentify);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700651 // <Get Chassis Status>
652 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
653 ipmi::chassis::cmdGetChassisStatus,
654 ipmi::Privilege::User, ipmiGetChassisStatus);
Jason M. Bills3efc6452019-06-20 15:51:47 -0700655 // <Get System Restart Cause>
656 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
657 ipmi::chassis::cmdGetSystemRestartCause,
658 ipmi::Privilege::User, ipmiGetSystemRestartCause);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700659 // <Set Front Panel Enables>
660 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
661 ipmi::chassis::cmdSetFrontPanelButtonEnables,
AppaRao Puli51acbdf2019-11-10 21:05:34 +0530662 ipmi::Privilege::Admin,
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700663 ipmiSetFrontPanelButtonEnables);
Yuan Li60e7aaf2019-05-28 14:22:40 +0800664}
665
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700666} // namespace ipmi::chassis