Dbus Based Gpio Event monitoring

This change provide the implementation for D-bus based Gpio Event monitoring.
For the platform not having direct GPIO access can use dbus based event
monitor by configuring dbus names in Json file. x86-power-control will monitor
the property change from the given DbusName and take appropriate action

Updated parsing logic of reading config values from json.

TESTED:Tested and verified in Tiogapass and YosemteV2. The existing functionality
is not broken after adding the JSON parser implementation in Tiogapass.

Signed-off-by: Priyatharshan P <priyatharshanp@hcl.com>
Change-Id: I480c62eccebf6d0a3c4609afaf24d55265d99602
diff --git a/power-control-x86/src/power_control.cpp b/power-control-x86/src/power_control.cpp
index 2222735..5781d6a 100644
--- a/power-control-x86/src/power_control.cpp
+++ b/power-control-x86/src/power_control.cpp
@@ -39,19 +39,72 @@
 
 static std::string node = "0";
 
-static std::string powerOutName;
-static std::string powerOkName;
-static std::string resetOutName;
-static std::string nmiOutName;
-static std::string sioPwrGoodName;
-static std::string sioOnControlName;
-static std::string sioS5Name;
-static std::string postCompleteName;
-static std::string powerButtonName;
-static std::string resetButtonName;
-static std::string idButtonName;
-static std::string nmiButtonName;
+enum class DbusConfigType
+{
+    name = 1,
+    path,
+    interface,
+    property
+};
+boost::container::flat_map<DbusConfigType, std::string> dbusParams = {
+    {DbusConfigType::name, "DbusName"},
+    {DbusConfigType::path, "Path"},
+    {DbusConfigType::interface, "Interface"},
+    {DbusConfigType::property, "Property"}};
 
+enum class ConfigType
+{
+    GPIO = 1,
+    DBUS
+};
+
+struct ConfigData
+{
+    std::string name;
+    std::string lineName;
+    std::string dbusName;
+    std::string path;
+    std::string interface;
+    ConfigType type;
+};
+
+static ConfigData powerOutConfig;
+static ConfigData powerOkConfig;
+static ConfigData resetOutConfig;
+static ConfigData nmiOutConfig;
+static ConfigData sioPwrGoodConfig;
+static ConfigData sioOnControlConfig;
+static ConfigData sioS5Config;
+static ConfigData postCompleteConfig;
+static ConfigData powerButtonConfig;
+static ConfigData resetButtonConfig;
+static ConfigData idButtonConfig;
+static ConfigData nmiButtonConfig;
+// map for storing list of gpio parameters whose config are to be read from x86
+// power control json config
+boost::container::flat_map<std::string, ConfigData*> powerSignalMap = {
+    {"PowerOut", &powerOutConfig},
+    {"PowerOk", &powerOkConfig},
+    {"ResetOut", &resetOutConfig},
+    {"NMIOut", &nmiOutConfig},
+    {"SioPowerGood", &sioPwrGoodConfig},
+    {"SioOnControl", &sioOnControlConfig},
+    {"SIOS5", &sioS5Config},
+    {"PostComplete", &postCompleteConfig},
+    {"PowerButton", &powerButtonConfig},
+    {"ResetButton", &resetButtonConfig},
+    {"IdButton", &idButtonConfig},
+    {"NMIButton", &nmiButtonConfig}
+
+};
+
+static std::string hostDbusName = "xyz.openbmc_project.State.Host";
+static std::string chassisDbusName = "xyz.openbmc_project.State.Chassis";
+static std::string osDbusName = "xyz.openbmc_project.State.OperatingSystem";
+static std::string buttonDbusName = "xyz.openbmc_project.Chassis.Buttons";
+static std::string nmiDbusName = "xyz.openbmc_project.Control.Host.NMI";
+static std::string rstCauseDbusName =
+    "xyz.openbmc_project.Control.Host.RestartCause";
 static std::shared_ptr<sdbusplus::asio::dbus_interface> hostIface;
 static std::shared_ptr<sdbusplus::asio::dbus_interface> chassisIface;
 #ifdef CHASSIS_SYSTEM_RESET
@@ -69,15 +122,17 @@
 static gpiod::line resetButtonMask;
 static bool nmiButtonMasked = false;
 
-static int powerPulseTimeMs = 200;
-static int forceOffPulseTimeMs = 15000;
-static int resetPulseTimeMs = 500;
-static int powerCycleTimeMs = 5000;
-static int sioPowerGoodWatchdogTimeMs = 1000;
-static int psPowerOKWatchdogTimeMs = 8000;
-static int gracefulPowerOffTimeS = 5 * 60;
-static int warmResetCheckTimeMs = 500;
-static int powerOffSaveTimeMs = 7000;
+// This map contains all timer values that are to be read from json config
+boost::container::flat_map<std::string, int> TimerMap = {
+    {"powerPulseTimeMs", 200},
+    {"forceOffPulseTimeMs", 15000},
+    {"resetPulseTimeMs", 500},
+    {"powerCycleTimeMs", 5000},
+    {"sioPowerGoodWatchdogTimeMs", 1000},
+    {"psPowerOKWatchdogTimeMs", 8000},
+    {"gracefulPowerOffTimeS", (5 * 60)},
+    {"warmResetCheckTimeMs", 500},
+    {"powerOffSaveTimeMs", 7000}};
 
 const static std::filesystem::path powerControlDir = "/var/lib/power-control";
 const static constexpr std::string_view powerStateFile = "power-state";
@@ -453,7 +508,7 @@
 static void savePowerState(const PowerState state)
 {
     powerStateSaveTimer.expires_after(
-        std::chrono::milliseconds(powerOffSaveTimeMs));
+        std::chrono::milliseconds(TimerMap["powerOffSaveTimeMs"]));
     powerStateSaveTimer.async_wait([state](const boost::system::error_code ec) {
         if (ec)
         {
@@ -612,7 +667,7 @@
         "MESSAGE=PowerControl: system power good failed to assert (VR failure)",
         "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
         "OpenBMC.0.1.SystemPowerGoodFailed", "REDFISH_MESSAGE_ARGS=%d",
-        sioPowerGoodWatchdogTimeMs, NULL);
+        TimerMap["sioPowerGoodWatchdogTimeMs"], NULL);
 }
 
 static void psPowerOKFailedLog()
@@ -621,7 +676,7 @@
         "MESSAGE=PowerControl: power supply power good failed to assert",
         "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
         "OpenBMC.0.1.PowerSupplyPowerGoodFailed", "REDFISH_MESSAGE_ARGS=%d",
-        psPowerOKWatchdogTimeMs, NULL);
+        TimerMap["psPowerOKWatchdogTimeMs"], NULL);
 }
 
 static void powerRestorePolicyLog()
@@ -1089,12 +1144,12 @@
                               const int durationMs)
 {
     // If the requested GPIO is masked, use the mask line to set the output
-    if (powerButtonMask && name == power_control::powerOutName)
+    if (powerButtonMask && name == powerOutConfig.lineName)
     {
         return setMaskedGPIOOutputForMs(powerButtonMask, name, value,
                                         durationMs);
     }
-    if (resetButtonMask && name == power_control::resetOutName)
+    if (resetButtonMask && name == resetOutConfig.lineName)
     {
         return setMaskedGPIOOutputForMs(resetButtonMask, name, value,
                                         durationMs);
@@ -1131,18 +1186,20 @@
 
 static void powerOn()
 {
-    setGPIOOutputForMs(power_control::powerOutName, 0, powerPulseTimeMs);
+    setGPIOOutputForMs(powerOutConfig.lineName, 0,
+                       TimerMap["powerPulseTimeMs"]);
 }
 
 static void gracefulPowerOff()
 {
-    setGPIOOutputForMs(power_control::powerOutName, 0, powerPulseTimeMs);
+    setGPIOOutputForMs(powerOutConfig.lineName, 0,
+                       TimerMap["powerPulseTimeMs"]);
 }
 
 static void forcePowerOff()
 {
-    if (setGPIOOutputForMs(power_control::powerOutName, 0,
-                           forceOffPulseTimeMs) < 0)
+    if (setGPIOOutputForMs(powerOutConfig.lineName, 0,
+                           TimerMap["forceOffPulseTimeMs"]) < 0)
     {
         return;
     }
@@ -1183,7 +1240,8 @@
 
 static void reset()
 {
-    setGPIOOutputForMs(power_control::resetOutName, 0, resetPulseTimeMs);
+    setGPIOOutputForMs(resetOutConfig.lineName, 0,
+                       TimerMap["resetPulseTimeMs"]);
 }
 
 static void gracefulPowerOffTimerStart()
@@ -1191,7 +1249,7 @@
     phosphor::logging::log<phosphor::logging::level::INFO>(
         "Graceful power-off timer started");
     gracefulPowerOffTimer.expires_after(
-        std::chrono::seconds(gracefulPowerOffTimeS));
+        std::chrono::seconds(TimerMap["gracefulPowerOffTimeS"]));
     gracefulPowerOffTimer.async_wait([](const boost::system::error_code ec) {
         if (ec)
         {
@@ -1218,7 +1276,8 @@
 {
     phosphor::logging::log<phosphor::logging::level::INFO>(
         "Power-cycle timer started");
-    powerCycleTimer.expires_after(std::chrono::milliseconds(powerCycleTimeMs));
+    powerCycleTimer.expires_after(
+        std::chrono::milliseconds(TimerMap["powerCycleTimeMs"]));
     powerCycleTimer.async_wait([](const boost::system::error_code ec) {
         if (ec)
         {
@@ -1246,7 +1305,7 @@
     phosphor::logging::log<phosphor::logging::level::INFO>(
         "power supply power OK watchdog timer started");
     psPowerOKWatchdogTimer.expires_after(
-        std::chrono::milliseconds(psPowerOKWatchdogTimeMs));
+        std::chrono::milliseconds(TimerMap["psPowerOKWatchdogTimeMs"]));
     psPowerOKWatchdogTimer.async_wait([](const boost::system::error_code ec) {
         if (ec)
         {
@@ -1275,7 +1334,7 @@
     phosphor::logging::log<phosphor::logging::level::INFO>(
         "Warm reset check timer started");
     warmResetCheckTimer.expires_after(
-        std::chrono::milliseconds(warmResetCheckTimeMs));
+        std::chrono::milliseconds(TimerMap["warmResetCheckTimeMs"]));
     warmResetCheckTimer.async_wait([](const boost::system::error_code ec) {
         if (ec)
         {
@@ -1464,7 +1523,7 @@
     phosphor::logging::log<phosphor::logging::level::INFO>(
         "SIO power good watchdog timer started");
     sioPowerGoodWatchdogTimer.expires_after(
-        std::chrono::milliseconds(sioPowerGoodWatchdogTimeMs));
+        std::chrono::milliseconds(TimerMap["sioPowerGoodWatchdogTimeMs"]));
     sioPowerGoodWatchdogTimer.async_wait(
         [](const boost::system::error_code ec) {
             if (ec)
@@ -2027,13 +2086,14 @@
 
     phosphor::logging::log<phosphor::logging::level::INFO>("NMI out action");
     nmiOutLine.set_value(value);
-    std::string logMsg = nmiOutName + " set to " + std::to_string(value);
+    std::string logMsg =
+        nmiOutConfig.lineName + " set to " + std::to_string(value);
     phosphor::logging::log<phosphor::logging::level::INFO>(logMsg.c_str());
     gpioAssertTimer.expires_after(std::chrono::milliseconds(nmiOutPulseTimeMs));
     gpioAssertTimer.async_wait([](const boost::system::error_code ec) {
         // restore the NMI_OUT GPIO line back to the opposite value
         nmiOutLine.set_value(!value);
-        std::string logMsg = nmiOutName + " released";
+        std::string logMsg = nmiOutConfig.lineName + " released";
         phosphor::logging::log<phosphor::logging::level::INFO>(logMsg.c_str());
         if (ec)
         {
@@ -2041,8 +2101,8 @@
             // completion.
             if (ec != boost::asio::error::operation_aborted)
             {
-                std::string errMsg =
-                    nmiOutName + " async_wait failed: " + ec.message();
+                std::string errMsg = nmiOutConfig.lineName +
+                                     " async_wait failed: " + ec.message();
                 phosphor::logging::log<phosphor::logging::level::ERR>(
                     errMsg.c_str());
             }
@@ -2281,131 +2341,648 @@
             "loadConfigValues : Cannot open config path");
         return -1;
     }
-    auto data = nlohmann::json::parse(configFile, nullptr);
+    auto jsonData = nlohmann::json::parse(configFile, nullptr);
 
-    if (data.is_discarded())
+    if (jsonData.is_discarded())
     {
         phosphor::logging::log<phosphor::logging::level::ERR>(
             "Power config readings JSON parser failure");
         return -1;
     }
-    auto gpios = data["gpio_configs"];
-    auto timers = data["timing_configs"];
+    auto gpios = jsonData["gpio_configs"];
+    auto timers = jsonData["timing_configs"];
 
-    if (gpios.contains("IdButton"))
+    ConfigData* tempGpioData;
+
+    for (nlohmann::json& gpioConfig : gpios)
     {
-        idButtonName = gpios["IdButton"];
+        if (!gpioConfig.contains("Name"))
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "The 'Name' field must be defined in Json file");
+            return -1;
+        }
+
+        // Iterate through the powersignal map to check if the gpio json config
+        // entry is valid
+        std::string gpioName = gpioConfig["Name"];
+        auto signalMapIter = powerSignalMap.find(gpioName);
+        if (signalMapIter == powerSignalMap.end())
+        {
+            std::string errMsg = "Undefined Name  : " + gpioName;
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                errMsg.c_str());
+            return -1;
+        }
+
+        // assign the power signal name to the corresponding structure reference
+        // from map then fillup the structure with coressponding json config
+        // value
+        tempGpioData = signalMapIter->second;
+        tempGpioData->name = gpioName;
+
+        if (!gpioConfig.contains("Type"))
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "The \'Type\' field must be defined in Json file");
+            return -1;
+        }
+
+        std::string signalType = gpioConfig["Type"];
+        if (signalType == "GPIO")
+        {
+            tempGpioData->type = ConfigType::GPIO;
+        }
+        else if (signalType == "DBUS")
+        {
+            tempGpioData->type = ConfigType::DBUS;
+        }
+        else
+        {
+            std::string errMsg = "Undefined Type : " + signalType;
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                errMsg.c_str());
+            return -1;
+        }
+
+        if (tempGpioData->type == ConfigType::GPIO)
+        {
+            if (gpioConfig.contains("LineName"))
+            {
+                tempGpioData->lineName = gpioConfig["LineName"];
+            }
+            else
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "The \'LineName\' field must be defined for GPIO "
+                    "configuration");
+                return -1;
+            }
+        }
+        else
+        {
+            // if dbus based gpio config is defined read and update the dbus
+            // params corresponding to the gpio config instance
+            for (auto& [key, dbusParamName] : dbusParams)
+            {
+                if (!gpios.contains(dbusParamName))
+                {
+                    std::string errMsg =
+                        "The " + dbusParamName +
+                        "field must be defined for Dbus configuration ";
+                    phosphor::logging::log<phosphor::logging::level::ERR>(
+                        errMsg.c_str());
+                    return -1;
+                }
+            }
+            tempGpioData->dbusName = gpios[dbusParams[DbusConfigType::name]];
+            tempGpioData->path = gpios[dbusParams[DbusConfigType::path]];
+            tempGpioData->interface =
+                gpios[dbusParams[DbusConfigType::interface]];
+            tempGpioData->lineName =
+                gpios[dbusParams[DbusConfigType::property]];
+        }
     }
 
-    if (gpios.contains("NMIButton"))
+    // read and store the timer values from json config to Timer Map
+    for (auto& [key, timerValue] : TimerMap)
     {
-        nmiButtonName = gpios["NMIButton"];
+        if (timers.contains(key.c_str()))
+        {
+            timerValue = timers[key.c_str()];
+        }
     }
 
-    if (gpios.contains("NMIOut"))
-    {
-        nmiOutName = gpios["NMIOut"];
-    }
-
-    if (gpios.contains("PostComplete"))
-    {
-        postCompleteName = gpios["PostComplete"];
-    }
-
-    if (gpios.contains("PwrButton"))
-    {
-        powerButtonName = gpios["PwrButton"];
-    }
-
-    if (gpios.contains("PwrOK"))
-    {
-        powerOkName = gpios["PwrOK"];
-    }
-
-    if (gpios.contains("PwrOut"))
-    {
-        powerOutName = gpios["PwrOut"];
-    }
-
-    if (gpios.contains("RstButton"))
-    {
-        resetButtonName = gpios["RstButton"];
-    }
-
-    if (gpios.contains("RstOut"))
-    {
-        resetOutName = gpios["RstOut"];
-    }
-
-    if (gpios.contains("SIOOnCtl"))
-    {
-        sioOnControlName = gpios["SIOOnCtl"];
-    }
-
-    if (gpios.contains("SIOPwrGd"))
-    {
-        sioPwrGoodName = gpios["SIOPwrGd"];
-    }
-
-    if (gpios.contains("SIOS5"))
-    {
-        sioS5Name = gpios["SIOS5"];
-    }
-
-    if (timers.contains("PowerPulseMs"))
-    {
-        powerPulseTimeMs = timers["PowerPulseMs"];
-    }
-
-    if (timers.contains("ForceOffPulseMs"))
-    {
-        forceOffPulseTimeMs = timers["ForceOffPulseMs"];
-    }
-
-    if (timers.contains("ResetPulseMs"))
-    {
-        resetPulseTimeMs = timers["ResetPulseMs"];
-    }
-
-    if (timers.contains("PowerCycleMs"))
-    {
-        powerCycleTimeMs = timers["PowerCycleMs"];
-    }
-
-    if (timers.contains("SioPowerGoodWatchdogMs"))
-    {
-        sioPowerGoodWatchdogTimeMs = timers["SioPowerGoodWatchdogMs"];
-    }
-
-    if (timers.contains("PsPowerOKWatchdogMs"))
-    {
-        psPowerOKWatchdogTimeMs = timers["PsPowerOKWatchdogMs"];
-    }
-
-    if (timers.contains("GracefulPowerOffS"))
-    {
-        gracefulPowerOffTimeS = timers["GracefulPowerOffS"];
-    }
-
-    if (timers.contains("WarmResetCheckMs"))
-    {
-        warmResetCheckTimeMs = timers["WarmResetCheckMs"];
-    }
-
-    if (timers.contains("PowerOffSaveMs"))
-    {
-        powerOffSaveTimeMs = timers["PowerOffSaveMs"];
-    }
     return 0;
 }
+inline static sdbusplus::bus::match::match powerButtonEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
 
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() || event != powerButtonConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : powerButtonConfig");
+            return;
+        }
+
+        if (value == false)
+        {
+            powerButtonPressLog();
+            powerButtonIface->set_property("ButtonPressed", true);
+            if (!powerButtonMask)
+            {
+                sendPowerControlEvent(Event::powerButtonPressed);
+                addRestartCause(RestartCause::powerButton);
+            }
+            else
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "power button press masked\n");
+            }
+        }
+        else
+        {
+            powerButtonIface->set_property("ButtonPressed", false);
+        }
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            powerButtonConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match resetButtonEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() || event != resetButtonConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : resetButtonConfig");
+            return;
+        }
+
+        if (value == false)
+        {
+            resetButtonPressLog();
+            resetButtonIface->set_property("ButtonPressed", true);
+            if (!resetButtonMask)
+            {
+                sendPowerControlEvent(Event::resetButtonPressed);
+                addRestartCause(RestartCause::resetButton);
+            }
+            else
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "reset button press masked");
+            }
+        }
+        else
+        {
+            resetButtonIface->set_property("ButtonPressed", false);
+        }
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            resetButtonConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match powerOkEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() || event != powerOkConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : powerOkConfig");
+            return;
+        }
+
+        Event powerControlEvent =
+            value ? Event::psPowerOKAssert : Event::psPowerOKDeAssert;
+        sendPowerControlEvent(powerControlEvent);
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            powerOkConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match sioPwrGoodEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() || event != sioPwrGoodConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : sioPwrGoodConfig");
+            return;
+        }
+
+        Event powerControlEvent =
+            value ? Event::sioPowerGoodAssert : Event::sioPowerGoodDeAssert;
+
+        sendPowerControlEvent(powerControlEvent);
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            sioPwrGoodConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match sioOnControlEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() || event != sioOnControlConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : sioOnControlConfig");
+            return;
+        }
+
+        std::string errMsg =
+            "SIO_ONCONTROL value changed : " + std::to_string(value);
+        phosphor::logging::log<phosphor::logging::level::ERR>(errMsg.c_str());
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            sioOnControlConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match sioS5EventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() || event != sioS5Config.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : sioS5Config");
+            return;
+        }
+
+        Event powerControlEvent =
+            value ? Event::sioS5DeAssert : Event::sioS5Assert;
+        sendPowerControlEvent(powerControlEvent);
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            sioS5Config.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match nmiButtonEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+            if (event.empty() || event != nmiButtonConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : nmiButtonConfig");
+            return;
+        }
+
+        if (value)
+        {
+            nmiButtonIface->set_property("ButtonPressed", false);
+        }
+        else
+        {
+            nmiButtonPressLog();
+            nmiButtonIface->set_property("ButtonPressed", true);
+            if (nmiButtonMasked)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "NMI button press masked");
+            }
+            else
+            {
+                setNmiSource();
+            }
+        }
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            nmiButtonConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match idButtonEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+
+        try
+        {
+
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() | event != idButtonConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : idButtonConfig");
+            return;
+        }
+
+        if (value)
+        {
+            idButtonIface->set_property("ButtonPressed", false);
+        }
+        else
+        {
+            idButtonIface->set_property("ButtonPressed", true);
+        }
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='" +
+            idButtonConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+inline static sdbusplus::bus::match::match postCompleteEventMonitor()
+{
+    auto pulseEventMatcherCallback = [](sdbusplus::message::message& msg) {
+        bool value = false;
+        std::string thresholdInterface;
+        std::string event;
+        boost::container::flat_map<std::string, std::variant<bool>>
+            propertiesChanged;
+        try
+        {
+
+            msg.read(thresholdInterface, propertiesChanged);
+
+            if (propertiesChanged.empty())
+            {
+                return;
+            }
+            event = propertiesChanged.begin()->first;
+
+            if (event.empty() | event != postCompleteConfig.lineName)
+            {
+                return;
+            }
+
+            value = std::get<bool>(propertiesChanged.begin()->second);
+        }
+        catch (std::exception& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "exception during reading dbus property : postCompleteConfig");
+            return;
+        }
+
+        if (value)
+        {
+            sendPowerControlEvent(Event::postCompleteDeAssert);
+            osIface->set_property("OperatingSystemState",
+                                  std::string("Inactive"));
+        }
+        else
+        {
+            sendPowerControlEvent(Event::postCompleteAssert);
+            osIface->set_property("OperatingSystemState",
+                                  std::string("Standby"));
+        }
+    };
+
+    sdbusplus::bus::match::match pulseEventMatcher(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',path='" + postCompleteConfig.path +
+            "',interface='org.freedesktop.DBus.Properties',member='"
+            "PropertiesChanged',arg0='" +
+            postCompleteConfig.dbusName + "'",
+        std::move(pulseEventMatcherCallback));
+
+    return pulseEventMatcher;
+}
+
+int getProperty(ConfigData& configData)
+{
+    auto method = conn->new_method_call(
+        configData.dbusName.c_str(), configData.path.c_str(),
+        "org.freedesktop.DBus.Properties", "Get");
+    method.append(configData.interface.c_str(), configData.lineName.c_str());
+
+    auto reply = conn->call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error reading from Bus");
+        return -1;
+    }
+    std::variant<int> resp;
+    reply.read(resp);
+    auto respValue = std::get_if<int>(&resp);
+    if (!respValue)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error reading response");
+        return -1;
+    }
+    return (*respValue);
+}
 } // namespace power_control
 
 int main(int argc, char* argv[])
 {
     using namespace power_control;
-    phosphor::logging::log<phosphor::logging::level::INFO>(
-        "Start Chassis power control service...");
+
+    if (argc > 1)
+    {
+        node = argv[1];
+    }
+    std::string infoMsg =
+        "Start Chassis power control service for host : " + node;
+    phosphor::logging::log<phosphor::logging::level::INFO>(infoMsg.c_str());
+
     conn = std::make_shared<sdbusplus::asio::connection>(io);
 
     // Load GPIO's through json config file
@@ -2415,15 +2992,23 @@
         phosphor::logging::log<phosphor::logging::level::ERR>(errMsg.c_str());
     }
 
-    // Request all the dbus names
-    conn->request_name("xyz.openbmc_project.State.Host");
-    conn->request_name("xyz.openbmc_project.State.Chassis");
-    conn->request_name("xyz.openbmc_project.State.OperatingSystem");
-    conn->request_name("xyz.openbmc_project.Chassis.Buttons");
-    conn->request_name("xyz.openbmc_project.Control.Host.NMI");
-    conn->request_name("xyz.openbmc_project.Control.Host.RestartCause");
+    hostDbusName = "xyz.openbmc_project.State.Host" + node;
+    chassisDbusName = "xyz.openbmc_project.State.Chassis" + node;
+    osDbusName = "xyz.openbmc_project.State.OperatingSystem" + node;
+    buttonDbusName = "xyz.openbmc_project.Chassis.Buttons" + node;
+    nmiDbusName = "xyz.openbmc_project.Control.Host.NMI" + node;
+    rstCauseDbusName = "xyz.openbmc_project.Control.Host.RestartCause" + node;
 
-    if (sioPwrGoodName.empty() || sioOnControlName.empty() || sioS5Name.empty())
+    // Request all the dbus names
+    conn->request_name(hostDbusName.c_str());
+    conn->request_name(chassisDbusName.c_str());
+    conn->request_name(osDbusName.c_str());
+    conn->request_name(buttonDbusName.c_str());
+    conn->request_name(nmiDbusName.c_str());
+    conn->request_name(rstCauseDbusName.c_str());
+
+    if (sioPwrGoodConfig.lineName.empty() ||
+        sioOnControlConfig.lineName.empty() || sioS5Config.lineName.empty())
     {
         sioEnabled = false;
         phosphor::logging::log<phosphor::logging::level::INFO>(
@@ -2431,14 +3016,20 @@
     }
 
     // Request PS_PWROK GPIO events
-    if (!powerOkName.empty())
+    if (powerOkConfig.type == ConfigType::GPIO)
     {
-        if (!requestGPIOEvents(powerOkName, psPowerOKHandler, psPowerOKLine,
-                               psPowerOKEvent))
+        if (!requestGPIOEvents(powerOkConfig.lineName, psPowerOKHandler,
+                               psPowerOKLine, psPowerOKEvent))
         {
             return -1;
         }
     }
+    else if (powerOkConfig.type == ConfigType::DBUS)
+    {
+
+        static sdbusplus::bus::match::match powerOkEventMonitor =
+            power_control::powerOkEventMonitor();
+    }
     else
     {
         phosphor::logging::log<phosphor::logging::level::ERR>(
@@ -2449,69 +3040,130 @@
     if (sioEnabled == true)
     {
         // Request SIO_POWER_GOOD GPIO events
-        if (!requestGPIOEvents(sioPwrGoodName, sioPowerGoodHandler,
-                               sioPowerGoodLine, sioPowerGoodEvent))
+        if (sioPwrGoodConfig.type == ConfigType::GPIO)
         {
+            if (!requestGPIOEvents(sioPwrGoodConfig.lineName,
+                                   sioPowerGoodHandler, sioPowerGoodLine,
+                                   sioPowerGoodEvent))
+            {
+                return -1;
+            }
+        }
+        else if (sioPwrGoodConfig.type == ConfigType::DBUS)
+        {
+            static sdbusplus::bus::match::match sioPwrGoodEventMonitor =
+                power_control::sioPwrGoodEventMonitor();
+        }
+        else
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "sioPwrGood name should be configured from json config file");
             return -1;
         }
 
         // Request SIO_ONCONTROL GPIO events
-        if (!requestGPIOEvents(sioOnControlName, sioOnControlHandler,
-                               sioOnControlLine, sioOnControlEvent))
+        if (sioOnControlConfig.type == ConfigType::GPIO)
         {
+            if (!requestGPIOEvents(sioOnControlConfig.lineName,
+                                   sioOnControlHandler, sioOnControlLine,
+                                   sioOnControlEvent))
+            {
+                return -1;
+            }
+        }
+        else if (sioOnControlConfig.type == ConfigType::DBUS)
+        {
+            static sdbusplus::bus::match::match sioOnControlEventMonitor =
+                power_control::sioOnControlEventMonitor();
+        }
+        else
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "sioOnControl name should be configured from json"
+                "config file\n");
             return -1;
         }
 
         // Request SIO_S5 GPIO events
-        if (!requestGPIOEvents(sioS5Name, sioS5Handler, sioS5Line, sioS5Event))
+        if (sioS5Config.type == ConfigType::GPIO)
         {
+            if (!requestGPIOEvents(sioS5Config.lineName, sioS5Handler,
+                                   sioS5Line, sioS5Event))
+            {
+                return -1;
+            }
+        }
+        else if (sioS5Config.type == ConfigType::DBUS)
+        {
+            static sdbusplus::bus::match::match sioS5EventMonitor =
+                power_control::sioS5EventMonitor();
+        }
+        else
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "sioS5 name should be configured from json config file");
             return -1;
         }
     }
 
     // Request POWER_BUTTON GPIO events
-    if (!powerButtonName.empty())
+    if (powerButtonConfig.type == ConfigType::GPIO)
     {
-        if (!requestGPIOEvents(powerButtonName, powerButtonHandler,
+        if (!requestGPIOEvents(powerButtonConfig.lineName, powerButtonHandler,
                                powerButtonLine, powerButtonEvent))
         {
             return -1;
         }
     }
-    else
+    else if (powerButtonConfig.type == ConfigType::DBUS)
     {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "powerButton name should be configured from json config file");
-        return -1;
+        static sdbusplus::bus::match::match powerButtonEventMonitor =
+            power_control::powerButtonEventMonitor();
     }
 
     // Request RESET_BUTTON GPIO events
-    if (!resetButtonName.empty())
+    if (resetButtonConfig.type == ConfigType::GPIO)
     {
-        if (!requestGPIOEvents(resetButtonName, resetButtonHandler,
+        if (!requestGPIOEvents(resetButtonConfig.lineName, resetButtonHandler,
                                resetButtonLine, resetButtonEvent))
         {
             return -1;
         }
     }
-    else
+    else if (resetButtonConfig.type == ConfigType::DBUS)
     {
-        phosphor::logging::log<phosphor::logging::level::INFO>(
-            "ResetButton not defined...");
+        static sdbusplus::bus::match::match resetButtonEventMonitor =
+            power_control::resetButtonEventMonitor();
     }
 
     // Request NMI_BUTTON GPIO events
-    if (!nmiButtonName.empty())
+    if (nmiButtonConfig.type == ConfigType::GPIO)
     {
-        requestGPIOEvents(nmiButtonName, nmiButtonHandler, nmiButtonLine,
-                          nmiButtonEvent);
+        if (!nmiButtonConfig.lineName.empty())
+        {
+            requestGPIOEvents(nmiButtonConfig.lineName, nmiButtonHandler,
+                              nmiButtonLine, nmiButtonEvent);
+        }
+    }
+    else if (nmiButtonConfig.type == ConfigType::DBUS)
+    {
+        static sdbusplus::bus::match::match nmiButtonEventMonitor =
+            power_control::nmiButtonEventMonitor();
     }
 
     // Request ID_BUTTON GPIO events
-    if (!idButtonName.empty())
+    if (idButtonConfig.type == ConfigType::GPIO)
     {
-        requestGPIOEvents(idButtonName, idButtonHandler, idButtonLine,
-                          idButtonEvent);
+        if (!idButtonConfig.lineName.empty())
+        {
+            requestGPIOEvents(idButtonConfig.lineName, idButtonHandler,
+                              idButtonLine, idButtonEvent);
+        }
+    }
+    else if (idButtonConfig.type == ConfigType::DBUS)
+    {
+        static sdbusplus::bus::match::match idButtonEventMonitor =
+            power_control::idButtonEventMonitor();
     }
 
 #ifdef USE_PLT_RST
@@ -2523,14 +3175,19 @@
 #endif
 
     // Request POST_COMPLETE GPIO events
-    if (!postCompleteName.empty())
+    if (postCompleteConfig.type == ConfigType::GPIO)
     {
-        if (!requestGPIOEvents(postCompleteName, postCompleteHandler,
+        if (!requestGPIOEvents(postCompleteConfig.lineName, postCompleteHandler,
                                postCompleteLine, postCompleteEvent))
         {
             return -1;
         }
     }
+    else if (postCompleteConfig.type == ConfigType::DBUS)
+    {
+        static sdbusplus::bus::match::match postCompleteEventMonitor =
+            power_control::postCompleteEventMonitor();
+    }
     else
     {
         phosphor::logging::log<phosphor::logging::level::ERR>(
@@ -2539,17 +3196,38 @@
     }
 
     // initialize NMI_OUT GPIO.
-    setGPIOOutput(nmiOutName, 0, nmiOutLine);
+    if (!nmiOutConfig.lineName.empty())
+    {
+        setGPIOOutput(nmiOutConfig.lineName, 0, nmiOutLine);
+    }
 
     // Initialize POWER_OUT and RESET_OUT GPIO.
     gpiod::line line;
-    if (!setGPIOOutput(powerOutName, 1, line))
+    if (!powerOutConfig.lineName.empty())
     {
+        if (!setGPIOOutput(powerOutConfig.lineName, 1, line))
+        {
+            return -1;
+        }
+    }
+    else
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "powerOut name should be configured from json config file");
         return -1;
     }
 
-    if (!setGPIOOutput(resetOutName, 1, line))
+    if (!resetOutConfig.lineName.empty())
     {
+        if (!setGPIOOutput(resetOutConfig.lineName, 1, line))
+        {
+            return -1;
+        }
+    }
+    else
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ResetOut name should be configured from json config file");
         return -1;
     }
 
@@ -2559,9 +3237,20 @@
     // Initialize the power state
     powerState = PowerState::off;
     // Check power good
-    if (psPowerOKLine.get_value() > 0)
+
+    if (powerOkConfig.type == ConfigType::GPIO)
     {
-        powerState = PowerState::on;
+        if (psPowerOKLine.get_value() > 0)
+        {
+            powerState = PowerState::on;
+        }
+    }
+    else
+    {
+        if (getProperty(powerOkConfig))
+        {
+            powerState = PowerState::on;
+        }
     }
 
     // Initialize the power state storage
@@ -2585,8 +3274,9 @@
         sdbusplus::asio::object_server(conn);
 
     // Power Control Interface
-    hostIface = hostServer.add_interface("/xyz/openbmc_project/state/host0",
-                                         "xyz.openbmc_project.State.Host");
+    hostIface =
+        hostServer.add_interface("/xyz/openbmc_project/state/host" + node,
+                                 "xyz.openbmc_project.State.Host");
 
     // Interface for IPMI/Redfish initiated host state transitions
     hostIface->register_property(
@@ -2698,7 +3388,7 @@
 
     // Chassis Control Interface
     chassisIface =
-        chassisServer.add_interface("/xyz/openbmc_project/state/chassis0",
+        chassisServer.add_interface("/xyz/openbmc_project/state/chassis" + node,
                                     "xyz.openbmc_project.State.Chassis");
 
     chassisIface->register_property(
@@ -2780,51 +3470,66 @@
     sdbusplus::asio::object_server buttonsServer =
         sdbusplus::asio::object_server(conn);
 
-    // Power Button Interface
-    powerButtonIface = buttonsServer.add_interface(
-        "/xyz/openbmc_project/chassis/buttons/power",
-        "xyz.openbmc_project.Chassis.Buttons");
-
-    powerButtonIface->register_property(
-        "ButtonMasked", false, [](const bool requested, bool& current) {
-            if (requested)
-            {
-                if (powerButtonMask)
-                {
-                    return 1;
-                }
-                if (!setGPIOOutput(powerOutName, 1, powerButtonMask))
-                {
-                    throw std::runtime_error("Failed to request GPIO");
-                    return 0;
-                }
-                phosphor::logging::log<phosphor::logging::level::INFO>(
-                    "Power Button Masked.");
-            }
-            else
-            {
-                if (!powerButtonMask)
-                {
-                    return 1;
-                }
-                phosphor::logging::log<phosphor::logging::level::INFO>(
-                    "Power Button Un-masked");
-                powerButtonMask.reset();
-            }
-            // Update the mask setting
-            current = requested;
-            return 1;
-        });
-
-    // Check power button state
-    bool powerButtonPressed = powerButtonLine.get_value() == 0;
-    powerButtonIface->register_property("ButtonPressed", powerButtonPressed);
-
-    powerButtonIface->initialize();
-
-    // Reset Button Interface
-    if (!resetButtonName.empty())
+    if (!powerButtonConfig.lineName.empty())
     {
+        // Power Button Interface
+        power_control::powerButtonIface = buttonsServer.add_interface(
+            "/xyz/openbmc_project/chassis/buttons/power",
+            "xyz.openbmc_project.Chassis.Buttons");
+
+        powerButtonIface->register_property(
+            "ButtonMasked", false, [](const bool requested, bool& current) {
+                if (requested)
+                {
+                    if (powerButtonMask)
+                    {
+                        return 1;
+                    }
+                    if (!setGPIOOutput(powerOutConfig.lineName, 1,
+                                       powerButtonMask))
+                    {
+                        throw std::runtime_error("Failed to request GPIO");
+                        return 0;
+                    }
+                    phosphor::logging::log<phosphor::logging::level::INFO>(
+                        "Power Button Masked.");
+                }
+                else
+                {
+                    if (!powerButtonMask)
+                    {
+                        return 1;
+                    }
+                    phosphor::logging::log<phosphor::logging::level::INFO>(
+                        "Power Button Un-masked");
+                    powerButtonMask.reset();
+                }
+                // Update the mask setting
+                current = requested;
+                return 1;
+            });
+
+        // Check power button state
+        bool powerButtonPressed;
+        if (powerButtonConfig.type == ConfigType::GPIO)
+        {
+            powerButtonPressed = powerButtonLine.get_value() == 0;
+        }
+        else
+        {
+            powerButtonPressed = getProperty(powerButtonConfig) == 0;
+        }
+
+        powerButtonIface->register_property("ButtonPressed",
+                                            powerButtonPressed);
+
+        powerButtonIface->initialize();
+    }
+
+    if (!resetButtonConfig.lineName.empty())
+    {
+        // Reset Button Interface
+
         resetButtonIface = buttonsServer.add_interface(
             "/xyz/openbmc_project/chassis/buttons/reset",
             "xyz.openbmc_project.Chassis.Buttons");
@@ -2837,7 +3542,8 @@
                     {
                         return 1;
                     }
-                    if (!setGPIOOutput(resetOutName, 1, resetButtonMask))
+                    if (!setGPIOOutput(resetOutConfig.lineName, 1,
+                                       resetButtonMask))
                     {
                         throw std::runtime_error("Failed to request GPIO");
                         return 0;
@@ -2861,7 +3567,16 @@
             });
 
         // Check reset button state
-        bool resetButtonPressed = resetButtonLine.get_value() == 0;
+        bool resetButtonPressed;
+        if (resetButtonConfig.type == ConfigType::GPIO)
+        {
+            resetButtonPressed = resetButtonLine.get_value() == 0;
+        }
+        else
+        {
+            resetButtonPressed = getProperty(resetButtonConfig) == 0;
+        }
+
         resetButtonIface->register_property("ButtonPressed",
                                             resetButtonPressed);
 
@@ -2900,7 +3615,16 @@
             });
 
         // Check NMI button state
-        bool nmiButtonPressed = nmiButtonLine.get_value() == 0;
+        bool nmiButtonPressed;
+        if (nmiButtonConfig.type == ConfigType::GPIO)
+        {
+            nmiButtonPressed = nmiButtonLine.get_value() == 0;
+        }
+        else
+        {
+            nmiButtonPressed = getProperty(nmiButtonConfig) == 0;
+        }
+
         nmiButtonIface->register_property("ButtonPressed", nmiButtonPressed);
 
         nmiButtonIface->initialize();
@@ -2913,9 +3637,9 @@
             sdbusplus::asio::object_server(conn);
 
         // NMI out Interface
-        nmiOutIface =
-            nmiOutServer.add_interface("/xyz/openbmc_project/control/host0/nmi",
-                                       "xyz.openbmc_project.Control.Host.NMI");
+        nmiOutIface = nmiOutServer.add_interface(
+            "/xyz/openbmc_project/control/host" + node + "/nmi",
+            "xyz.openbmc_project.Control.Host.NMI");
         nmiOutIface->register_method("NMI", nmiReset);
         nmiOutIface->initialize();
     }
@@ -2928,7 +3652,16 @@
             "xyz.openbmc_project.Chassis.Buttons");
 
         // Check ID button state
-        bool idButtonPressed = idButtonLine.get_value() == 0;
+        bool idButtonPressed;
+        if (idButtonConfig.type == ConfigType::GPIO)
+        {
+            idButtonPressed = idButtonLine.get_value() == 0;
+        }
+        else
+        {
+            idButtonPressed = getProperty(idButtonConfig) == 0;
+        }
+
         idButtonIface->register_property("ButtonPressed", idButtonPressed);
 
         idButtonIface->initialize();
@@ -2946,8 +3679,15 @@
     // Get the initial OS state based on POST complete
     //      0: Asserted, OS state is "Standby" (ready to boot)
     //      1: De-Asserted, OS state is "Inactive"
-    std::string osState =
-        postCompleteLine.get_value() > 0 ? "Inactive" : "Standby";
+    std::string osState;
+    if (postCompleteConfig.type == ConfigType::GPIO)
+    {
+        osState = postCompleteLine.get_value() > 0 ? "Inactive" : "Standby";
+    }
+    else
+    {
+        osState = getProperty(postCompleteConfig) > 0 ? "Inactive" : "Standby";
+    }
 
     osIface->register_property("OperatingSystemState", std::string(osState));