Initial commit
This commit is contained in:
+234
@@ -0,0 +1,234 @@
|
||||
From b9106871dcc7cfe174c61ca8a6b2e3013d1720c6 Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Thu, 14 Nov 2024 19:18:00 +0800
|
||||
Subject: [PATCH] Add ReleaseDate for Software interface
|
||||
|
||||
---
|
||||
image_manager.cpp | 5 ++++-
|
||||
item_updater.cpp | 25 ++++++++++++++++++++-----
|
||||
meson.build | 1 +
|
||||
version.cpp | 24 ++++++++++++++++++++++++
|
||||
version.hpp | 18 +++++++++++++++++-
|
||||
5 files changed, 66 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/image_manager.cpp b/image_manager.cpp
|
||||
index baa0571..75cd541 100644
|
||||
--- a/image_manager.cpp
|
||||
+++ b/image_manager.cpp
|
||||
@@ -191,6 +191,9 @@ int Manager::processImage(const std::string& tarFilePath)
|
||||
std::string extendedVersion = Version::getValue(manifestPath.string(),
|
||||
"ExtendedVersion");
|
||||
|
||||
+ // Get ReleaseDate
|
||||
+ std::string releaseDate = Version::getBMCReleaseDate(OS_RELEASE_FILE);
|
||||
+
|
||||
// Get CompatibleNames
|
||||
std::vector<std::string> compatibleNames =
|
||||
Version::getRepeatedValues(manifestPath.string(), "CompatibleName");
|
||||
@@ -219,7 +222,7 @@ int Manager::processImage(const std::string& tarFilePath)
|
||||
|
||||
// Create Version object
|
||||
auto versionPtr = std::make_unique<Version>(
|
||||
- bus, objPath, version, purpose, extendedVersion,
|
||||
+ bus, objPath, version, purpose, extendedVersion, releaseDate,
|
||||
imageDirPath.string(), compatibleNames,
|
||||
std::bind(&Manager::erase, this, std::placeholders::_1), id);
|
||||
versionPtr->deleteObject =
|
||||
diff --git a/item_updater.cpp b/item_updater.cpp
|
||||
index d8348e3..36bf5b3 100644
|
||||
--- a/item_updater.cpp
|
||||
+++ b/item_updater.cpp
|
||||
@@ -48,6 +48,7 @@ void ItemUpdater::createActivation(sdbusplus::message_t& msg)
|
||||
sdbusplus::message::object_path objPath;
|
||||
auto purpose = VersionPurpose::Unknown;
|
||||
std::string extendedVersion;
|
||||
+ std::string releaseDate;
|
||||
std::string version;
|
||||
std::map<std::string,
|
||||
std::map<std::string,
|
||||
@@ -109,6 +110,16 @@ void ItemUpdater::createActivation(sdbusplus::message_t& msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ else if (intf.first == RELEASE_DATE_IFACE)
|
||||
+ {
|
||||
+ for (const auto& property : intf.second)
|
||||
+ {
|
||||
+ if (property.first == "ReleaseDate")
|
||||
+ {
|
||||
+ releaseDate = std::get<std::string>(property.second);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
else if (intf.first == COMPATIBLE_IFACE)
|
||||
{
|
||||
for (const auto& property : intf.second)
|
||||
@@ -159,7 +170,7 @@ void ItemUpdater::createActivation(sdbusplus::message_t& msg)
|
||||
}
|
||||
|
||||
auto versionPtr = std::make_unique<VersionClass>(
|
||||
- bus, path, version, purpose, extendedVersion, filePath,
|
||||
+ bus, path, version, purpose, extendedVersion, releaseDate, filePath,
|
||||
compatibleNames,
|
||||
std::bind(&ItemUpdater::erase, this, std::placeholders::_1),
|
||||
versionId);
|
||||
@@ -278,6 +289,10 @@ void ItemUpdater::processBMCImage()
|
||||
// Read os-release from /etc/ to get the BMC extended version
|
||||
std::string extendedVersion =
|
||||
VersionClass::getBMCExtendedVersion(osRelease);
|
||||
+
|
||||
+ // Read os-release from /etc/ to get the BMC release date
|
||||
+ std::string releaseDate =
|
||||
+ VersionClass::getBMCReleaseDate(osRelease);
|
||||
|
||||
auto path = fs::path(SOFTWARE_OBJPATH) / id;
|
||||
|
||||
@@ -307,7 +322,7 @@ void ItemUpdater::processBMCImage()
|
||||
|
||||
// Create Version instance for this version.
|
||||
auto versionPtr = std::make_unique<VersionClass>(
|
||||
- bus, path, version, purpose, extendedVersion, flashId,
|
||||
+ bus, path, version, purpose, extendedVersion, releaseDate, flashId,
|
||||
std::vector<std::string>(),
|
||||
std::bind(&ItemUpdater::erase, this, std::placeholders::_1),
|
||||
id);
|
||||
@@ -876,7 +891,7 @@ void ItemUpdater::createBIOSObject()
|
||||
// Do nothing;
|
||||
};
|
||||
biosVersion = std::make_unique<VersionClass>(
|
||||
- bus, path, version, VersionPurpose::Host, "", "",
|
||||
+ bus, path, version, VersionPurpose::Host, "", "", "",
|
||||
std::vector<std::string>(),
|
||||
std::bind(dummyErase, std::placeholders::_1), "");
|
||||
biosVersion->deleteObject =
|
||||
@@ -910,7 +925,7 @@ void ItemUpdater::createCPLDObject()
|
||||
// Do nothing;
|
||||
};
|
||||
cpldVersion = std::make_unique<VersionClass>(
|
||||
- bus, path, version, VersionPurpose::CPLD, "", "",
|
||||
+ bus, path, version, VersionPurpose::CPLD, "", "", "",
|
||||
std::vector<std::string>(),
|
||||
std::bind(dummyErase, std::placeholders::_1), "");
|
||||
cpldVersion->deleteObject =
|
||||
@@ -944,7 +959,7 @@ void ItemUpdater::createFBCPLDObject()
|
||||
// Do nothing;
|
||||
};
|
||||
FBcpldVersion = std::make_unique<VersionClass>(
|
||||
- bus, path, version, VersionPurpose::FBCPLD, "", "",
|
||||
+ bus, path, version, VersionPurpose::FBCPLD, "", "", "",
|
||||
std::vector<std::string>(),
|
||||
std::bind(dummyErase, std::placeholders::_1), "");
|
||||
cpldVersion->deleteObject =
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 009dcef..68f1f91 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -40,6 +40,7 @@ conf.set_quoted('SYSTEMD_INTERFACE', 'org.freedesktop.systemd1.Manager')
|
||||
conf.set_quoted('VERSION_BUSNAME', 'xyz.openbmc_project.Software.Version')
|
||||
conf.set_quoted('VERSION_IFACE', 'xyz.openbmc_project.Software.Version')
|
||||
conf.set_quoted('EXTENDED_VERSION_IFACE', 'xyz.openbmc_project.Software.ExtendedVersion')
|
||||
+conf.set_quoted('RELEASE_DATE_IFACE', 'xyz.openbmc_project.Software.ReleaseDate')
|
||||
conf.set_quoted('COMPATIBLE_IFACE', 'xyz.openbmc_project.Inventory.Decorator.Compatible')
|
||||
|
||||
# Names of the forward and reverse associations
|
||||
diff --git a/version.cpp b/version.cpp
|
||||
index b8b1247..f40c03e 100644
|
||||
--- a/version.cpp
|
||||
+++ b/version.cpp
|
||||
@@ -178,6 +178,30 @@ std::string Version::getBMCExtendedVersion(const std::string& releaseFilePath)
|
||||
return extendedVersion;
|
||||
}
|
||||
|
||||
+std::string Version::getBMCReleaseDate(const std::string& releaseFilePath)
|
||||
+{
|
||||
+ std::string releaseDateKey = "BUILD_DATE=";
|
||||
+ std::string releaseDateValue{};
|
||||
+ std::string releaseDate{};
|
||||
+ std::ifstream efile(releaseFilePath);
|
||||
+ std::string line;
|
||||
+
|
||||
+ while (getline(efile, line))
|
||||
+ {
|
||||
+ if (line.substr(0, releaseDateKey.size())
|
||||
+ .find(releaseDateKey) != std::string::npos)
|
||||
+ {
|
||||
+ releaseDateValue = line.substr(releaseDateKey.size());
|
||||
+ std::size_t pos = releaseDateValue.find_first_of('"') + 1;
|
||||
+ releaseDate = releaseDateValue.substr(
|
||||
+ pos, releaseDateValue.find_last_of('"') - pos);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return releaseDate;
|
||||
+}
|
||||
+
|
||||
std::string Version::getBMCVersion(const std::string& releaseFilePath)
|
||||
{
|
||||
std::string versionKey = "VERSION_ID=";
|
||||
diff --git a/version.hpp b/version.hpp
|
||||
index 5c74f99..d54b41d 100644
|
||||
--- a/version.hpp
|
||||
+++ b/version.hpp
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "xyz/openbmc_project/Object/Delete/server.hpp"
|
||||
#include "xyz/openbmc_project/Software/ExtendedVersion/server.hpp"
|
||||
#include "xyz/openbmc_project/Software/Version/server.hpp"
|
||||
+#include "xyz/openbmc_project/Software/ReleaseDate/server.hpp"
|
||||
|
||||
#include <sdbusplus/bus.hpp>
|
||||
|
||||
@@ -23,6 +24,7 @@ typedef std::function<void(std::string)> eraseFunc;
|
||||
|
||||
using VersionInherit = sdbusplus::server::object_t<
|
||||
sdbusplus::xyz::openbmc_project::Software::server::ExtendedVersion,
|
||||
+ sdbusplus::xyz::openbmc_project::Software::server::ReleaseDate,
|
||||
sdbusplus::xyz::openbmc_project::Software::server::Version,
|
||||
sdbusplus::xyz::openbmc_project::Common::server::FilePath,
|
||||
sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::Compatible>;
|
||||
@@ -76,13 +78,15 @@ class Version : public VersionInherit
|
||||
* @param[in] versionString - The version string
|
||||
* @param[in] versionPurpose - The version purpose
|
||||
* @param[in] extVersion - The extended version
|
||||
+ * @param[in] relDate - The firmware release date
|
||||
* @param[in] filePath - The image filesystem path
|
||||
* @param[in] compatibleNames - The device compatibility names
|
||||
* @param[in] callback - The eraseFunc callback
|
||||
*/
|
||||
Version(sdbusplus::bus_t& bus, const std::string& objPath,
|
||||
const std::string& versionString, VersionPurpose versionPurpose,
|
||||
- const std::string& extVersion, const std::string& filePath,
|
||||
+ const std::string& extVersion, const std::string& relDate,
|
||||
+ const std::string& filePath,
|
||||
const std::vector<std::string>& compatibleNames, eraseFunc callback,
|
||||
const std::string& id) :
|
||||
VersionInherit(bus, (objPath).c_str(),
|
||||
@@ -91,6 +95,7 @@ class Version : public VersionInherit
|
||||
{
|
||||
// Set properties.
|
||||
extendedVersion(extVersion);
|
||||
+ releaseDate(relDate);
|
||||
purpose(versionPurpose);
|
||||
version(versionString);
|
||||
path(filePath);
|
||||
@@ -150,6 +155,17 @@ class Version : public VersionInherit
|
||||
static std::string
|
||||
getBMCExtendedVersion(const std::string& releaseFilePath);
|
||||
|
||||
+ /**
|
||||
+ * @brief Get the BMC Release Date string.
|
||||
+ *
|
||||
+ * @param[in] releaseFilePath - The path to the file which contains
|
||||
+ * the release machine string.
|
||||
+ *
|
||||
+ * @return The release date string.
|
||||
+ */
|
||||
+ static std::string
|
||||
+ getBMCReleaseDate(const std::string& releaseFilePath);
|
||||
+
|
||||
/**
|
||||
* @brief Get the active BMC version string.
|
||||
*
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
From 9f12832b7a6d2056b3db4e044f88c3e5b65dee97 Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Wed, 13 Nov 2024 11:04:54 +0800
|
||||
Subject: [PATCH] Add fan board cpld for software manager
|
||||
|
||||
---
|
||||
item_updater.cpp | 37 +++++++++++++++++++++++++++++++++++++
|
||||
item_updater.hpp | 20 ++++++++++++++++++++
|
||||
meson.build | 5 +++++
|
||||
meson_options.txt | 8 ++++++++
|
||||
4 files changed, 70 insertions(+)
|
||||
|
||||
diff --git a/item_updater.cpp b/item_updater.cpp
|
||||
index 76f72d4..d8348e3 100644
|
||||
--- a/item_updater.cpp
|
||||
+++ b/item_updater.cpp
|
||||
@@ -74,6 +74,9 @@ void ItemUpdater::createActivation(sdbusplus::message_t& msg)
|
||||
#endif
|
||||
#ifdef CPLD_UPGRADE
|
||||
value == VersionPurpose::CPLD ||
|
||||
+#endif
|
||||
+#ifdef FB_CPLD_UPGRADE
|
||||
+ value == VersionPurpose::FBCPLD ||
|
||||
#endif
|
||||
value == VersionPurpose::System)
|
||||
{
|
||||
@@ -916,6 +919,40 @@ void ItemUpdater::createCPLDObject()
|
||||
}
|
||||
#endif
|
||||
|
||||
+#ifdef FB_CPLD_UPGRADE
|
||||
+void ItemUpdater::createFBCPLDObject()
|
||||
+{
|
||||
+ std::string path = FB_CPLD_OBJPATH;
|
||||
+ // Get version id from last item in the path
|
||||
+ auto pos = path.rfind("/");
|
||||
+ if (pos == std::string::npos)
|
||||
+ {
|
||||
+ error("No version id found in object path {PATH}", "PATH", path);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ createActiveAssociation(path);
|
||||
+ createFunctionalAssociation(path);
|
||||
+
|
||||
+ auto versionId = path.substr(pos + 1);
|
||||
+ auto version = "null";
|
||||
+ AssociationList assocs = {};
|
||||
+ FBcpldActivation = std::make_unique<Activation>(
|
||||
+ bus, path, *this, versionId, server::Activation::Activations::Active,
|
||||
+ assocs);
|
||||
+ auto dummyErase = [](std::string /*entryId*/) {
|
||||
+ // Do nothing;
|
||||
+ };
|
||||
+ FBcpldVersion = std::make_unique<VersionClass>(
|
||||
+ bus, path, version, VersionPurpose::FBCPLD, "", "",
|
||||
+ std::vector<std::string>(),
|
||||
+ std::bind(dummyErase, std::placeholders::_1), "");
|
||||
+ cpldVersion->deleteObject =
|
||||
+ std::make_unique<phosphor::software::manager::Delete>(bus, path,
|
||||
+ *cpldVersion);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
void ItemUpdater::getRunningSlot()
|
||||
{
|
||||
// Check /run/media/slot to get the slot number
|
||||
diff --git a/item_updater.hpp b/item_updater.hpp
|
||||
index 26b657d..fc8d6c3 100644
|
||||
--- a/item_updater.hpp
|
||||
+++ b/item_updater.hpp
|
||||
@@ -70,6 +70,9 @@ class ItemUpdater : public ItemUpdaterInherit
|
||||
#endif
|
||||
#ifdef CPLD_UPGRADE
|
||||
createCPLDObject();
|
||||
+#endif
|
||||
+#ifdef FB_CPLD_UPGRADE
|
||||
+ createFBCPLDObject();
|
||||
#endif
|
||||
emit_object_added();
|
||||
};
|
||||
@@ -299,6 +302,23 @@ class ItemUpdater : public ItemUpdaterInherit
|
||||
/** @brief Persistent Version D-Bus object for CPLD */
|
||||
std::unique_ptr<VersionClass> cpldVersion;
|
||||
#endif
|
||||
+
|
||||
+#ifdef FB_CPLD_UPGRADE
|
||||
+ /** @brief Create the CPLD object without knowing the version.
|
||||
+ *
|
||||
+ * The object is created only to provide the DBus access so that an
|
||||
+ * external service could set the correct CPLD version.
|
||||
+ * On CPLD code update, the version is updated accordingly.
|
||||
+ */
|
||||
+ void createFBCPLDObject();
|
||||
+
|
||||
+ /** @brief Persistent Activation D-Bus object for CPLD */
|
||||
+ std::unique_ptr<Activation> FBcpldActivation;
|
||||
+
|
||||
+ public:
|
||||
+ /** @brief Persistent Version D-Bus object for CPLD */
|
||||
+ std::unique_ptr<VersionClass> FBcpldVersion;
|
||||
+#endif
|
||||
/** @brief Get the slot number of running image */
|
||||
void getRunningSlot();
|
||||
};
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 509d9f7..009dcef 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -68,6 +68,7 @@ conf.set('MMC_LAYOUT', get_option('bmc-layout').contains('mmc'))
|
||||
# Configurable features
|
||||
conf.set('HOST_BIOS_UPGRADE', get_option('host-bios-upgrade').enabled())
|
||||
conf.set('CPLD_UPGRADE', get_option('cpld-upgrade').enabled())
|
||||
+conf.set('FB_CPLD_UPGRADE', get_option('fb-cpld-upgrade').enabled())
|
||||
conf.set('WANT_SIGNATURE_VERIFY', \
|
||||
get_option('verify-signature').enabled() or \
|
||||
get_option('verify-full-signature').enabled())
|
||||
@@ -101,6 +102,10 @@ if get_option('cpld-upgrade').enabled()
|
||||
conf.set_quoted('CPLD_OBJPATH', get_option('cpld-object-path'))
|
||||
endif
|
||||
|
||||
+if get_option('fb-cpld-upgrade').enabled()
|
||||
+ conf.set_quoted('FB_CPLD_OBJPATH', get_option('fb-cpld-object-path'))
|
||||
+endif
|
||||
+
|
||||
if get_option('bmc-static-dual-image').enabled()
|
||||
conf.set('BMC_STATIC_DUAL_IMAGE', get_option('bmc-static-dual-image').enabled())
|
||||
conf.set_quoted('ALT_ROFS_DIR', get_option('alt-rofs-dir'))
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index d638c93..2109025 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -13,6 +13,8 @@ option('host-bios-upgrade', type: 'feature', value: 'enabled',
|
||||
description: 'Enable host bios upgrade support.')
|
||||
option('cpld-upgrade', type: 'feature', value: 'enabled',
|
||||
description: 'Enable cpld upgrade support.')
|
||||
+option('fb-cpld-upgrade', type: 'feature', value: 'enabled',
|
||||
+ description: 'Enable fan board cpld upgrade support.')
|
||||
|
||||
option('sync-bmc-files', type: 'feature', value: 'enabled',
|
||||
description: 'Enable sync of filesystem files.')
|
||||
@@ -129,6 +131,12 @@ option(
|
||||
description: 'The CPLD DBus object path.',
|
||||
)
|
||||
|
||||
+option(
|
||||
+ 'fb-cpld-object-path', type: 'string',
|
||||
+ value: '/xyz/openbmc_project/software/fb_cpld_active',
|
||||
+ description: 'The Fan Board CPLD DBus object path.',
|
||||
+)
|
||||
+
|
||||
option('bmc-static-dual-image', type: 'feature', value: 'enabled',
|
||||
description: 'Enable the dual image support for static layout.')
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+694
@@ -0,0 +1,694 @@
|
||||
From bfa8b769aa57a3e25299640d36dd16d3037d5859 Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Mon, 6 Jan 2025 18:11:52 +0800
|
||||
Subject: [PATCH] Sypport applyoption and updatetarget parameter
|
||||
|
||||
---
|
||||
activation.cpp | 11 +-
|
||||
activation.hpp | 38 ++++
|
||||
image_async_main.cpp | 360 +++++++++++++++++++++++++++++++++++
|
||||
item_updater.cpp | 26 ++-
|
||||
meson.build | 9 +
|
||||
meson_options.txt | 5 +
|
||||
obmc-async-update.service.in | 11 ++
|
||||
static/flash.cpp | 77 ++++++--
|
||||
8 files changed, 513 insertions(+), 24 deletions(-)
|
||||
create mode 100755 image_async_main.cpp
|
||||
create mode 100755 obmc-async-update.service.in
|
||||
|
||||
diff --git a/activation.cpp b/activation.cpp
|
||||
index f866461..7fb4038 100644
|
||||
--- a/activation.cpp
|
||||
+++ b/activation.cpp
|
||||
@@ -175,14 +175,14 @@ auto Activation::activation(Activations value) -> Activations
|
||||
|
||||
#else // STATIC_LAYOUT
|
||||
|
||||
- if (parent.runningImageSlot == 0)
|
||||
- {
|
||||
+ // if (parent.runningImageSlot == 0)
|
||||
+ // {
|
||||
// On primary, update it as before
|
||||
onFlashWriteSuccess();
|
||||
return softwareServer::Activation::activation(
|
||||
softwareServer::Activation::Activations::Active);
|
||||
- }
|
||||
- // On secondary, wait for the service to complete
|
||||
+ // }
|
||||
+ // // On secondary, wait for the service to complete
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -198,6 +198,7 @@ void Activation::onFlashWriteSuccess()
|
||||
|
||||
activationBlocksTransition.reset(nullptr);
|
||||
activationProgress.reset(nullptr);
|
||||
+ applyOptions.reset();
|
||||
|
||||
rwVolumeCreated = false;
|
||||
roVolumeCreated = false;
|
||||
@@ -291,6 +292,8 @@ auto Activation::requestedActivation(RequestedActivations value)
|
||||
softwareServer::Activation::RequestedActivations::Active))
|
||||
{
|
||||
if ((softwareServer::Activation::activation() ==
|
||||
+ softwareServer::Activation::Activations::AddQueue) ||
|
||||
+ (softwareServer::Activation::activation() ==
|
||||
softwareServer::Activation::Activations::Ready) ||
|
||||
(softwareServer::Activation::activation() ==
|
||||
softwareServer::Activation::Activations::Failed))
|
||||
diff --git a/activation.hpp b/activation.hpp
|
||||
index 7d10472..0c6d8b5 100644
|
||||
--- a/activation.hpp
|
||||
+++ b/activation.hpp
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <xyz/openbmc_project/Association/Definitions/server.hpp>
|
||||
#include <xyz/openbmc_project/Software/Activation/server.hpp>
|
||||
#include <xyz/openbmc_project/Software/ActivationBlocksTransition/server.hpp>
|
||||
+#include <xyz/openbmc_project/Software/ApplyOptions/server.hpp>
|
||||
+#include <xyz/openbmc_project/Software/UpdateTarget/server.hpp>
|
||||
|
||||
#ifdef WANT_SIGNATURE_VERIFY
|
||||
#include <filesystem>
|
||||
@@ -39,6 +41,10 @@ using RedundancyPriorityInherit = sdbusplus::server::object_t<
|
||||
sdbusplus::xyz::openbmc_project::Software::server::RedundancyPriority>;
|
||||
using ActivationProgressInherit = sdbusplus::server::object_t<
|
||||
sdbusplus::xyz::openbmc_project::Software::server::ActivationProgress>;
|
||||
+using UpdateTargetInherit = sdbusplus::server::object::object<
|
||||
+ sdbusplus::xyz::openbmc_project::Software::server::UpdateTarget>;
|
||||
+using ApplyOptionsInherit = sdbusplus::server::object::object<
|
||||
+ sdbusplus::xyz::openbmc_project::Software::server::ApplyOptions>;
|
||||
|
||||
constexpr auto applyTimeImmediate =
|
||||
"xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.Immediate";
|
||||
@@ -166,6 +172,32 @@ class ActivationProgress : public ActivationProgressInherit
|
||||
}
|
||||
};
|
||||
|
||||
+class UpdateTarget : public UpdateTargetInherit
|
||||
+{
|
||||
+ public:
|
||||
+ /** @brief Constructs UpdateTarget
|
||||
+ *
|
||||
+ * @param[in] bus - The Dbus bus object
|
||||
+ * @param[in] path - The Dbus object path
|
||||
+ */
|
||||
+ UpdateTarget(sdbusplus::bus::bus& bus, const std::string& path) :
|
||||
+ UpdateTargetInherit(bus, path.c_str(), action::emit_interface_added)
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+class ApplyOptions : public ApplyOptionsInherit
|
||||
+{
|
||||
+ public:
|
||||
+ /** @brief Constructs ApplyOptions
|
||||
+ *
|
||||
+ * @param[in] bus - The Dbus bus object
|
||||
+ * @param[in] path - The Dbus object path
|
||||
+ */
|
||||
+ ApplyOptions(sdbusplus::bus::bus& bus, const std::string& path) :
|
||||
+ ApplyOptionsInherit(bus, path.c_str(), action::emit_interface_added)
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
/** @class Activation
|
||||
* @brief OpenBMC activation software management implementation.
|
||||
* @details A concrete implementation for
|
||||
@@ -328,6 +360,12 @@ class Activation : public ActivationInherit, public Flash
|
||||
/** @brief Persistent ActivationProgress dbus object */
|
||||
std::unique_ptr<ActivationProgress> activationProgress;
|
||||
|
||||
+ /** @brief Persistent UpdateTarget dbus object */
|
||||
+ std::unique_ptr<UpdateTarget> updateTarget;
|
||||
+
|
||||
+ /** @brief Persistent ApplyOptions dbus object */
|
||||
+ std::unique_ptr<ApplyOptions> applyOptions;
|
||||
+
|
||||
/** @brief Used to subscribe to dbus systemd signals **/
|
||||
sdbusplus::bus::match_t systemdSignals;
|
||||
|
||||
diff --git a/image_async_main.cpp b/image_async_main.cpp
|
||||
new file mode 100755
|
||||
index 0000000..bd17564
|
||||
--- /dev/null
|
||||
+++ b/image_async_main.cpp
|
||||
@@ -0,0 +1,360 @@
|
||||
+#include <boost/asio.hpp>
|
||||
+#include <boost/chrono.hpp>
|
||||
+#include <boost/container/flat_map.hpp>
|
||||
+#include <phosphor-logging/elog-errors.hpp>
|
||||
+#include <phosphor-logging/elog.hpp>
|
||||
+#include <phosphor-logging/lg2.hpp>
|
||||
+#include <sdbusplus/asio/connection.hpp>
|
||||
+#include <sdbusplus/asio/object_server.hpp>
|
||||
+#include <sdbusplus/bus.hpp>
|
||||
+#include <sdbusplus/message.hpp>
|
||||
+#include <sdbusplus/server.hpp>
|
||||
+
|
||||
+#include <deque>
|
||||
+#include <exception>
|
||||
+#include <filesystem>
|
||||
+#include <iostream>
|
||||
+#include <string>
|
||||
+#include <utility>
|
||||
+#include <variant>
|
||||
+#include <vector>
|
||||
+
|
||||
+using namespace phosphor::logging;
|
||||
+using DbusVariant = std::variant<std::vector<std::string>, std::string, bool>;
|
||||
+
|
||||
+static boost::asio::io_context ioCtx;
|
||||
+static std::shared_ptr<sdbusplus::asio::connection> conn;
|
||||
+static std::shared_ptr<sdbusplus::asio::dbus_interface> interface;
|
||||
+static std::shared_ptr<sdbusplus::bus::match::match> match;
|
||||
+
|
||||
+static boost::asio::steady_timer checkTimer(ioCtx);
|
||||
+static boost::asio::steady_timer updateTimer(ioCtx);
|
||||
+static std::string status{"Idle"};
|
||||
+
|
||||
+static std::deque<std::pair<std::string, std::string>> components;
|
||||
+static bool powerStatus = false;
|
||||
+static std::unique_ptr<sdbusplus::bus::match_t> powerMatch = nullptr;
|
||||
+
|
||||
+static std::string handlerStart();
|
||||
+
|
||||
+namespace power
|
||||
+{
|
||||
+const static constexpr char* busname = "xyz.openbmc_project.State.Chassis";
|
||||
+const static constexpr char* interface = "xyz.openbmc_project.State.Chassis";
|
||||
+const static constexpr char* path = "/xyz/openbmc_project/state/chassis0";
|
||||
+const static constexpr char* property = "CurrentPowerState";
|
||||
+} // namespace power
|
||||
+
|
||||
+namespace properties
|
||||
+{
|
||||
+constexpr const char* interface = "org.freedesktop.DBus.Properties";
|
||||
+constexpr const char* get = "Get";
|
||||
+constexpr const char* set = "Set";
|
||||
+} // namespace properties
|
||||
+
|
||||
+static void
|
||||
+ getPowerStatus(const std::shared_ptr<sdbusplus::asio::connection>& conn,
|
||||
+ size_t retries = 2)
|
||||
+{
|
||||
+ conn->async_method_call(
|
||||
+ [conn, retries](boost::system::error_code ec,
|
||||
+ const std::variant<std::string>& state) {
|
||||
+ if (ec)
|
||||
+ {
|
||||
+ if (retries != 0U)
|
||||
+ {
|
||||
+ auto timer = std::make_shared<boost::asio::steady_timer>(
|
||||
+ conn->get_io_context());
|
||||
+ timer->expires_after(std::chrono::seconds(15));
|
||||
+ timer->async_wait(
|
||||
+ [timer, conn, retries](boost::system::error_code) {
|
||||
+ getPowerStatus(conn, retries - 1);
|
||||
+ });
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // we commonly come up before power control, we'll capture the
|
||||
+ // property change later
|
||||
+ lg2::error("error getting power status {ERROR}", "ERROR",
|
||||
+ ec.message());
|
||||
+ return;
|
||||
+ }
|
||||
+ powerStatus = std::get<std::string>(state).ends_with(".On");
|
||||
+ },
|
||||
+ power::busname, power::path, properties::interface, properties::get,
|
||||
+ power::interface, power::property);
|
||||
+}
|
||||
+
|
||||
+void setupPowerMonitor(const std::shared_ptr<sdbusplus::asio::connection>& conn)
|
||||
+{
|
||||
+ // create a match for powergood changes, first time do a method call to
|
||||
+ // cache the correct value
|
||||
+ if (powerMatch)
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ powerMatch = std::make_unique<sdbusplus::bus::match_t>(
|
||||
+ static_cast<sdbusplus::bus_t&>(*conn),
|
||||
+ "type='signal',interface='" + std::string(properties::interface) +
|
||||
+ "',path='" + std::string(power::path) + "',arg0='" +
|
||||
+ std::string(power::interface) + "'",
|
||||
+ [](sdbusplus::message_t& message) {
|
||||
+ std::string objectName;
|
||||
+ std::map<std::string, std::variant<std::string>> values;
|
||||
+ message.read(objectName, values);
|
||||
+ auto findState = values.find(power::property);
|
||||
+ if (findState != values.end())
|
||||
+ {
|
||||
+ powerStatus =
|
||||
+ std::get<std::string>(findState->second).ends_with(".Running");
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ getPowerStatus(conn);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief remove image form bmc filesystem.
|
||||
+ * @param[in] imageID - old image.
|
||||
+ * @details if image type is same as in queue, remove old image.
|
||||
+ *
|
||||
+ */
|
||||
+void removeExistImage(const std::string& imageID)
|
||||
+{
|
||||
+ auto oldImage = "/xyz/openbmc_project/software/" + imageID;
|
||||
+ conn->async_method_call([](const boost::system::error_code& /*ec*/) {},
|
||||
+ "xyz.openbmc_project.Software.BMC.Updater",
|
||||
+ oldImage, "xyz.openbmc_project.Object.Delete",
|
||||
+ "Delete");
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Async AddQueue method implementation for dbus.
|
||||
+ * @param[in] versionPurpose - VersionPurpose as unique key.
|
||||
+ * @param[in] imageID - get from bmc.
|
||||
+ * @details REST API
|
||||
+ * https://<IP>/xyz/openbmc_project/Software/AsyncUpdate/action/AddQueue for for
|
||||
+ * web and update-script.
|
||||
+ *
|
||||
+ */
|
||||
+static void handlerAddQueue(std::string& versionPurpose, std::string& imageID)
|
||||
+{
|
||||
+ // remove same image from bmc filesystem.
|
||||
+ // position is same as before in queue
|
||||
+ bool existImage = false;
|
||||
+ for (auto& item : components)
|
||||
+ {
|
||||
+ if (item.first == versionPurpose)
|
||||
+ {
|
||||
+ removeExistImage(item.second);
|
||||
+ item.second = imageID;
|
||||
+ existImage = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!existImage)
|
||||
+ {
|
||||
+ components.push_back(std::make_pair(versionPurpose, imageID));
|
||||
+ }
|
||||
+ // if Running, keep Running status.
|
||||
+ if (status == "Idle")
|
||||
+ {
|
||||
+ status = "Waiting";
|
||||
+ interface->set_property("AsyncUpdateStatus", status);
|
||||
+ }
|
||||
+ // set the status of async upgrade to add queue
|
||||
+ auto objectPath = "/xyz/openbmc_project/software/" + imageID;
|
||||
+ try
|
||||
+ {
|
||||
+ conn->async_method_call(
|
||||
+ [](const boost::system::error_code& /*ec*/) {},
|
||||
+ "xyz.openbmc_project.Software.BMC.Updater", objectPath,
|
||||
+ "org.freedesktop.DBus.Properties", "Set",
|
||||
+ "xyz.openbmc_project.Software.Activation", "Activation",
|
||||
+ DbusVariant(
|
||||
+ "xyz.openbmc_project.Software.Activation.Activations.AddQueue"));
|
||||
+ }
|
||||
+ catch (const sdbusplus::exception::SdBusError& e)
|
||||
+ {
|
||||
+ lg2::error("Can not to set async upgrade status: {ERROR}", "ERROR", e);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Get power status.
|
||||
+ * @return if true means power is off
|
||||
+ * false power on
|
||||
+ *
|
||||
+ */
|
||||
+static bool isPowerOff()
|
||||
+{
|
||||
+ return powerStatus == false;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief start update.
|
||||
+ */
|
||||
+static void activateImage()
|
||||
+{
|
||||
+ status = "Running";
|
||||
+ interface->set_property("AsyncUpdateStatus", status);
|
||||
+ auto imagePair = components.front();
|
||||
+ auto versionId = imagePair.first;
|
||||
+ auto image = imagePair.second;
|
||||
+ auto currImage = "/xyz/openbmc_project/software/" + image;
|
||||
+ try
|
||||
+ {
|
||||
+ conn->async_method_call(
|
||||
+ [](const boost::system::error_code& /*ec*/) {},
|
||||
+ "xyz.openbmc_project.Software.BMC.Updater", currImage,
|
||||
+ "org.freedesktop.DBus.Properties", "Set",
|
||||
+ "xyz.openbmc_project.Software.Activation", "RequestedActivation",
|
||||
+ DbusVariant(
|
||||
+ "xyz.openbmc_project.Software.Activation.RequestedActivations.Active"));
|
||||
+ }
|
||||
+ catch (const sdbusplus::exception::SdBusError& e)
|
||||
+ {
|
||||
+ lg2::error("Can not activate image: {ERROR}", "ERROR", e);
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief stop update.
|
||||
+ */
|
||||
+static void interruptImage(std::string& image)
|
||||
+{
|
||||
+ auto currImage = "/xyz/openbmc_project/software/" + image;
|
||||
+ try
|
||||
+ {
|
||||
+ conn->async_method_call(
|
||||
+ [](const boost::system::error_code& /*ec*/) {},
|
||||
+ "xyz.openbmc_project.Software.BMC.Updater", currImage,
|
||||
+ "org.freedesktop.DBus.Properties", "Set",
|
||||
+ "xyz.openbmc_project.Software.Activation", "Activation",
|
||||
+ DbusVariant(
|
||||
+ "xyz.openbmc_project.Software.Activation.Activations.Interrupted"));
|
||||
+ }
|
||||
+ catch (const sdbusplus::exception::SdBusError& e)
|
||||
+ {
|
||||
+ lg2::error("Can not interrupt image: {IMAGE} error: {ERROR}", "IMAGE",
|
||||
+ image, "ERROR", e);
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief dbus method callback.
|
||||
+ */
|
||||
+static std::string handlerStart()
|
||||
+{
|
||||
+ // when queue is empty return idle status
|
||||
+ if (components.empty())
|
||||
+ {
|
||||
+ if (status == "Running")
|
||||
+ {
|
||||
+ status = "Idle";
|
||||
+ }
|
||||
+ interface->set_property("AsyncUpdateStatus", status);
|
||||
+ return status;
|
||||
+ }
|
||||
+ // queue is not empty start async update ,use timer to check power status
|
||||
+ checkTimer.expires_after(boost::asio::chrono::seconds(5));
|
||||
+ checkTimer.async_wait([&](const boost::system::error_code& ec) {
|
||||
+ if (ec)
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!isPowerOff())
|
||||
+ {
|
||||
+ if (status == "Running")
|
||||
+ {
|
||||
+ lg2::error("power is on, stop async update for queued images.");
|
||||
+ for (auto& item : components)
|
||||
+ {
|
||||
+ lg2::error(
|
||||
+ "stop queued image async update, imageID: {IMAGE}, versionID: {VERSION}",
|
||||
+ "IMAGE", item.second, "VERSION", item.first);
|
||||
+ interruptImage(item.second);
|
||||
+ }
|
||||
+ components.clear();
|
||||
+
|
||||
+ status = "Idle";
|
||||
+ interface->set_property("AsyncUpdateStatus", status);
|
||||
+ return;
|
||||
+ }
|
||||
+ // power is on recheck power status
|
||||
+ handlerStart();
|
||||
+ return;
|
||||
+ }
|
||||
+ // power is off start async update
|
||||
+ activateImage();
|
||||
+ });
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief dbus match callback.
|
||||
+ */
|
||||
+void matchJobs(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);
|
||||
+ // normal update will be ignore
|
||||
+ if (status == "Running")
|
||||
+ {
|
||||
+ // if newStateUnit exist image ID, means it is a service job
|
||||
+ if (newStateUnit.find(components.front().second) != std::string::npos)
|
||||
+ {
|
||||
+ if (newStateResult == "done")
|
||||
+ {
|
||||
+ lg2::info("async update image finish successfully ({SERVICE})",
|
||||
+ "SERVICE", newStateUnit);
|
||||
+ }
|
||||
+ else if (newStateResult == "failed")
|
||||
+ {
|
||||
+ lg2::error("async update image failed ({SERVICE})", "SERVICE",
|
||||
+ newStateUnit);
|
||||
+ }
|
||||
+ // when finish, remove image from queue
|
||||
+ components.pop_front();
|
||||
+ // start next
|
||||
+ handlerStart();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int main(int /*argc*/, char** /*argv*/)
|
||||
+{
|
||||
+ const auto BUS_NAME = "xyz.openbmc_project.Software.AsyncUpdate";
|
||||
+ const auto OBJECT_PATH = "/xyz/openbmc_project/Software/AsyncUpdate";
|
||||
+ const auto INTERFACE_NAME = "xyz.openbmc_project.Software.AsyncUpdate";
|
||||
+ conn = std::make_shared<sdbusplus::asio::connection>(ioCtx);
|
||||
+ conn->request_name(BUS_NAME);
|
||||
+
|
||||
+ setupPowerMonitor(conn);
|
||||
+ match = std::make_shared<sdbusplus::bus::match::match>(
|
||||
+ *conn,
|
||||
+ "type='signal',member='JobRemoved',path='/org/freedesktop/systemd1',interface='org.freedesktop.systemd1.Manager'",
|
||||
+ matchJobs);
|
||||
+ sdbusplus::asio::object_server hostServer =
|
||||
+ sdbusplus::asio::object_server(conn);
|
||||
+ interface = hostServer.add_interface(OBJECT_PATH, INTERFACE_NAME);
|
||||
+ interface->register_property(
|
||||
+ "AsyncUpdateStatus", status,
|
||||
+ [&](const std::string& requested, std::string& resp) -> int {
|
||||
+ status = requested;
|
||||
+ resp = requested;
|
||||
+ return 1;
|
||||
+ });
|
||||
+ interface->register_method("Start", handlerStart);
|
||||
+ interface->register_method("AddQueue", handlerAddQueue);
|
||||
+ interface->initialize();
|
||||
+ ioCtx.run();
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/item_updater.cpp b/item_updater.cpp
|
||||
index 36bf5b3..a09f704 100644
|
||||
--- a/item_updater.cpp
|
||||
+++ b/item_updater.cpp
|
||||
@@ -179,10 +179,15 @@ void ItemUpdater::createActivation(sdbusplus::message_t& msg)
|
||||
*versionPtr);
|
||||
versions.insert(std::make_pair(versionId, std::move(versionPtr)));
|
||||
|
||||
- activations.insert(std::make_pair(
|
||||
- versionId,
|
||||
- std::make_unique<Activation>(bus, path, *this, versionId,
|
||||
- activationState, associations)));
|
||||
+ if (version == "Mismatch" || version == "Invalid")
|
||||
+ {
|
||||
+ activationState = server::Activation::Activations::Invalid;
|
||||
+ }
|
||||
+ auto activationPtr = std::make_unique<Activation>(
|
||||
+ bus, path, *this, versionId, activationState, associations);
|
||||
+ activationPtr->updateTarget = std::make_unique<UpdateTarget>(bus, path);
|
||||
+ activationPtr->applyOptions = std::make_unique<ApplyOptions>(bus, path);
|
||||
+ activations.insert(std::make_pair(versionId, std::move(activationPtr)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -768,12 +773,21 @@ void ItemUpdater::resetUbootEnvVars()
|
||||
void ItemUpdater::freeSpace([[maybe_unused]] const Activation& caller)
|
||||
{
|
||||
#ifdef BMC_STATIC_DUAL_IMAGE
|
||||
- // For the golden image case, always remove the version on the primary side
|
||||
+ // For dual image case, erase the slot depends on the updateTarget
|
||||
+ auto targetSlot = UpdateTarget::TargetSlot::Primary;
|
||||
+ if (caller.updateTarget)
|
||||
+ {
|
||||
+ targetSlot = caller.updateTarget->updateTargetSlot();
|
||||
+ }
|
||||
+ auto priorityToErase = targetSlot == UpdateTarget::TargetSlot::Primary ? 0
|
||||
+ : 1;
|
||||
+
|
||||
std::string versionIDtoErase;
|
||||
for (const auto& iter : activations)
|
||||
{
|
||||
if (iter.second->redundancyPriority &&
|
||||
- iter.second->redundancyPriority.get()->priority() == 0)
|
||||
+ iter.second->redundancyPriority.get()->priority() ==
|
||||
+ priorityToErase)
|
||||
{
|
||||
versionIDtoErase = iter.second->versionId;
|
||||
break;
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 68f1f91..99d3645 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -247,6 +247,15 @@ if get_option('sync-bmc-files').enabled()
|
||||
)
|
||||
endif
|
||||
|
||||
+if get_option('async-update').allowed()
|
||||
+ executable(
|
||||
+ 'obmc-async-update',
|
||||
+ 'image_async_main.cpp',
|
||||
+ dependencies: deps,
|
||||
+ install: true
|
||||
+ )
|
||||
+ unit_files += 'obmc-async-update.service.in'
|
||||
+endif
|
||||
if (get_option('verify-signature').enabled() or \
|
||||
get_option('verify-full-signature').enabled())
|
||||
image_updater_sources += files(
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index 2109025..53c61fd 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -40,6 +40,11 @@ option(
|
||||
description: 'Automatic flash side switch on boot',
|
||||
)
|
||||
|
||||
+option(
|
||||
+ 'async-update', type: 'feature', value: 'enabled',
|
||||
+ description: 'Enable Async update.',
|
||||
+)
|
||||
+
|
||||
# Variables
|
||||
option(
|
||||
'active-bmc-max-allowed', type: 'integer',
|
||||
diff --git a/obmc-async-update.service.in b/obmc-async-update.service.in
|
||||
new file mode 100755
|
||||
index 0000000..d586a55
|
||||
--- /dev/null
|
||||
+++ b/obmc-async-update.service.in
|
||||
@@ -0,0 +1,11 @@
|
||||
+[Unit]
|
||||
+Description=BMC async update
|
||||
+
|
||||
+[Service]
|
||||
+Restart=always
|
||||
+Type=dbus
|
||||
+BusName=xyz.openbmc_project.Software.AsyncUpdate
|
||||
+ExecStart=/usr/bin/obmc-async-update
|
||||
+
|
||||
+[Install]
|
||||
+WantedBy=multi-user.target
|
||||
\ No newline at end of file
|
||||
diff --git a/static/flash.cpp b/static/flash.cpp
|
||||
index 74316d1..812b5de 100644
|
||||
--- a/static/flash.cpp
|
||||
+++ b/static/flash.cpp
|
||||
@@ -31,20 +31,20 @@ using namespace phosphor::software::image;
|
||||
|
||||
void Activation::flashWrite()
|
||||
{
|
||||
-#ifdef BMC_STATIC_DUAL_IMAGE
|
||||
- if (parent.runningImageSlot != 0)
|
||||
- {
|
||||
- // It's running on the secondary chip, update the primary one
|
||||
- info("Flashing primary flash from secondary, id: {ID}", "ID",
|
||||
- versionId);
|
||||
- auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
|
||||
- SYSTEMD_INTERFACE, "StartUnit");
|
||||
- auto serviceFile = FLASH_ALT_SERVICE_TMPL + versionId + ".service";
|
||||
- method.append(serviceFile, "replace");
|
||||
- bus.call_noreply(method);
|
||||
- return;
|
||||
- }
|
||||
-#endif
|
||||
+// #ifdef BMC_STATIC_DUAL_IMAGE
|
||||
+// if (parent.runningImageSlot != 0)
|
||||
+// {
|
||||
+// // It's running on the secondary chip, update the primary one
|
||||
+// info("Flashing primary flash from secondary, id: {ID}", "ID",
|
||||
+// versionId);
|
||||
+// auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
|
||||
+// SYSTEMD_INTERFACE, "StartUnit");
|
||||
+// auto serviceFile = FLASH_ALT_SERVICE_TMPL + versionId + ".service";
|
||||
+// method.append(serviceFile, "replace");
|
||||
+// bus.call_noreply(method);
|
||||
+// return;
|
||||
+// }
|
||||
+// #endif
|
||||
// For static layout code update, just put images in /run/initramfs.
|
||||
// It expects user to trigger a reboot and an updater script will program
|
||||
// the image to flash during reboot.
|
||||
@@ -57,6 +57,55 @@ void Activation::flashWrite()
|
||||
fs::copy_file(uploadDir / versionId / bmcImage, toPath / bmcImage,
|
||||
fs::copy_options::overwrite_existing, ec);
|
||||
}
|
||||
+
|
||||
+ std::string old_prefix = "image-";
|
||||
+ std::string new_prefix = "image-alt-";
|
||||
+ auto targetSlot = UpdateTarget::TargetSlot::Primary;
|
||||
+ if (updateTarget)
|
||||
+ {
|
||||
+ targetSlot = updateTarget->updateTargetSlot();
|
||||
+ }
|
||||
+
|
||||
+ if (targetSlot == UpdateTarget::TargetSlot::Both)
|
||||
+ {
|
||||
+ for (const auto& entry : fs::directory_iterator(toPath))
|
||||
+ {
|
||||
+ if (entry.is_regular_file())
|
||||
+ {
|
||||
+ std::string old_name = entry.path().filename().string();
|
||||
+ if (old_name.find(old_prefix) == 0 && old_name.find(new_prefix) == std::string::npos)
|
||||
+ {
|
||||
+ std::string new_name = new_prefix + old_name.substr(old_prefix.length());
|
||||
+ fs::copy_file(entry.path(), entry.path().parent_path() / new_name);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ else if (targetSlot == UpdateTarget::TargetSlot::Secondary)
|
||||
+ {
|
||||
+ for (const auto& entry : fs::directory_iterator(toPath))
|
||||
+ {
|
||||
+ if (entry.is_regular_file())
|
||||
+ {
|
||||
+ std::string old_name = entry.path().filename().string();
|
||||
+ if (old_name.find(old_prefix) == 0 && old_name.find(new_prefix) == std::string::npos)
|
||||
+ {
|
||||
+ std::string new_name = new_prefix + old_name.substr(old_prefix.length());
|
||||
+ fs::rename(entry.path(), entry.path().parent_path() / new_name);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ auto clearConfig = ApplyOptions::ConfigManagement::Keep;
|
||||
+ if (applyOptions)
|
||||
+ {
|
||||
+ clearConfig = applyOptions->clearConfig();
|
||||
+ }
|
||||
+ if (clearConfig == ApplyOptions::ConfigManagement::Clear)
|
||||
+ {
|
||||
+ utils::execute("/sbin/fw_setenv", "openbmconce", "factory-reset");
|
||||
+ }
|
||||
}
|
||||
|
||||
void Activation::onStateChanges([[maybe_unused]] sdbusplus::message_t& msg)
|
||||
--
|
||||
2.25.1
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
bus=14
|
||||
address=0x53
|
||||
offset=0x08
|
||||
tmp=$(i2ctransfer -y -f $bus w2@$address $offset 0x00 r32)
|
||||
for str in $tmp;do
|
||||
if [[ $str != 0x00 ]]; then
|
||||
str=$(printf "%d" "$str")
|
||||
version=$(echo "$str" | awk '{printf("%c", $str)}')
|
||||
biosversion="$biosversion$version"
|
||||
fi
|
||||
done
|
||||
echo "BIOS version got from epprom:$biosversion"
|
||||
if [ "$biosversion" == "" ]; then
|
||||
echo "BIOS version is null, skip"
|
||||
else
|
||||
mapper wait /xyz/openbmc_project/software/bios_active
|
||||
busctl set-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/bios_active xyz.openbmc_project.Software.Version Version s "${biosversion}"
|
||||
echo "Restored BIOS version ${biosversion}"
|
||||
fi
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
[Service]
|
||||
ExecStartPost=/usr/bin/restore-bios-version.sh
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
bus=0
|
||||
address=0x0d
|
||||
offset=0x05
|
||||
str=$(i2ctransfer -y -a $bus w2@$address $offset 0x00 r1)
|
||||
version=${str:2:2}
|
||||
echo "CPLD version got from I2C:$version"
|
||||
if [ "$version" == "" ]; then
|
||||
echo "CPLD version is null, skip"
|
||||
else
|
||||
mapper wait /xyz/openbmc_project/software/cpld_active
|
||||
busctl set-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/cpld_active xyz.openbmc_project.Software.Version Version s ${version}
|
||||
echo "Restored CPLD version ${version}"
|
||||
fi
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
[Service]
|
||||
ExecStartPost=/usr/bin/restore-cpld-version.sh
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
bus=7
|
||||
address=0x7c
|
||||
offset=0x40
|
||||
str=$(i2ctransfer -y -a $bus w2@$address $offset 0x00 r1)
|
||||
version=${str:2:2}
|
||||
echo "Fan Board CPLD version got from I2C:$version"
|
||||
if [ "$version" == "" ]; then
|
||||
echo "Fan Board CPLD version is null, skip"
|
||||
else
|
||||
mapper wait /xyz/openbmc_project/software/fb_cpld_active
|
||||
busctl set-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/fb_cpld_active xyz.openbmc_project.Software.Version Version s ${version}
|
||||
echo "Restored Fan Board CPLD version ${version}"
|
||||
fi
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
[Service]
|
||||
ExecStartPost=/usr/bin/restore-fb-cpld-version.sh
|
||||
Reference in New Issue
Block a user