Implement NMI command in Chassis Control command.

Set NMI (Diagnostic Interrupt) signal source to Chassis command.
Please refer ipmi spec 1.3 table 1 for details.
Set Enabled property to inform NMI source handling to
trigger a NMI_OUT BSOD.

Tested:
NMI is actived(host is hang) due to NMI command
ipmitool chassis power diag

Change-Id: I8066aa19ba1f5a81897857de2a5fe551876101b3
Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
diff --git a/chassishandler.cpp b/chassishandler.cpp
index 305897b..053f29a 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -767,6 +767,38 @@
     return rc;
 }
 
+//------------------------------------------
+// Set Enabled property to inform NMI source
+// handling to trigger a NMI_OUT BSOD.
+//------------------------------------------
+int setNmiProperty(const bool value)
+{
+    constexpr const char* nmiSourceObjPath =
+        "/xyz/openbmc_project/Chassis/Control/NMISource";
+    constexpr const char* nmiSourceIntf =
+        "xyz.openbmc_project.Chassis.Control.NMISource";
+    std::string bmcSourceSignal = "xyz.openbmc_project.Chassis.Control."
+                                  "NMISource.BMCSourceSignal.ChassisCmd";
+    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
+
+    try
+    {
+        auto service = ipmi::getService(*busp, nmiSourceIntf, nmiSourceObjPath);
+        ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
+                              "BMCSource", bmcSourceSignal);
+        ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
+                              "Enabled", value);
+    }
+    catch (std::exception& e)
+    {
+        log<level::ERR>("Failed to trigger NMI_OUT",
+                        entry("EXCEPTION=%s", e.what()));
+        return -1;
+    }
+
+    return 0;
+}
+
 namespace power_policy
 {
 
@@ -1172,6 +1204,10 @@
             rc = initiate_state_transition(State::Host::Transition::Off);
             break;
 
+        case CMD_PULSE_DIAGNOSTIC_INTR:
+            rc = setNmiProperty(true);
+            break;
+
         default:
         {
             log<level::ERR>("Invalid Chassis Control command",