diff options
author | AppaRao Puli <apparao.puli@linux.intel.com> | 2019-07-22 14:20:09 +0300 |
---|---|---|
committer | AppaRao Puli <apparao.puli@linux.intel.com> | 2019-07-31 20:03:57 +0300 |
commit | b3c425aab385bda0da9950f28de2d1c5ebf6a6c0 (patch) | |
tree | 423bca06a23ccd098646c4f687978aba4c0a2cfc | |
parent | 1135f5c809de345946ce5cc7f8f043b203f6a379 (diff) | |
download | provingground-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.hpp | 19 | ||||
-rw-r--r-- | intel-pfr-manager/libpfr/inc/pfr.hpp | 1 | ||||
-rw-r--r-- | intel-pfr-manager/libpfr/src/pfr.cpp | 18 | ||||
-rw-r--r-- | intel-pfr-manager/service/src/mainapp.cpp | 73 |
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'. |