diff options
author | Lei YU <mine260309@gmail.com> | 2019-02-22 17:35:24 +0800 |
---|---|---|
committer | Lei YU <mine260309@gmail.com> | 2019-03-13 11:01:53 +0800 |
commit | a2e67163d22c69a3f1870737d6d49ccf2d04c450 (patch) | |
tree | 938d51d51877cde4e41a3d1cf482be292eb34254 | |
parent | b53425d44b49fc494750d46a1fe4050ecd3db434 (diff) | |
download | openpower-pnor-code-mgmt-a2e67163d22c69a3f1870737d6d49ccf2d04c450.tar.gz openpower-pnor-code-mgmt-a2e67163d22c69a3f1870737d6d49ccf2d04c450.zip |
Static layout: Implement PNOR code update
Implement the PNOR code update by pflash tool in openpower-pnor-update
service, and update the related associations.
Tested: Verify PNOR code update succeeds.
Change-Id: I53781d6420071200ac2ed6837f7a79bf5e1162c2
Signed-off-by: Lei YU <mine260309@gmail.com>
-rw-r--r-- | activation.cpp | 3 | ||||
-rw-r--r-- | openpower-pnor-update@.service | 9 | ||||
-rw-r--r-- | static/activation_static.cpp | 124 | ||||
-rw-r--r-- | static/activation_static.hpp | 3 | ||||
-rw-r--r-- | static/item_updater_static.cpp | 23 | ||||
-rw-r--r-- | static/item_updater_static.hpp | 5 |
6 files changed, 164 insertions, 3 deletions
diff --git a/activation.cpp b/activation.cpp index ce8cd077b..ff4832627 100644 --- a/activation.cpp +++ b/activation.cpp @@ -89,8 +89,7 @@ auto Activation::requestedActivation(RequestedActivations value) (softwareServer::Activation::activation() == softwareServer::Activation::Activations::Failed)) { - Activation::activation( - softwareServer::Activation::Activations::Activating); + activation(softwareServer::Activation::Activations::Activating); } } return softwareServer::Activation::requestedActivation(value); diff --git a/openpower-pnor-update@.service b/openpower-pnor-update@.service new file mode 100644 index 000000000..b1db21935 --- /dev/null +++ b/openpower-pnor-update@.service @@ -0,0 +1,9 @@ +[Unit] +Description=Update PNOR %I + +[Service] +Type=oneshot +RemainAfterExit=no +ExecStart=/usr/sbin/pflash -E -f -p %I +SyslogIdentifier=pflash + diff --git a/static/activation_static.cpp b/static/activation_static.cpp index d73dc50a4..9768d4157 100644 --- a/static/activation_static.cpp +++ b/static/activation_static.cpp @@ -1,23 +1,147 @@ #include "activation_static.hpp" +#include "item_updater.hpp" + +#include <filesystem> +#include <phosphor-logging/log.hpp> + namespace openpower { namespace software { namespace updater { +namespace fs = std::filesystem; namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server; +using namespace phosphor::logging; + +auto ActivationStatic::activation(Activations value) -> Activations +{ + + if (value != softwareServer::Activation::Activations::Active) + { + redundancyPriority.reset(nullptr); + } + + if (value == softwareServer::Activation::Activations::Activating) + { + parent.freeSpace(); + startActivation(); + return softwareServer::Activation::activation(value); + } + else + { + activationBlocksTransition.reset(nullptr); + activationProgress.reset(nullptr); + } + + return softwareServer::Activation::activation(value); +} + void ActivationStatic::startActivation() { + fs::path pnorFile; + fs::path imagePath(IMG_DIR); + imagePath /= versionId; + + for (const auto& entry : fs::directory_iterator(imagePath)) + { + if (entry.path().extension() == ".pnor") + { + pnorFile = entry; + break; + } + } + if (pnorFile.empty()) + { + log<level::ERR>("Unable to find pnor file", + entry("DIR=%s", imagePath.c_str())); + return; + } + + if (!activationProgress) + { + activationProgress = std::make_unique<ActivationProgress>(bus, path); + } + + if (!activationBlocksTransition) + { + activationBlocksTransition = + std::make_unique<ActivationBlocksTransition>(bus, path); + } + + // TODO: check why the signal is still received without calling this + // function? + subscribeToSystemdSignals(); + + log<level::INFO>("Start programming...", + entry("PNOR=%s", pnorFile.c_str())); + + std::string pnorFileEscaped = pnorFile.string(); + // Escape all '/' to '-' + std::replace(pnorFileEscaped.begin(), pnorFileEscaped.end(), '/', '-'); + + constexpr auto updatePNORService = "openpower-pnor-update@"; + pnorUpdateUnit = + std::string(updatePNORService) + pnorFileEscaped + ".service"; + auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, + SYSTEMD_INTERFACE, "StartUnit"); + method.append(pnorUpdateUnit, "replace"); + bus.call_noreply(method); + + activationProgress->progress(10); } void ActivationStatic::unitStateChange(sdbusplus::message::message& msg) { + uint32_t newStateID{}; + sdbusplus::message::object_path newStateObjPath; + std::string newStateUnit{}; + std::string newStateResult{}; + + // Read the msg and populate each variable + msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult); + + if (newStateUnit == pnorUpdateUnit) + { + if (newStateResult == "done") + { + finishActivation(); + } + if (newStateResult == "failed" || newStateResult == "dependency") + { + Activation::activation( + softwareServer::Activation::Activations::Failed); + } + } } void ActivationStatic::finishActivation() { + activationProgress->progress(90); + + // Set Redundancy Priority before setting to Active + if (!redundancyPriority) + { + redundancyPriority = + std::make_unique<RedundancyPriority>(bus, path, *this, 0); + } + + activationProgress->progress(100); + + activationBlocksTransition.reset(); + activationProgress.reset(); + + unsubscribeFromSystemdSignals(); + // Remove version object from image manager + deleteImageManagerObject(); + // Create active association + parent.createActiveAssociation(path); + // Create functional assocaition + parent.updateFunctionalAssociation(versionId); + + Activation::activation(Activation::Activations::Active); } } // namespace updater diff --git a/static/activation_static.hpp b/static/activation_static.hpp index 85914ac50..6fe713899 100644 --- a/static/activation_static.hpp +++ b/static/activation_static.hpp @@ -17,11 +17,14 @@ class ActivationStatic : public Activation public: using Activation::Activation; ~ActivationStatic() = default; + Activations activation(Activations value) override; private: void unitStateChange(sdbusplus::message::message& msg) override; void startActivation() override; void finishActivation() override; + + std::string pnorUpdateUnit; }; } // namespace updater diff --git a/static/item_updater_static.cpp b/static/item_updater_static.cpp index 9ae2942c7..8eaf21d82 100644 --- a/static/item_updater_static.cpp +++ b/static/item_updater_static.cpp @@ -10,6 +10,7 @@ #include <fstream> #include <phosphor-logging/elog-errors.hpp> #include <phosphor-logging/log.hpp> +#include <sstream> #include <string> using namespace sdbusplus::xyz::openbmc_project::Common::Error; @@ -210,7 +211,7 @@ void ItemUpdaterStatic::reset() bool ItemUpdaterStatic::isVersionFunctional(const std::string& versionId) { - return true; + return versionId == functionalVersionId; } void ItemUpdaterStatic::freePriority(uint8_t value, @@ -220,10 +221,30 @@ void ItemUpdaterStatic::freePriority(uint8_t value, void ItemUpdaterStatic::deleteAll() { + // Static layout has only one active and function pnor + // There is no implementation for this interface } void ItemUpdaterStatic::freeSpace() { + // For now assume static layout only has 1 active PNOR, + // so erase the active PNOR + for (const auto& iter : activations) + { + if (iter.second.get()->activation() == + server::Activation::Activations::Active) + { + erase(iter.second->versionId); + break; + } + } +} + +void ItemUpdaterStatic::updateFunctionalAssociation( + const std::string& versionId) +{ + functionalVersionId = versionId; + ItemUpdater::updateFunctionalAssociation(versionId); } void GardReset::reset() diff --git a/static/item_updater_static.hpp b/static/item_updater_static.hpp index dd7245fbb..75afedade 100644 --- a/static/item_updater_static.hpp +++ b/static/item_updater_static.hpp @@ -35,6 +35,8 @@ class ItemUpdaterStatic : public ItemUpdater void freeSpace() override; + void updateFunctionalAssociation(const std::string& versionId) override; + bool isVersionFunctional(const std::string& versionId) override; private: @@ -61,6 +63,9 @@ class ItemUpdaterStatic : public ItemUpdater /** @brief Host factory reset - clears PNOR partitions for each * Activation D-Bus object */ void reset() override; + + /** @brief The functional version ID */ + std::string functionalVersionId; }; } // namespace updater |