blob: f5cc0a3df02669107b64ce89a9b38adfb35202f3 [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";
Jason M. Bills09221d72019-07-26 13:38:28 -070056enum class ChassisIDState
57{
58 off = 0,
59 temporary = 1,
60 indefinite = 2,
61};
62static ChassisIDState chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +080063
64constexpr size_t defaultIdentifyTimeOut = 15;
65
66std::unique_ptr<phosphor::Timer> identifyTimer
67 __attribute__((init_priority(101)));
68std::unique_ptr<sdbusplus::bus::match_t> matchPtr
69 __attribute__((init_priority(101)));
70
71static void registerChassisFunctions() __attribute__((constructor));
72
73static ipmi::ServiceCache LEDService(ledInterface, ledIDBlinkObj);
74
Jason M. Billsb08f84e2019-06-10 12:59:42 -070075void enclosureIdentifyLed(const char* objName, bool isIdLedOn)
Yuan Li60e7aaf2019-05-28 14:22:40 +080076{
77 auto bus = getSdBus();
78
79 try
80 {
81 std::string service = LEDService.getService(*bus);
82 setDbusProperty(*bus, service, objName, ledInterface, ledProp,
83 isIdLedOn);
84 }
Jason M. Billsb08f84e2019-06-10 12:59:42 -070085 catch (const std::exception& e)
Yuan Li60e7aaf2019-05-28 14:22:40 +080086 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -070087 log<level::ERR>("enclosureIdentifyLed: can't set property",
88 entry("ERR=%s", e.what()));
Yuan Li60e7aaf2019-05-28 14:22:40 +080089 }
90}
91
Jason M. Billsb08f84e2019-06-10 12:59:42 -070092bool getIDState(const char* objName, bool& state)
Yuan Li60e7aaf2019-05-28 14:22:40 +080093{
94 auto bus = getSdBus();
95
96 try
97 {
98 std::string service = LEDService.getService(*bus);
99 ipmi::Value enabled =
100 getDbusProperty(*bus, service, objName, ledInterface, ledProp);
101 state = std::get<bool>(enabled);
102 }
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700103 catch (sdbusplus::exception::SdBusError& e)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800104 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700105 log<level::ERR>("Fail to get property", entry("PATH=%s", objName),
106 entry("ERROR=%s", e.what()));
Yuan Li60e7aaf2019-05-28 14:22:40 +0800107 return false;
108 }
109 return true;
110}
111
112void enclosureIdentifyLedBlinkOff()
113{
Jason M. Bills09221d72019-07-26 13:38:28 -0700114 chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800115 enclosureIdentifyLed(ledIDBlinkObj, false);
116}
117
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700118void idButtonPropChanged(sdbusplus::message::message& msg)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800119{
120 bool asserted = false;
121 bool buttonPressed = false;
122
123 std::map<std::string, ipmi::Value> props;
124 std::vector<std::string> inval;
125 std::string iface;
126 msg.read(iface, props, inval);
127
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700128 for (const auto& t : props)
Yuan Li60e7aaf2019-05-28 14:22:40 +0800129 {
130 auto key = t.first;
131 auto value = t.second;
132
133 if (key == idButtonProp)
134 {
135 buttonPressed = std::get<bool>(value);
136 }
137 break;
138 }
139
140 if (buttonPressed)
141 {
142 if (identifyTimer->isRunning())
143 {
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700144 log<level::INFO>("ID timer is running");
Yuan Li60e7aaf2019-05-28 14:22:40 +0800145 }
146
147 // make sure timer is stopped
148 identifyTimer->stop();
149
150 if (!getIDState(ledIDBlinkObj, asserted))
151 {
152 return;
153 }
154
155 if (asserted)
156 {
157 // LED is blinking, turn off the LED
Jason M. Bills09221d72019-07-26 13:38:28 -0700158 chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800159 enclosureIdentifyLed(ledIDBlinkObj, false);
160 enclosureIdentifyLed(ledIDOnObj, false);
161 }
162 else
163 {
164 // toggle the IED on/off
165 if (!getIDState(ledIDOnObj, asserted))
166 {
167 return;
168 }
169 enclosureIdentifyLed(ledIDOnObj, !asserted);
170 }
171 }
172}
173
174void createIdentifyTimer()
175{
176 if (!identifyTimer)
177 {
178 identifyTimer =
179 std::make_unique<phosphor::Timer>(enclosureIdentifyLedBlinkOff);
180 }
181}
182
183ipmi::RspType<> ipmiChassisIdentify(std::optional<uint8_t> interval,
184 std::optional<uint8_t> force)
185{
186 uint8_t identifyInterval = interval.value_or(defaultIdentifyTimeOut);
187 bool forceIdentify = force.value_or(0) & 0x01;
188
189 enclosureIdentifyLed(ledIDOnObj, false);
190 identifyTimer->stop();
191
192 if (identifyInterval || forceIdentify)
193 {
194 enclosureIdentifyLed(ledIDBlinkObj, true);
195 if (forceIdentify)
196 {
Jason M. Bills09221d72019-07-26 13:38:28 -0700197 chassisIDState = ChassisIDState::indefinite;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800198 return ipmi::responseSuccess();
199 }
Jason M. Bills09221d72019-07-26 13:38:28 -0700200 chassisIDState = ChassisIDState::temporary;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800201 // start the timer
202 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
203 std::chrono::seconds(identifyInterval));
204 identifyTimer->start(time);
205 }
206 else
207 {
Jason M. Bills09221d72019-07-26 13:38:28 -0700208 chassisIDState = ChassisIDState::off;
Yuan Li60e7aaf2019-05-28 14:22:40 +0800209 enclosureIdentifyLed(ledIDBlinkObj, false);
210 }
211 return ipmi::responseSuccess();
212}
213
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700214namespace power_policy
215{
216/* helper function for Get Chassis Status Command
217 */
218std::optional<uint2_t> getPowerRestorePolicy()
219{
220 constexpr const char* powerRestorePath =
221 "/xyz/openbmc_project/control/host0/power_restore_policy";
222 constexpr const char* powerRestoreIntf =
223 "xyz.openbmc_project.Control.Power.RestorePolicy";
224 uint2_t restorePolicy = 0;
225 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
226
227 try
228 {
229 auto service =
230 ipmi::getService(*busp, powerRestoreIntf, powerRestorePath);
231
232 ipmi::Value result =
233 ipmi::getDbusProperty(*busp, service, powerRestorePath,
234 powerRestoreIntf, "PowerRestorePolicy");
235 auto powerRestore = sdbusplus::xyz::openbmc_project::Control::Power::
236 server::RestorePolicy::convertPolicyFromString(
237 std::get<std::string>(result));
238
239 using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
240 switch (powerRestore)
241 {
242 case RestorePolicy::Policy::AlwaysOff:
243 restorePolicy = 0x00;
244 break;
245 case RestorePolicy::Policy::Restore:
246 restorePolicy = 0x01;
247 break;
248 case RestorePolicy::Policy::AlwaysOn:
249 restorePolicy = 0x02;
250 break;
251 }
252 }
253 catch (const std::exception& e)
254 {
255 log<level::ERR>("Failed to fetch PowerRestorePolicy property",
256 entry("ERROR=%s", e.what()),
257 entry("PATH=%s", powerRestorePath),
258 entry("INTERFACE=%s", powerRestoreIntf));
259 return std::nullopt;
260 }
261 return std::make_optional(restorePolicy);
262}
263
264/*
265 * getPowerStatus
266 * helper function for Get Chassis Status Command
267 * return - optional value for pgood (no value on error)
268 */
269std::optional<bool> getPowerStatus()
270{
271 bool powerGood = false;
272 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
273 try
274 {
275 constexpr const char* chassisStatePath =
276 "/xyz/openbmc_project/state/chassis0";
277 constexpr const char* chassisStateIntf =
278 "xyz.openbmc_project.State.Chassis";
279 auto service =
280 ipmi::getService(*busp, chassisStateIntf, chassisStatePath);
281
282 ipmi::Value variant =
283 ipmi::getDbusProperty(*busp, service, chassisStatePath,
284 chassisStateIntf, "CurrentPowerState");
285 std::string powerState = std::get<std::string>(variant);
286 if (powerState == "xyz.openbmc_project.State.Chassis.PowerState.On")
287 {
288 powerGood = true;
289 }
290 }
291 catch (const std::exception& e)
292 {
293 log<level::ERR>("Failed to fetch power state property",
294 entry("ERROR=%s", e.what()));
295 return std::nullopt;
296 }
297 return std::make_optional(powerGood);
298}
299
300/*
301 * getACFailStatus
302 * helper function for Get Chassis Status Command
303 * return - bool value for ACFail (false on error)
304 */
305bool getACFailStatus()
306{
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700307 constexpr const char* acBootObj =
308 "/xyz/openbmc_project/control/host0/ac_boot";
309 constexpr const char* acBootIntf = "xyz.openbmc_project.Common.ACBoot";
310 std::string acFail;
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700311 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
312 try
313 {
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700314 auto service = ipmi::getService(*bus, acBootIntf, acBootObj);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700315
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700316 ipmi::Value variant = ipmi::getDbusProperty(*bus, service, acBootObj,
317 acBootIntf, "ACBoot");
318 acFail = std::get<std::string>(variant);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700319 }
320 catch (const std::exception& e)
321 {
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700322 log<level::ERR>(
323 "Failed to fetch ACBoot property", entry("ERROR=%s", e.what()),
324 entry("PATH=%s", acBootObj), entry("INTERFACE=%s", acBootIntf));
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700325 }
Jason M. Billsa2b4c7a2019-06-24 16:55:21 -0700326 return acFail == "True";
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700327}
328} // namespace power_policy
329
330static std::optional<bool> getButtonEnabled(const std::string& buttonPath)
331{
332 bool buttonDisabled = false;
333 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
334 try
335 {
336 auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
337 ipmi::Value disabled = ipmi::getDbusProperty(
338 *busp, service, buttonPath, buttonIntf, "ButtonMasked");
339 buttonDisabled = std::get<bool>(disabled);
340 }
341 catch (sdbusplus::exception::SdBusError& e)
342 {
343 log<level::ERR>("Fail to get button disabled property",
344 entry("PATH=%s", buttonPath.c_str()),
345 entry("ERROR=%s", e.what()));
346 return std::nullopt;
347 }
348 return std::make_optional(buttonDisabled);
349}
350
351static bool setButtonEnabled(const std::string& buttonPath, const bool disabled)
352{
353 try
354 {
355 auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
356 ipmi::setDbusProperty(*getSdBus(), service, buttonPath, buttonIntf,
357 "ButtonMasked", disabled);
358 }
359 catch (std::exception& e)
360 {
361 log<level::ERR>("Failed to set button disabled",
362 entry("EXCEPTION=%s, REQUEST=%x", e.what(), disabled));
363 return -1;
364 }
365
366 return 0;
367}
368
Jason M. Bills8c615392019-07-26 13:45:41 -0700369static bool getRestartCause(std::string& restartCause)
370{
371 constexpr const char* restartCausePath =
372 "/xyz/openbmc_project/control/host0/restart_cause";
373 constexpr const char* restartCauseIntf =
Jason M. Billsbf124d42019-10-04 10:50:43 -0700374 "xyz.openbmc_project.Control.Host.RestartCause";
Jason M. Bills8c615392019-07-26 13:45:41 -0700375 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
376
377 try
378 {
379 auto service =
380 ipmi::getService(*busp, restartCauseIntf, restartCausePath);
381
382 ipmi::Value result = ipmi::getDbusProperty(
383 *busp, service, restartCausePath, restartCauseIntf, "RestartCause");
384 restartCause = std::get<std::string>(result);
385 }
386 catch (const std::exception& e)
387 {
388 log<level::ERR>("Failed to fetch RestartCause property",
389 entry("ERROR=%s", e.what()),
390 entry("PATH=%s", restartCausePath),
391 entry("INTERFACE=%s", restartCauseIntf));
392 return false;
393 }
394 return true;
395}
396
397static bool checkIPMIRestartCause(bool& ipmiRestartCause)
398{
399 std::string restartCause;
400 if (!getRestartCause(restartCause))
401 {
402 return false;
403 }
404 ipmiRestartCause =
405 (restartCause ==
406 "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand");
407 return true;
408}
409
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700410//----------------------------------------------------------------------
411// Get Chassis Status commands
412//----------------------------------------------------------------------
413ipmi::RspType<bool, // Power is on
414 bool, // Power overload
415 bool, // Interlock
416 bool, // power fault
417 bool, // power control fault
418 uint2_t, // power restore policy
419 bool, // reserved
420
421 bool, // AC failed
422 bool, // last power down caused by a Power overload
423 bool, // last power down caused by a power interlock
424 bool, // last power down caused by power fault
425 bool, // last ‘Power is on’ state was entered via IPMI command
426 uint3_t, // reserved
427
428 bool, // Chassis intrusion active
429 bool, // Front Panel Lockout active
430 bool, // Drive Fault
431 bool, // Cooling/fan fault detected
432 uint2_t, // Chassis Identify State
433 bool, // Chassis Identify command and state info supported
434 bool, // reserved
435
436 bool, // Power off button disabled
437 bool, // Reset button disabled
438 bool, // Diagnostic Interrupt button disabled
439 bool, // Standby (sleep) button disabled
440 bool, // Power off button disable allowed
441 bool, // Reset button disable allowed
442 bool, // Diagnostic Interrupt button disable allowed
443 bool // Standby (sleep) button disable allowed
444 >
445 ipmiGetChassisStatus()
446{
447 std::optional<uint2_t> restorePolicy =
448 power_policy::getPowerRestorePolicy();
449 std::optional<bool> powerGood = power_policy::getPowerStatus();
450 if (!restorePolicy || !powerGood)
451 {
452 return ipmi::responseUnspecifiedError();
453 }
454
455 // Front Panel Button Capabilities and disable/enable status(Optional)
456 std::optional<bool> powerButtonReading = getButtonEnabled(powerButtonPath);
457 // allow disable if the interface is present
458 bool powerButtonDisableAllow = static_cast<bool>(powerButtonReading);
459 // default return the button is enabled (not disabled)
460 bool powerButtonDisabled = false;
461 if (powerButtonDisableAllow)
462 {
463 // return the real value of the button status, if present
464 powerButtonDisabled = *powerButtonReading;
465 }
466
467 std::optional<bool> resetButtonReading = getButtonEnabled(resetButtonPath);
468 // allow disable if the interface is present
469 bool resetButtonDisableAllow = static_cast<bool>(resetButtonReading);
470 // default return the button is enabled (not disabled)
471 bool resetButtonDisabled = false;
472 if (resetButtonDisableAllow)
473 {
474 // return the real value of the button status, if present
475 resetButtonDisabled = *resetButtonReading;
476 }
477
478 std::optional<bool> interruptButtonReading =
479 getButtonEnabled(interruptButtonPath);
480 // allow disable if the interface is present
481 bool interruptButtonDisableAllow =
482 static_cast<bool>(interruptButtonReading);
483 // default return the button is enabled (not disabled)
484 bool interruptButtonDisabled = false;
485 if (interruptButtonDisableAllow)
486 {
487 // return the real value of the button status, if present
488 interruptButtonDisabled = *interruptButtonReading;
489 }
490
491 bool powerDownAcFailed = power_policy::getACFailStatus();
492
Jason M. Bills8c615392019-07-26 13:45:41 -0700493 bool powerStatusIPMI = false;
494 if (!checkIPMIRestartCause(powerStatusIPMI))
495 {
496 return ipmi::responseUnspecifiedError();
497 }
498
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700499 // This response has a lot of hard-coded, unsupported fields
500 // They are set to false or 0
501 constexpr bool powerOverload = false;
502 constexpr bool chassisInterlock = false;
503 constexpr bool powerFault = false;
504 constexpr bool powerControlFault = false;
505 constexpr bool powerDownOverload = false;
506 constexpr bool powerDownInterlock = false;
507 constexpr bool powerDownPowerFault = false;
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700508 constexpr bool chassisIntrusionActive = false;
509 constexpr bool frontPanelLockoutActive = false;
510 constexpr bool driveFault = false;
511 constexpr bool coolingFanFault = false;
512 // chassisIdentifySupport set because this command is implemented
513 constexpr bool chassisIdentifySupport = true;
Jason M. Bills09221d72019-07-26 13:38:28 -0700514 uint2_t chassisIdentifyState = chassisIDState;
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700515 constexpr bool sleepButtonDisabled = false;
516 constexpr bool sleepButtonDisableAllow = false;
517
518 return ipmi::responseSuccess(
519 *powerGood, powerOverload, chassisInterlock, powerFault,
520 powerControlFault, *restorePolicy,
521 false, // reserved
522
523 powerDownAcFailed, powerDownOverload, powerDownInterlock,
524 powerDownPowerFault, powerStatusIPMI,
525 uint3_t(0), // reserved
526
527 chassisIntrusionActive, frontPanelLockoutActive, driveFault,
528 coolingFanFault, chassisIdentifyState, chassisIdentifySupport,
529 false, // reserved
530
531 powerButtonDisabled, resetButtonDisabled, interruptButtonDisabled,
532 sleepButtonDisabled, powerButtonDisableAllow, resetButtonDisableAllow,
533 interruptButtonDisableAllow, sleepButtonDisableAllow);
534}
535
Jason M. Bills8c615392019-07-26 13:45:41 -0700536static uint4_t getRestartCauseValue(const std::string& cause)
Jason M. Bills3efc6452019-06-20 15:51:47 -0700537{
538 uint4_t restartCauseValue = 0;
539 if (cause == "xyz.openbmc_project.State.Host.RestartCause.Unknown")
540 {
541 restartCauseValue = 0x0;
542 }
543 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand")
544 {
545 restartCauseValue = 0x1;
546 }
547 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.ResetButton")
548 {
549 restartCauseValue = 0x2;
550 }
551 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PowerButton")
552 {
553 restartCauseValue = 0x3;
554 }
555 else if (cause ==
556 "xyz.openbmc_project.State.Host.RestartCause.WatchdogTimer")
557 {
558 restartCauseValue = 0x4;
559 }
560 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.OEM")
561 {
562 restartCauseValue = 0x5;
563 }
564 else if (cause ==
565 "xyz.openbmc_project.State.Host.RestartCause.PowerPolicyAlwaysOn")
566 {
567 restartCauseValue = 0x6;
568 }
569 else if (cause == "xyz.openbmc_project.State.Host.RestartCause."
570 "PowerPolicyPreviousState")
571 {
572 restartCauseValue = 0x7;
573 }
574 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PEFReset")
575 {
576 restartCauseValue = 0x8;
577 }
578 else if (cause ==
579 "xyz.openbmc_project.State.Host.RestartCause.PEFPowerCycle")
580 {
581 restartCauseValue = 0x9;
582 }
583 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.SoftReset")
584 {
585 restartCauseValue = 0xa;
586 }
587 else if (cause == "xyz.openbmc_project.State.Host.RestartCause.RTCWakeup")
588 {
589 restartCauseValue = 0xb;
590 }
591 return restartCauseValue;
592}
593
594ipmi::RspType<uint4_t, // Restart Cause
595 uint4_t, // reserved
596 uint8_t // channel number (not supported)
597 >
598 ipmiGetSystemRestartCause()
599{
Jason M. Bills3efc6452019-06-20 15:51:47 -0700600 std::string restartCauseStr;
Jason M. Bills8c615392019-07-26 13:45:41 -0700601 if (!getRestartCause(restartCauseStr))
Jason M. Bills3efc6452019-06-20 15:51:47 -0700602 {
Jason M. Bills3efc6452019-06-20 15:51:47 -0700603 return ipmi::responseUnspecifiedError();
604 }
605
Jason M. Bills8c615392019-07-26 13:45:41 -0700606 return ipmi::responseSuccess(getRestartCauseValue(restartCauseStr), 0, 0);
Jason M. Bills3efc6452019-06-20 15:51:47 -0700607}
608
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700609ipmi::RspType<> ipmiSetFrontPanelButtonEnables(bool disablePowerButton,
610 bool disableResetButton,
611 bool disableInterruptButton,
612 bool disableSleepButton,
613 uint4_t reserved)
614{
615 bool error = false;
616
617 error |= setButtonEnabled(powerButtonPath, disablePowerButton);
618 error |= setButtonEnabled(resetButtonPath, disableResetButton);
619 error |= setButtonEnabled(interruptButtonPath, disableInterruptButton);
620
621 if (error)
622 {
623 return ipmi::responseUnspecifiedError();
624 }
625 return ipmi::responseSuccess();
626}
627
Yuan Li60e7aaf2019-05-28 14:22:40 +0800628static void registerChassisFunctions(void)
629{
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700630 log<level::INFO>("Registering Chassis commands");
Yuan Li60e7aaf2019-05-28 14:22:40 +0800631
632 createIdentifyTimer();
633
634 if (matchPtr == nullptr)
635 {
636 using namespace sdbusplus::bus::match::rules;
637 auto bus = getSdBus();
638
639 matchPtr = std::make_unique<sdbusplus::bus::match_t>(
640 *bus,
641 sdbusplus::bus::match::rules::propertiesChanged(idButtonPath,
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700642 buttonIntf),
Yuan Li60e7aaf2019-05-28 14:22:40 +0800643 std::bind(idButtonPropChanged, std::placeholders::_1));
644 }
645
646 // <Chassis Identify>
647 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
648 ipmi::chassis::cmdChassisIdentify,
649 ipmi::Privilege::Operator, ipmiChassisIdentify);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700650 // <Get Chassis Status>
651 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
652 ipmi::chassis::cmdGetChassisStatus,
653 ipmi::Privilege::User, ipmiGetChassisStatus);
Jason M. Bills3efc6452019-06-20 15:51:47 -0700654 // <Get System Restart Cause>
655 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
656 ipmi::chassis::cmdGetSystemRestartCause,
657 ipmi::Privilege::User, ipmiGetSystemRestartCause);
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700658 // <Set Front Panel Enables>
659 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
660 ipmi::chassis::cmdSetFrontPanelButtonEnables,
661 ipmi::Privilege::User,
662 ipmiSetFrontPanelButtonEnables);
Yuan Li60e7aaf2019-05-28 14:22:40 +0800663}
664
Jason M. Billsb08f84e2019-06-10 12:59:42 -0700665} // namespace ipmi::chassis