summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAppaRao Puli <apparao.puli@linux.intel.com>2019-07-22 14:20:09 +0300
committerAppaRao Puli <apparao.puli@linux.intel.com>2019-07-31 20:03:57 +0300
commitb3c425aab385bda0da9950f28de2d1c5ebf6a6c0 (patch)
tree423bca06a23ccd098646c4f687978aba4c0a2cfc
parent1135f5c809de345946ce5cc7f8f043b203f6a379 (diff)
downloadprovingground-b3c425aab385bda0da9950f28de2d1c5ebf6a6c0.tar.xz
PFR: Setting BMC boot finished checkpoint
Adding support to monitor the StartupFinished systemd signal and setting the "bmc boot finished" checkpoint to cpld. Tested: Did BMC reset and cross verified bmc boot finished check-point properly set or not. Change-Id: I14e6aa8b364b28da6cd6b2473cde8502d1ebd77c Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
-rw-r--r--intel-pfr-manager/libpfr/inc/file.hpp19
-rw-r--r--intel-pfr-manager/libpfr/inc/pfr.hpp1
-rw-r--r--intel-pfr-manager/libpfr/src/pfr.cpp18
-rw-r--r--intel-pfr-manager/service/src/mainapp.cpp73
4 files changed, 111 insertions, 0 deletions
diff --git a/intel-pfr-manager/libpfr/inc/file.hpp b/intel-pfr-manager/libpfr/inc/file.hpp
index c7ef58c..1fbc62a 100644
--- a/intel-pfr-manager/libpfr/inc/file.hpp
+++ b/intel-pfr-manager/libpfr/inc/file.hpp
@@ -89,6 +89,25 @@ class I2CFile
return value;
}
+ /** @brief Writes the byte data to I2C dev
+ *
+ * @param[in] Offset - Offset value
+ * @param[in] Byte data - Data
+ */
+ void i2cWriteByteData(const uint8_t offset, const uint8_t value)
+ {
+ int retries = 3;
+ while (i2c_smbus_write_byte_data(fd, offset, value) < 0)
+ {
+ if (!retries--)
+ {
+ throw std::runtime_error("i2c_smbus_write_byte_data() failed");
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ return;
+ }
+
~I2CFile()
{
if (!(fd < 0))
diff --git a/intel-pfr-manager/libpfr/inc/pfr.hpp b/intel-pfr-manager/libpfr/inc/pfr.hpp
index 012c647..cd1b4f2 100644
--- a/intel-pfr-manager/libpfr/inc/pfr.hpp
+++ b/intel-pfr-manager/libpfr/inc/pfr.hpp
@@ -44,6 +44,7 @@ enum class ActionType
std::string getVersionInfoCPLD(ImageType &imgType);
int getProvisioningStatus(bool &ufmLocked, bool &ufmProvisioned);
int readCpldReg(const ActionType &action, uint8_t value);
+int setBMCBootCheckpoint(const uint8_t checkPoint);
} // namespace pfr
} // namespace intel
diff --git a/intel-pfr-manager/libpfr/src/pfr.cpp b/intel-pfr-manager/libpfr/src/pfr.cpp
index 1ad98b2..2e87fa9 100644
--- a/intel-pfr-manager/libpfr/src/pfr.cpp
+++ b/intel-pfr-manager/libpfr/src/pfr.cpp
@@ -41,6 +41,7 @@ static constexpr uint8_t panicEventReason = 0x07;
static constexpr uint8_t majorErrorCode = 0x08;
static constexpr uint8_t minorErrorCode = 0x09;
static constexpr uint8_t provisioningStatus = 0x0A;
+static constexpr uint8_t bmcBootCheckpoint = 0x0F;
static constexpr uint8_t pchActiveMajorVersion = 0x17;
static constexpr uint8_t pchActiveMinorVersion = 0x18;
static constexpr uint8_t bmcActiveMajorVersion = 0x19;
@@ -186,5 +187,22 @@ int readCpldReg(const ActionType& action, uint8_t value)
}
}
+int setBMCBootCheckpoint(const uint8_t checkPoint)
+{
+ try
+ {
+ I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
+ cpldDev.i2cWriteByteData(bmcBootCheckpoint, checkPoint);
+ return 0;
+ }
+ catch (const std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Exception caught in setBMCBootCheckout.",
+ phosphor::logging::entry("MSG=%s", e.what()));
+ return -1;
+ }
+}
+
} // namespace pfr
} // namespace intel
diff --git a/intel-pfr-manager/service/src/mainapp.cpp b/intel-pfr-manager/service/src/mainapp.cpp
index 7be7a45..cc5f9ff 100644
--- a/intel-pfr-manager/service/src/mainapp.cpp
+++ b/intel-pfr-manager/service/src/mainapp.cpp
@@ -18,6 +18,7 @@
#include "pfr_mgr.hpp"
#include "pfr.hpp"
+#include <boost/asio.hpp>
static std::array<std::string, 5> listVersionPaths = {
"bmc_active", "bmc_recovery", "bios_active", "bios_recovery", "cpld"};
@@ -32,7 +33,11 @@ static uint8_t lastMajorErr = 0;
static uint8_t lastMinorErr = 0;
static bool stateTimerRunning = false;
+bool finishedSettingChkPoint = false;
+static constexpr uint8_t bmcBootFinishedChkPoint = 0x09;
+
std::unique_ptr<boost::asio::steady_timer> stateTimer = nullptr;
+std::unique_ptr<boost::asio::steady_timer> initTimer = nullptr;
// Recovery reason map. { <CPLD association>, <Recovery Reason> }
static std::map<uint8_t, std::string> recoveryReasonMap = {
@@ -185,12 +190,64 @@ static void monitorPlatformStateChange(
});
}
+void checkAndSetCheckpoint(sdbusplus::asio::object_server& server,
+ std::shared_ptr<sdbusplus::asio::connection>& conn)
+{
+ // Check whether systemd completed all the loading.
+ conn->async_method_call(
+ [&server, &conn](boost::system::error_code ec,
+ const std::variant<uint64_t>& value) {
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "async_method_call error: FinishTimestamp failed");
+ return;
+ }
+ if (std::get<uint64_t>(value))
+ {
+ if (!finishedSettingChkPoint)
+ {
+ finishedSettingChkPoint = true;
+ intel::pfr::setBMCBootCheckpoint(bmcBootFinishedChkPoint);
+ }
+ }
+ else
+ {
+ // FIX-ME: Latest up-stream sync caused issue in receiving
+ // StartupFinished signal. Unable to get StartupFinished signal
+ // from systemd1 hence using poll method too, to trigger it
+ // properly.
+ constexpr size_t pollTimeout = 10; // seconds
+ initTimer->expires_after(std::chrono::seconds(pollTimeout));
+ initTimer->async_wait([&server, &conn](
+ const boost::system::error_code& ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ // Timer reset.
+ return;
+ }
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Set boot Checkpoint - async wait error.");
+ return;
+ }
+ checkAndSetCheckpoint(server, conn);
+ });
+ }
+ },
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.DBus.Properties", "Get",
+ "org.freedesktop.systemd1.Manager", "FinishTimestamp");
+}
+
int main()
{
// setup connection to dbus
boost::asio::io_service io;
auto conn = std::make_shared<sdbusplus::asio::connection>(io);
stateTimer = std::make_unique<boost::asio::steady_timer>(io);
+ initTimer = std::make_unique<boost::asio::steady_timer>(io);
conn->request_name("xyz.openbmc_project.Intel.PFR.Manager");
auto server = sdbusplus::asio::object_server(conn, true);
@@ -203,6 +260,22 @@ int main()
intel::pfr::PfrVersion obj(server, conn, path);
}
+ // Monitor Boot finished signal and set the checkpoint 9 to
+ // notify CPLD about BMC boot finish.
+ auto bootFinishedSignal = std::make_unique<sdbusplus::bus::match::match>(
+ static_cast<sdbusplus::bus::bus&>(*conn),
+ "type='signal',"
+ "member='StartupFinished',path='/org/freedesktop/systemd1',"
+ "interface='org.freedesktop.systemd1.Manager'",
+ [&server, &conn](sdbusplus::message::message& msg) {
+ if (!finishedSettingChkPoint)
+ {
+ finishedSettingChkPoint = true;
+ intel::pfr::setBMCBootCheckpoint(bmcBootFinishedChkPoint);
+ }
+ });
+ checkAndSetCheckpoint(server, conn);
+
// Capture the Chassis state and Start the monitor timer
// if state changed to 'On'. Run timer until OS boot.
// Stop timer if state changed to 'Off'.