Add Get System Restart Cause command

This change overrides the Get System Restart Cause command to
use the RestartCause DBus property.

Tested:
ipmitool chassis restart_cause
System restart cause: power-up due to restore-previous power policy
ipmitool power cycle
Chassis Power Control: Cycle
ipmitool chassis restart_cause
System restart cause: chassis power control command

Change-Id: I2023f958bdc4d8abf18c25b701709cbd83c0b9b0
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/src/chassiscommands.cpp b/src/chassiscommands.cpp
index 9c37939..04035f0 100644
--- a/src/chassiscommands.cpp
+++ b/src/chassiscommands.cpp
@@ -475,6 +475,98 @@
         interruptButtonDisableAllow, sleepButtonDisableAllow);
 }
 
+static uint4_t getRestartCause(const std::string& cause)
+{
+    uint4_t restartCauseValue = 0;
+    if (cause == "xyz.openbmc_project.State.Host.RestartCause.Unknown")
+    {
+        restartCauseValue = 0x0;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand")
+    {
+        restartCauseValue = 0x1;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.ResetButton")
+    {
+        restartCauseValue = 0x2;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PowerButton")
+    {
+        restartCauseValue = 0x3;
+    }
+    else if (cause ==
+             "xyz.openbmc_project.State.Host.RestartCause.WatchdogTimer")
+    {
+        restartCauseValue = 0x4;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.OEM")
+    {
+        restartCauseValue = 0x5;
+    }
+    else if (cause ==
+             "xyz.openbmc_project.State.Host.RestartCause.PowerPolicyAlwaysOn")
+    {
+        restartCauseValue = 0x6;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause."
+                      "PowerPolicyPreviousState")
+    {
+        restartCauseValue = 0x7;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PEFReset")
+    {
+        restartCauseValue = 0x8;
+    }
+    else if (cause ==
+             "xyz.openbmc_project.State.Host.RestartCause.PEFPowerCycle")
+    {
+        restartCauseValue = 0x9;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.SoftReset")
+    {
+        restartCauseValue = 0xa;
+    }
+    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.RTCWakeup")
+    {
+        restartCauseValue = 0xb;
+    }
+    return restartCauseValue;
+}
+
+ipmi::RspType<uint4_t, // Restart Cause
+              uint4_t, // reserved
+              uint8_t  // channel number (not supported)
+              >
+    ipmiGetSystemRestartCause()
+{
+    constexpr const char* restartCausePath =
+        "/xyz/openbmc_project/control/host0/restart_cause";
+    constexpr const char* restartCauseIntf =
+        "xyz.openbmc_project.Common.RestartCause";
+    std::string restartCauseStr;
+    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
+
+    try
+    {
+        auto service =
+            ipmi::getService(*busp, restartCauseIntf, restartCausePath);
+
+        ipmi::Value result = ipmi::getDbusProperty(
+            *busp, service, restartCausePath, restartCauseIntf, "RestartCause");
+        restartCauseStr = std::get<std::string>(result);
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>("Failed to fetch RestartCause property",
+                        entry("ERROR=%s", e.what()),
+                        entry("PATH=%s", restartCausePath),
+                        entry("INTERFACE=%s", restartCauseIntf));
+        return ipmi::responseUnspecifiedError();
+    }
+
+    return ipmi::responseSuccess(getRestartCause(restartCauseStr), 0, 0);
+}
+
 ipmi::RspType<> ipmiSetFrontPanelButtonEnables(bool disablePowerButton,
                                                bool disableResetButton,
                                                bool disableInterruptButton,
@@ -520,6 +612,10 @@
     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
                           ipmi::chassis::cmdGetChassisStatus,
                           ipmi::Privilege::User, ipmiGetChassisStatus);
+    // <Get System Restart Cause>
+    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
+                          ipmi::chassis::cmdGetSystemRestartCause,
+                          ipmi::Privilege::User, ipmiGetSystemRestartCause);
     // <Set Front Panel Enables>
     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
                           ipmi::chassis::cmdSetFrontPanelButtonEnables,