summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaqib Khan <khansa@us.ibm.com>2017-08-10 15:29:34 -0500
committerMichael Tritz <mtritz@us.ibm.com>2017-08-30 12:46:12 -0500
commit1eef62de893e619a8bc0c250e0b439178da11e8f (patch)
treeb3f252891a0a6d3bbda400da819e482e9a559006
parentb60add1e003373cbd48423d4ee60d0b580031f39 (diff)
downloadphosphor-bmc-code-mgmt-1eef62de893e619a8bc0c250e0b439178da11e8f.tar.gz
phosphor-bmc-code-mgmt-1eef62de893e619a8bc0c250e0b439178da11e8f.zip
BMC: Restore version and activation dbus objects on BMC reboot.
- Read the /media/ dir for active bmc versions. Each active version has a /etc/os-release inside /media/ which is used to recreate the version and activation objects. Resolves openbmc/openbmc#2137 Change-Id: I40e97396b0912095868172a5a6566e2189a3446b Signed-off-by: Saqib Khan <khansa@us.ibm.com>
-rwxr-xr-xconfigure.ac6
-rw-r--r--item_updater.cpp108
-rw-r--r--serialize.cpp61
-rw-r--r--serialize.hpp3
-rw-r--r--version.cpp4
-rwxr-xr-xversion.hpp5
6 files changed, 155 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac
index 22eece4..c7730a3 100755
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,12 @@ AC_DEFINE(VERSION_IFACE, "xyz.openbmc_project.Software.Version",
[The software version manager interface])
AC_DEFINE(FILEPATH_IFACE, "xyz.openbmc_project.Common.FilePath",
[The common file path interface])
+AC_DEFINE(OS_RELEASE_FILE, "/etc/os-release",
+ [The name of the BMC table of contents file])
+AC_DEFINE(MEDIA_DIR, "/media/",
+ [The base dir where all RO partitions are mounted])
+AC_DEFINE(BMC_RO_PREFIX, "/media/ro-",
+ [The prefix path for the versioned read-only bmc partitions])
AC_DEFINE(PERSIST_DIR, "/var/lib/obmc/phosphor-bmc-code-mgmt/",
[The dir where activation data is stored in files])
AC_DEFINE(SYSTEMD_BUSNAME, "org.freedesktop.systemd1",
diff --git a/item_updater.cpp b/item_updater.cpp
index aa072ef..7d7df3f 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -145,40 +145,88 @@ void ItemUpdater::createActivation(sdbusplus::message::message& msg)
void ItemUpdater::processBMCImage()
{
- using VersionClass = phosphor::software::manager::Version;
-
- auto purpose = server::Version::VersionPurpose::BMC;
- auto version = phosphor::software::manager::Version::getBMCVersion();
- auto id = phosphor::software::manager::Version::getId(version);
- auto path = std::string{SOFTWARE_OBJPATH} + '/' + id;
-
// Create an association to the BMC inventory item
AssociationList associations{(std::make_tuple(
ACTIVATION_FWD_ASSOCIATION,
ACTIVATION_REV_ASSOCIATION,
bmcInventoryPath))};
- activations.insert(std::make_pair(
- id,
- std::make_unique<Activation>(
- bus,
- path,
- *this,
- id,
- server::Activation::Activations::Active,
- associations)));
- versions.insert(std::make_pair(
- id,
- std::make_unique<VersionClass>(
+ // Read os-release from folders under /media/ to get
+ // BMC Software Versions.
+ for(const auto& iter : fs::directory_iterator(MEDIA_DIR))
+ {
+ auto activationState = server::Activation::Activations::Active;
+ static const auto BMC_RO_PREFIX_LEN = strlen(BMC_RO_PREFIX);
+
+ // Check if the BMC_RO_PREFIXis the prefix of the iter.path
+ if (0 == iter.path().native().compare(0, BMC_RO_PREFIX_LEN,
+ BMC_RO_PREFIX))
+ {
+ auto osRelease = iter.path() / OS_RELEASE_FILE;
+ if (!fs::is_regular_file(osRelease))
+ {
+ log<level::ERR>("Failed to read osRelease\n",
+ entry("FileName=%s", osRelease.string()));
+ activationState = server::Activation::Activations::Invalid;
+ }
+ auto version =
+ phosphor::software::manager::Version::
+ getBMCVersion(osRelease);
+ if (version.empty())
+ {
+ log<level::ERR>("Failed to read version from osRelease",
+ entry("FILENAME=%s", osRelease.string()));
+ activationState = server::Activation::Activations::Invalid;
+ }
+ // The versionId is extracted from the path
+ // for example /media/ro-2a1022fe
+ auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
+ auto purpose = server::Version::VersionPurpose::BMC;
+ 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,
+ server::Activation::Activations::Active,
+ associations)));
+
+ // If Active, create RedundancyPriority instance for this version.
+ if (activationState == server::Activation::Activations::Active)
+ {
+ uint8_t priority = std::numeric_limits<uint8_t>::max();
+ if (!restoreFromFile(id, priority))
+ {
+ log<level::ERR>("Unable to restore priority from file.",
+ entry("VERSIONID=%s", id));
+ }
+ activations.find(id)->second->redundancyPriority =
+ std::make_unique<RedundancyPriority>(
bus,
path,
- version,
- purpose,
- "",
- std::bind(&ItemUpdater::erase,
+ *(activations.find(id)->second),
+ priority);
+ }
+
+ // Create Version instance for this version.
+ versions.insert(std::make_pair(
+ id,
+ std::make_unique<
+ phosphor::software::manager::Version>(
+ bus,
+ path,
+ version,
+ purpose,
+ "",
+ std::bind(&ItemUpdater::erase,
this,
std::placeholders::_1))));
-
+ }
+ }
return;
}
@@ -186,6 +234,17 @@ void ItemUpdater::erase(std::string entryId)
{
// Delete ReadOnly partitions
removeReadOnlyPartition(entryId);
+ removeFile(entryId);
+
+ // Remove the priority environment variable.
+ auto serviceFile = "obmc-flash-bmc-setenv@" + entryId + ".service";
+ auto method = bus.new_method_call(
+ SYSTEMD_BUSNAME,
+ SYSTEMD_PATH,
+ SYSTEMD_INTERFACE,
+ "StartUnit");
+ method.append(serviceFile, "replace");
+ bus.call_noreply(method);
// Removing entry in versions map
auto it = versions.find(entryId);
@@ -212,7 +271,6 @@ void ItemUpdater::erase(std::string entryId)
// If not, don't continue.
this->activations.erase(entryId);
- removeFile(entryId);
}
ItemUpdater::ActivationStatus ItemUpdater::validateSquashFSImage(
diff --git a/serialize.cpp b/serialize.cpp
index 8c97c89..da9e878 100644
--- a/serialize.cpp
+++ b/serialize.cpp
@@ -3,6 +3,7 @@
#include <cereal/archives/json.hpp>
#include <fstream>
#include "serialize.hpp"
+#include <sdbusplus/server.hpp>
namespace phosphor
{
@@ -15,6 +16,8 @@ namespace fs = std::experimental::filesystem;
void storeToFile(std::string versionId, uint8_t priority)
{
+ auto bus = sdbusplus::bus::new_default();
+
if(!fs::is_directory(PERSIST_DIR))
{
fs::create_directory(PERSIST_DIR);
@@ -24,17 +27,69 @@ void storeToFile(std::string versionId, uint8_t priority)
std::ofstream os(path.c_str());
cereal::JSONOutputArchive oarchive(os);
oarchive(cereal::make_nvp("priority", priority));
+
+ std::string serviceFile = "obmc-flash-bmc-setenv@" + versionId + "\\x3d" +
+ std::to_string(priority) + ".service";
+ auto method = bus.new_method_call(
+ SYSTEMD_BUSNAME,
+ SYSTEMD_PATH,
+ SYSTEMD_INTERFACE,
+ "StartUnit");
+ method.append(serviceFile, "replace");
+ bus.call_noreply(method);
}
-void restoreFromFile(std::string versionId, uint8_t& priority)
+bool restoreFromFile(std::string versionId, uint8_t& priority)
{
std::string path = PERSIST_DIR + versionId;
if (fs::exists(path))
{
std::ifstream is(path.c_str(), std::ios::in);
- cereal::JSONInputArchive iarchive(is);
- iarchive(cereal::make_nvp("priority", priority));
+ try
+ {
+ cereal::JSONInputArchive iarchive(is);
+ iarchive(cereal::make_nvp("priority", priority));
+ return true;
+ }
+ catch(cereal::RapidJSONException& e)
+ {
+ fs::remove(path);
+ }
}
+
+ // Find the mtd device "u-boot-env" to retrieve the environment variables
+ std::ifstream mtdDevices("/proc/mtd");
+ std::string device, devicePath;
+
+ try
+ {
+ while (std::getline(mtdDevices, device)) {
+ if (device.find("u-boot-env") != std::string::npos)
+ {
+ devicePath = "/dev/" + device.substr(0, device.find(':'));
+ break;
+ }
+ }
+
+ if (!devicePath.empty())
+ {
+ std::ifstream input(devicePath.c_str());
+ std::string envVars;
+ std::getline(input, envVars);
+
+ if (envVars.find(versionId) != std::string::npos)
+ {
+ // Grab the environment variable for this versionId. These
+ // variables follow the format "versionId=priority\0"
+ auto var = envVars.substr(envVars.find(versionId));
+ priority = std::stoi(var.substr(var.find('=') + 1));
+ return true;
+ }
+ }
+ }
+ catch (const std::exception& e){}
+
+ return false;
}
void removeFile(std::string versionId)
diff --git a/serialize.hpp b/serialize.hpp
index 7b6461f..03eea99 100644
--- a/serialize.hpp
+++ b/serialize.hpp
@@ -21,8 +21,9 @@ void storeToFile(std::string versionId, uint8_t priority);
/** @brief Serialization function - restores activation information from file
* @param[in] versionId - The version for which to retrieve information.
* @param[in] priority - RedundancyPriority reference for that version.
+ * @return true if restore was successful, false if not
**/
-void restoreFromFile(std::string versionId, uint8_t& priority);
+bool restoreFromFile(std::string versionId, uint8_t& priority);
/** @brief Removes the serial file for a given version.
* @param[in] versionId - The version for which to remove a file, if it exists.
diff --git a/version.cpp b/version.cpp
index c7fab30..35df88f 100644
--- a/version.cpp
+++ b/version.cpp
@@ -72,13 +72,13 @@ std::string Version::getId(const std::string& version)
return hexId.str();
}
-std::string Version::getBMCVersion()
+std::string Version::getBMCVersion(const std::string& releaseFilePath)
{
std::string versionKey = "VERSION_ID=";
std::string version{};
std::ifstream efile;
std::string line;
- efile.open("/etc/os-release");
+ efile.open(releaseFilePath);
while (getline(efile, line))
{
diff --git a/version.hpp b/version.hpp
index ef6747f..cbc2bd7 100755
--- a/version.hpp
+++ b/version.hpp
@@ -73,9 +73,12 @@ class Version : public VersionInherit
/**
* @brief Get the active bmc version identifier.
*
+ * @param[in] releaseFilePath - The Path to file which contains
+ * the release version.
+ *
* @return The version identifier.
*/
- static std::string getBMCVersion();
+ static std::string getBMCVersion(const std::string& releaseFilePath);
/**
* @brief Delete the d-bus object and image.
OpenPOWER on IntegriCloud