pseq: Add setPowerSupplyError D-Bus method

Add a setPowerSupplyError method to the org.openbmc.control.Power
D-Bus interface.  When a power supply error is detected which is severe
enough to cause a power good failure, that error should be used in
preference to the power good error. Add a D-Bus method to allow this to
be communicated between the applications.  The parameter passed should
be the power supply error to log, for example
"xyz.openbmc_project.Power.PowerSupply.Error.PSKillFault".

Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: I8500ace4638236dda2d7ff4361b61efa30a50ac1
diff --git a/phosphor-power-sequencer/src/power_interface.cpp b/phosphor-power-sequencer/src/power_interface.cpp
index 50f5911..d266ee1 100644
--- a/phosphor-power-sequencer/src/power_interface.cpp
+++ b/phosphor-power-sequencer/src/power_interface.cpp
@@ -151,10 +151,10 @@
 
             int timeout{};
             m.read(timeout);
-
-            auto pwrObj = static_cast<PowerInterface*>(context);
             log<level::INFO>(
                 fmt::format("callbackSetPgoodTimeout: {}", timeout).c_str());
+
+            auto pwrObj = static_cast<PowerInterface*>(context);
             pwrObj->setPgoodTimeout(timeout);
         }
         catch (const sdbusplus::exception_t& e)
@@ -223,10 +223,10 @@
                                         "org.openbmc.ControlPower.Error.Failed",
                                         "Invalid power state");
             }
-
-            auto pwrObj = static_cast<PowerInterface*>(context);
             log<level::INFO>(
                 fmt::format("callbackSetPowerState: {}", state).c_str());
+
+            auto pwrObj = static_cast<PowerInterface*>(context);
             pwrObj->setState(state);
 
             m.new_method_return().method_return();
@@ -246,6 +246,43 @@
     return 1;
 }
 
+int PowerInterface::callbackSetPowerSupplyError(sd_bus_message* msg,
+                                                void* context,
+                                                sd_bus_error* error)
+{
+    if (msg != nullptr && context != nullptr)
+    {
+        try
+        {
+            auto m = sdbusplus::message::message(msg);
+
+            std::string psError{};
+            m.read(psError);
+            log<level::INFO>(
+                fmt::format("callbackSetPowerSupplyError: {}", psError)
+                    .c_str());
+
+            auto pwrObj = static_cast<PowerInterface*>(context);
+            pwrObj->setPowerSupplyError(psError);
+
+            m.new_method_return().method_return();
+        }
+        catch (const sdbusplus::exception_t& e)
+        {
+            return sd_bus_error_set(error, e.name(), e.description());
+        }
+    }
+    else
+    {
+        // The message or context were null
+        log<level::ERR>(
+            "Unable to service setPowerSupplyError method callback");
+        return -1;
+    }
+
+    return 1;
+}
+
 void PowerInterface::emitPowerGoodSignal()
 {
     log<level::INFO>("emitPowerGoodSignal");
@@ -286,6 +323,9 @@
     sdbusplus::vtable::property("pgood_timeout", "i", callbackGetPgoodTimeout,
                                 callbackSetPgoodTimeout,
                                 sdbusplus::vtable::property_::emits_change),
+    // Method setPowerSupplyError takes a string parameter and returns void
+    sdbusplus::vtable::method("setPowerSupplyError", "s", "",
+                              callbackSetPowerSupplyError),
     sdbusplus::vtable::end()};
 
 } // namespace phosphor::power::sequencer