PNOR: Restore version and activation dbus objects on BMC reboot.
- Read the /media/ dir for active pnor versions. Each active
version has a pnor.toc inside /media/ which is used to
recreate the version and activation objects.
- version that matches the version inside
"/var/lib/phosphor-software-manager/pnor/ro" is considered
the current version and its priority is set to 0.
Resolves openbmc/openbmc#1846
Change-Id: Ic3d22cc310fdd60d708a73ddc406d3fb0620845c
Signed-off-by: Saqib Khan <khansa@us.ibm.com>
diff --git a/item_updater.cpp b/item_updater.cpp
index 1c0a6b8..fa3938e 100755
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -129,52 +129,111 @@
void ItemUpdater::processPNORImage()
{
-
- fs::path pnorTOC(PNOR_RO_ACTIVE_PATH);
- pnorTOC /= PNOR_TOC_FILE;
- std::ifstream efile(pnorTOC.c_str());
- if (efile.good() != 1)
+ // Get the current PNOR version
+ auto pnorTOC = fs::path(PNOR_RO_ACTIVE_PATH) / PNOR_TOC_FILE;
+ if (!fs::is_regular_file(pnorTOC))
{
log<level::INFO>("Error PNOR current version is empty");
return;
}
- auto keyValues = Version::getValue(pnorTOC.string(),
- std::map<std::string, std::string> {{"version", ""},
- {"extended_version", ""}});
- std::string version = keyValues.at("version");
- std::string extendedVersion = keyValues.at("extended_version");
- auto id = Version::getId(version);
- auto purpose = server::Version::VersionPurpose::Host;
- auto path = std::string{SOFTWARE_OBJPATH} + '/' + id;
- auto activationState = server::Activation::Activations::Active;
- activations.insert(std::make_pair(
- id,
- std::make_unique<Activation>(
- bus,
- path,
- *this,
- id,
- extendedVersion,
- activationState)));
- versions.insert(std::make_pair(
- id,
- std::make_unique<Version>(
+ std::string currentVersion =
+ Version::getValue(pnorTOC, {{ "version", "" }}).begin()->second;
+
+ // Read pnor.toc from folders under /media/
+ // to get Active Software Versions.
+ for(const auto& iter : fs::directory_iterator(MEDIA_DIR))
+ {
+ auto activationState = server::Activation::Activations::Active;
+
+ static const auto PNOR_RO_PREFIX_LEN = strlen(PNOR_RO_PREFIX);
+
+ // Check if the PNOR_RO_PREFIX is the prefix of the iter.path
+ if (0 == iter.path().native().compare(0, PNOR_RO_PREFIX_LEN,
+ PNOR_RO_PREFIX))
+ {
+ auto pnorTOC = iter.path() / PNOR_TOC_FILE;
+ if (!fs::is_regular_file(pnorTOC))
+ {
+ log<level::ERR>("Failed to read pnorTOC\n",
+ entry("FileName=%s", pnorTOC.string()));
+ activationState = server::Activation::Activations::Invalid;
+ }
+ auto keyValues =
+ Version::getValue(pnorTOC,
+ {{ "version", "" },
+ { "extended_version", "" } });
+ auto& version = keyValues.at("version");
+ if (version.empty())
+ {
+ log<level::ERR>("Failed to read version from pnorTOC",
+ entry("FILENAME=%s", pnorTOC.string()));
+ activationState = server::Activation::Activations::Invalid;
+ }
+
+ auto& extendedVersion = keyValues.at("extended_version");
+ if (extendedVersion.empty())
+ {
+ log<level::ERR>("Failed to read extendedVersion from pnorTOC",
+ entry("FILENAME=%s", pnorTOC.string()));
+ activationState = server::Activation::Activations::Invalid;
+ }
+
+ // The versionId is extracted from the path
+ // for example /media/pnor-ro-2a1022fe
+ auto id = iter.path().native().substr(PNOR_RO_PREFIX_LEN);
+ auto purpose = server::Version::VersionPurpose::Host;
+ auto path = fs::path(SOFTWARE_OBJPATH) / id;
+
+ // Create Activation instance for this version.
+ activations.insert(std::make_pair(
+ id,
+ std::make_unique<Activation>(
+ bus,
+ path,
+ *this,
+ id,
+ extendedVersion,
+ activationState)));
+
+ // If Active, create RedundancyPriority instance for this version.
+ if (activationState == server::Activation::Activations::Active)
+ {
+ // Current PNOR needs the lowest Priority, so setting to 0.
+ // TODO openbmc/openbmc#2040 Need to store Priority in the
+ // RW partition to be able to restore the priorities that
+ // were set before the BMC reboot.
+ auto priority = 1;
+ if (currentVersion == version)
+ {
+ priority = 0;
+ }
+ activations.find(id)->second->redundancyPriority =
+ std::make_unique<RedundancyPriority>(
bus,
path,
- version,
- purpose,
- "",
- *this)));
+ *(activations.find(id)->second),
+ priority);
+ }
+
+ // Create Version instance for this version.
+ versions.insert(std::make_pair(
+ id,
+ std::make_unique<Version>(
+ bus,
+ path,
+ version,
+ purpose,
+ "",
+ *this)));
+ }
+ }
return;
}
int ItemUpdater::validateSquashFSImage(const std::string& filePath)
{
- fs::path file(filePath);
- file /= squashFSImage;
- std::ifstream efile(file.c_str());
-
- if (efile.good() == 1)
+ auto file = fs::path(filePath) / squashFSImage;
+ if (fs::is_regular_file(file))
{
return 0;
}