Implement set front panel button enables command

The buttons D-Bus interface offers an Enabled option that can be
used by IPMI to change the button enabled state.

This adds support for disabling the power and reset buttons.

Test-By: ipmitool raw 0x0 0xa 0x2 # disable reset button
         ipmitool raw 0x0 0xa 0x1 # disable power button
         ipmitool raw 0x0 0xa 0x0 # enable all buttons
         ipmitool raw 0x0 0x01    # check button status in byte 5

Change-Id: I3d40261f4e7b4eb82606a3d7a9e861e12ca18151
Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/chassishandler.cpp b/chassishandler.cpp
index 216af6a..46a4707 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -982,6 +982,29 @@
     return std::make_optional(buttonDisabled);
 }
 
+static bool setButtonEnabled(ipmi::Context::ptr& ctx,
+                             const std::string& buttonPath,
+                             const std::string& buttonIntf, bool enable)
+{
+    std::string service;
+    boost::system::error_code ec;
+    ec = ipmi::getService(ctx, buttonIntf, buttonPath, service);
+    if (!ec)
+    {
+        ec = ipmi::setDbusProperty(ctx, service, buttonPath, buttonIntf,
+                                   "Enabled", enable);
+    }
+    if (ec)
+    {
+        log<level::ERR>("Fail to set button Enabled property",
+                        entry("SERVICE=%s", service.c_str()),
+                        entry("PATH=%s", buttonPath.c_str()),
+                        entry("ERROR=%s", ec.message().c_str()));
+        return false;
+    }
+    return true;
+}
+
 //----------------------------------------------------------------------
 // Get Chassis Status commands
 //----------------------------------------------------------------------
@@ -1952,6 +1975,28 @@
     return ipmi::responseSuccess(power_policy::allSupport, reserved);
 }
 
+ipmi::RspType<> ipmiSetFrontPanelButtonEnables(
+    ipmi::Context::ptr ctx, bool disablePowerButton, bool disableResetButton,
+    bool disableDiagButton, bool disableSleepButton, uint4_t reserved)
+{
+    using namespace chassis::internal;
+
+    // set power button Enabled property
+    bool success = setButtonEnabled(ctx, powerButtonPath, powerButtonIntf,
+                                    !disablePowerButton);
+
+    // set reset button Enabled property
+    success &= setButtonEnabled(ctx, resetButtonPath, resetButtonIntf,
+                                !disableResetButton);
+
+    if (!success)
+    {
+        // not all buttons were successfully set
+        return ipmi::responseUnspecifiedError();
+    }
+    return ipmi::responseSuccess();
+}
+
 void register_netfn_chassis_functions()
 {
     createIdentifyTimer();
@@ -1961,6 +2006,12 @@
                           ipmi::chassis::cmdGetChassisCapabilities,
                           ipmi::Privilege::User, ipmiGetChassisCap);
 
+    // Set Front Panel Button Enables
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
+                          ipmi::chassis::cmdSetFrontPanelButtonEnables,
+                          ipmi::Privilege::Admin,
+                          ipmiSetFrontPanelButtonEnables);
+
     // Set Chassis Capabilities
     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
                           ipmi::chassis::cmdSetChassisCapabilities,