summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control/0004-Protect-POST-Complete-GPIO-read.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control/0004-Protect-POST-Complete-GPIO-read.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control/0004-Protect-POST-Complete-GPIO-read.patch219
1 files changed, 219 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control/0004-Protect-POST-Complete-GPIO-read.patch b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control/0004-Protect-POST-Complete-GPIO-read.patch
new file mode 100644
index 000000000..8da9660ef
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control/0004-Protect-POST-Complete-GPIO-read.patch
@@ -0,0 +1,219 @@
+From 247bb976d0852af0a2e2c1fb6730876c01895487 Mon Sep 17 00:00:00 2001
+From: rrv <rashmi.r.v@intel.com>
+Date: Fri, 15 Oct 2021 10:29:01 +0530
+Subject: [PATCH] Protect POST Complete GPIO read
+
+In BRC/MRC platforms, due to ME BIOS limitation,
+PostComplete GPIO pin cannot be locked. Hence
+to nullify the impact to BMC, this change makes sure
+that Post Complete monitor is based on espi reset.
+for BRC and MRC platforms.
+
+Tested:
+
+Checked the OperatingSystemState property during all
+conditions of AC ON, AC cycle, DC cycle, DC OFF and DC ON,
+and BMC reset. It works as expected.
+
+Signed-off-by: rrv <rashmi.r.v@intel.com>
+---
+ power-control-x86/src/power_control.cpp | 155 ++++++++++++++++++++++++
+ 1 file changed, 155 insertions(+)
+
+diff --git a/power-control-x86/src/power_control.cpp b/power-control-x86/src/power_control.cpp
+index 5a8487e..28b296d 100644
+--- a/power-control-x86/src/power_control.cpp
++++ b/power-control-x86/src/power_control.cpp
+@@ -18,6 +18,7 @@
+ #include <sys/sysinfo.h>
+ #include <systemd/sd-journal.h>
+
++#include <boost/algorithm/string/predicate.hpp>
+ #include <boost/asio/posix/stream_descriptor.hpp>
+ #include <boost/container/flat_map.hpp>
+ #include <boost/container/flat_set.hpp>
+@@ -112,6 +113,11 @@ static gpiod::line nmiOutLine;
+
+ static constexpr uint8_t beepPowerFail = 8;
+
++static uint16_t productId = 0;
++static constexpr uint16_t brcId = 160;
++static constexpr uint16_t mrcId = 161;
++static std::unique_ptr<sdbusplus::bus::match::match> productIdMatch;
++
+ static void beep(const uint8_t& beepPriority)
+ {
+ std::cerr << "Beep with priority: " << (unsigned)beepPriority << "\n";
+@@ -2029,6 +2035,11 @@ static void postCompleteHandler()
+ {
+ sendPowerControlEvent(Event::postCompleteAssert);
+ osIface->set_property("OperatingSystemState", std::string("Standby"));
++ // return only when MRC or BRC platforms
++ if (productId == brcId || productId == mrcId)
++ {
++ return;
++ }
+ }
+ else
+ {
+@@ -2047,6 +2058,147 @@ static void postCompleteHandler()
+ postCompleteHandler();
+ });
+ }
++
++static void getEspiPlatformReset()
++{
++
++ static std::unique_ptr<sdbusplus::bus::match::match> eSpiMatch =
++ std::make_unique<sdbusplus::bus::match::match>(
++ *conn,
++ "type='signal',interface='org.freedesktop.DBus.Properties',"
++ "member='PropertiesChanged',arg0namespace='xyz.openbmc_project."
++ "State.Host.Misc'",
++ [](sdbusplus::message::message& msg) {
++ std::string interfaceName;
++ boost::container::flat_map<std::string,
++ std::variant<bool, std::string>>
++ propertiesChanged;
++ try
++ {
++ msg.read(interfaceName, propertiesChanged);
++ if (propertiesChanged.begin()->first == "ESpiPlatformReset")
++ {
++ bool value =
++ std::get<bool>(propertiesChanged.begin()->second);
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "ESpiPlatformReset propertiesChanged",
++ phosphor::logging::entry("VALUE= %d", value));
++ if (value)
++ {
++ postCompleteHandler();
++ }
++ }
++ }
++ catch (std::exception& e)
++ {
++ std::cerr << "Unable to read ESpiPlatformReset \n";
++ return;
++ }
++ });
++}
++
++static void getProductId(const std::string& baseboardObjPath)
++{
++ // Check if it's already on DBus
++ conn->async_method_call(
++ [](boost::system::error_code ec,
++ const std::variant<uint64_t>& prodIdProperty) {
++ if (ec)
++ {
++ return;
++ }
++ const uint64_t* prodId = std::get_if<uint64_t>(&prodIdProperty);
++ if (prodId == nullptr)
++ {
++ std::cerr << "Unable to read power restore delay value\n";
++ return;
++ }
++ // Reset the signal
++ productIdMatch.reset();
++ productId = static_cast<uint16_t>(*prodId);
++ if (productId == brcId || productId == mrcId)
++ {
++ getEspiPlatformReset();
++ };
++ },
++ "xyz.openbmc_project.EntityManager", baseboardObjPath,
++ "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.Inventory.Item.Board.Motherboard", "ProductId");
++}
++
++static void checkProductId()
++{
++ productIdMatch = std::make_unique<sdbusplus::bus::match::match>(
++ *conn,
++ "type='signal',interface='org.freedesktop.DBus.Properties',"
++ "member='PropertiesChanged',arg0namespace='xyz.openbmc_project."
++ "Inventory.Item.Board.Motherboard'",
++ [](sdbusplus::message::message& msg) {
++ std::string interfaceName;
++ boost::container::flat_map<std::string,
++ std::variant<uint64_t, std::string>>
++ propertiesChanged;
++ try
++ {
++ msg.read(interfaceName, propertiesChanged);
++ if (propertiesChanged.begin()->first == "ProductId")
++ {
++ productId = static_cast<uint16_t>(
++ std::get<uint64_t>(propertiesChanged.begin()->second));
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "ProductId propertiesChanged",
++ phosphor::logging::entry(" PRODUCTID= %d", productId));
++ }
++ }
++ catch (std::exception& e)
++ {
++ std::cerr << "Unable to read ProductId \n";
++ productIdMatch.reset();
++ return;
++ }
++ // Reset the signal
++ productIdMatch.reset();
++ // monitor the eSpiplatform reset only BRC OR MRC
++ // platforms
++ if (productId == brcId || productId == mrcId)
++ {
++ getEspiPlatformReset();
++ }
++ });
++
++ // get the MRC/BRC board path.
++ conn->async_method_call(
++ [](boost::system::error_code ec, std::vector<std::string>& subtree) {
++ if (ec)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "dbus call failed in getSubTree of board interface.",
++ phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
++ return;
++ }
++ const std::string match = "board";
++ for (const std::string& objpath : subtree)
++ {
++ // Iterate over all retrieved ObjectPaths.
++ if (!boost::ends_with(objpath, match))
++ {
++ // Just move to next path.
++ continue;
++ }
++
++ // Baseboard object path found
++ getProductId(objpath);
++ return;
++ }
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
++ "/xyz/openbmc_project/inventory", 0,
++ std::array<const char*, 1>{
++ "xyz.openbmc_project.Inventory.Item.Board.Motherboard"});
++}
++
+ } // namespace power_control
+
+ int main(int argc, char* argv[])
+@@ -2123,6 +2275,9 @@ int main(int argc, char* argv[])
+ "ID_BUTTON", power_control::idButtonHandler,
+ power_control::idButtonLine, power_control::idButtonEvent);
+
++ // Read productId from Dbus and check
++ power_control::checkProductId();
++
+ // Request POST_COMPLETE GPIO events
+ if (!power_control::requestGPIOEvents(
+ "POST_COMPLETE", power_control::postCompleteHandler,
+--
+2.17.1
+