summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/flash
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/flash')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch41
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch225
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch411
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch415
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0009-Add-ApplyOptions-D-bus-property-under-Software.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0010-Add-error-reporting-to-pfr_image_manager.patch190
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0014-PFR-image-verification.patch116
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0016-Process-PLDM-image-type.patch234
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0017-Fix-build-error.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0018-Fix-delete-image-by-ID-and-inhibit-removal-of-bmc_ac.patch171
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0019-log-redfish-errors-on-all-pfr-image-auth-failures.patch100
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend30
18 files changed, 2273 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch
new file mode 100644
index 000000000..2a4c7e9b6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch
@@ -0,0 +1,44 @@
+From b6b3051c8078267153712ed8cf514373924fd07a Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Mon, 16 Jul 2018 19:15:04 -0700
+Subject: [PATCH 2/6] Redfish firmware activation -- Modified flash.cpp to
+ call to customized flash service
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Change-Id: I81c3185e9c4c2ee907feeb53620faa22723c04d4
+---
+ ubi/flash.cpp | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/ubi/flash.cpp b/ubi/flash.cpp
+index ffa9348..5af2a17 100644
+--- a/ubi/flash.cpp
++++ b/ubi/flash.cpp
+@@ -15,10 +15,13 @@ void Activation::flashWrite()
+ {
+ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+- method.append("obmc-flash-bmc-ubirw.service", "replace");
++ std::string rwServiceFile =
++ "obmc-flash-bmc-ubirw@" + versionId + ".service";
++ method.append(rwServiceFile, "replace");
+ bus.call_noreply(method);
+
+- auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
++ std::string roServiceFile =
++ "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+ method.append(roServiceFile, "replace");
+@@ -37,7 +40,7 @@ void Activation::onStateChanges(sdbusplus::message::message& msg)
+ // Read the msg and populate each variable
+ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+- auto rwServiceFile = "obmc-flash-bmc-ubirw.service";
++ auto rwServiceFile = "obmc-flash-bmc-ubirw@" + versionId + ".service";
+ auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ auto ubootVarsServiceFile =
+ "obmc-flash-bmc-updateubootvars@" + versionId + ".service";
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch
new file mode 100644
index 000000000..bcf692f5e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch
@@ -0,0 +1,41 @@
+From 1b00440d0c8fabfa2e3eda984a21c0f004ca2150 Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Fri, 26 Oct 2018 11:54:05 -0700
+Subject: [PATCH 4/6] Changed the condition of software version service
+ watching deamon
+
+ Originally it watches only files that are "written" into /tmp/images directory.
+This change modified the condition to also watch files that are "moved" into this directory.
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Change-Id: I3e9cf1ffc3f5350d4649d32d3d3837991322a65b
+---
+ watch.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/watch.cpp b/watch.cpp
+index e46b8aa..eee1bc3 100644
+--- a/watch.cpp
++++ b/watch.cpp
+@@ -46,7 +46,7 @@ Watch::Watch(sd_event* loop, std::function<int(std::string&)> imageCallback) :
+ std::strerror(error));
+ }
+
+- wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CLOSE_WRITE);
++ wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CLOSE_WRITE | IN_MOVED_TO);
+ if (-1 == wd)
+ {
+ auto error = errno;
+@@ -97,7 +97,8 @@ int Watch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
+ while (offset < bytes)
+ {
+ auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
+- if ((event->mask & IN_CLOSE_WRITE) && !(event->mask & IN_ISDIR))
++ if ((event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) &&
++ !(event->mask & IN_ISDIR))
+ {
+ auto tarballPath = std::string{IMG_UPLOAD_DIR} + '/' + event->name;
+ auto rc = static_cast<Watch*>(userdata)->imageCallback(tarballPath);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch
new file mode 100644
index 000000000..fcdc75f8f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch
@@ -0,0 +1,225 @@
+From 6e95f4a761021e3204912e3a7c5b80a18d9f16cf Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Mon, 10 Dec 2018 10:36:44 -0800
+Subject: [PATCH] Modified firmware activation to launch fwupd.sh through
+
+ non-ubi fs code path to match more closely to the upstream design -
+ Added option FWUPD_SCRIPT to saperate intel customized code - Adopted
+ ActivationProgress from ubi fs activation code mainly for progress indicator
+ for ipmi update
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ activation.cpp | 50 +++++++++++++++++++++++++++++++++++++----------
+ meson.build | 2 ++
+ meson_options.txt | 3 +++
+ static/flash.cpp | 42 +++++++++++++++++++++++++++++++++++++--
+ ubi/flash.cpp | 9 +++------
+ 5 files changed, 88 insertions(+), 18 deletions(-)
+
+diff --git a/activation.cpp b/activation.cpp
+index 5490cd9974b3..e43959d78ed2 100644
+--- a/activation.cpp
++++ b/activation.cpp
+@@ -88,20 +88,50 @@ auto Activation::activation(Activations value) -> Activations
+
+ if (value == softwareServer::Activation::Activations::Activating)
+ {
+-#ifdef WANT_SIGNATURE_VERIFY
+- fs::path uploadDir(IMG_UPLOAD_DIR);
+- if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
++#ifdef FWUPD_SCRIPT
++ if (!activationProgress)
+ {
+- onVerifyFailed();
+- // Stop the activation process, if fieldMode is enabled.
+- if (parent.control::FieldMode::fieldModeEnabled())
++ // Enable systemd signals
++ Activation::subscribeToSystemdSignals();
++ parent.freeSpace(*this);
++
++ activationProgress =
++ std::make_unique<ActivationProgress>(bus, path);
++
++#ifdef WANT_SIGNATURE_VERIFY
++ fs::path uploadDir(IMG_UPLOAD_DIR);
++ if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
+ {
+- return softwareServer::Activation::activation(
+- softwareServer::Activation::Activations::Failed);
++ onVerifyFailed();
++ // Stop the activation process, if fieldMode is enabled.
++ if (parent.control::FieldMode::fieldModeEnabled())
++ {
++ return softwareServer::Activation::activation(
++ softwareServer::Activation::Activations::Failed);
++ }
+ }
+- }
+ #endif
++ flashWrite();
++ }
++ else if (activationProgress->progress() == 100)
++ {
++ error("progress == 100...");
++ if (!redundancyPriority)
++ {
++ redundancyPriority =
++ std::make_unique<RedundancyPriority>(bus, path, *this, 0);
++ }
++
++ // Remove version object from image manager
++ Activation::deleteImageManagerObject();
+
++ // Create active association
++ parent.createActiveAssociation(path);
++
++ return softwareServer::Activation::activation(
++ softwareServer::Activation::Activations::Active);
++ }
++#else // !FWUPD_SCRIPT
+ #ifdef HOST_BIOS_UPGRADE
+ auto purpose = parent.versions.find(versionId)->second->purpose();
+ if (purpose == VersionPurpose::Host)
+@@ -124,7 +154,6 @@ auto Activation::activation(Activations value) -> Activations
+ return softwareServer::Activation::activation(value);
+ }
+ #endif
+-
+ auto versionStr = parent.versions.find(versionId)->second->version();
+
+ if (!minimum_ship_level::verify(versionStr))
+@@ -174,6 +203,7 @@ auto Activation::activation(Activations value) -> Activations
+ return softwareServer::Activation::activation(
+ softwareServer::Activation::Activations::Active);
+ #endif
++#endif // FWUPD_SCRIPT
+ }
+ else
+ {
+diff --git a/meson.build b/meson.build
+index a6ebcc43c0ec..5c7900924959 100644
+--- a/meson.build
++++ b/meson.build
+@@ -59,6 +59,8 @@ conf.set('WANT_SIGNATURE_VERIFY', \
+ get_option('verify-full-signature').enabled())
+ conf.set('WANT_SIGNATURE_FULL_VERIFY', get_option('verify-full-signature').enabled())
+
++conf.set('FWUPD_SCRIPT', get_option('fwupd-script').enabled())
++
+ # Configurable variables
+ conf.set('ACTIVE_BMC_MAX_ALLOWED', get_option('active-bmc-max-allowed'))
+ conf.set_quoted('HASH_FILE_NAME', get_option('hash-file-name'))
+diff --git a/meson_options.txt b/meson_options.txt
+index 4def7f982809..74e757b75f01 100644
+--- a/meson_options.txt
++++ b/meson_options.txt
+@@ -25,6 +25,9 @@ option('verify-signature', type: 'feature',
+ option('verify-full-signature', type: 'feature',
+ description: 'Enable image full signature validation.')
+
++option('fwupd-script', type: 'feature',
++ description: 'Enable fwupd script support.')
++
+ # Variables
+ option(
+ 'active-bmc-max-allowed', type: 'integer',
+diff --git a/static/flash.cpp b/static/flash.cpp
+index 101828b1ade5..5506a59ac499 100644
+--- a/static/flash.cpp
++++ b/static/flash.cpp
+@@ -22,9 +22,11 @@ namespace updater
+
+ namespace fs = std::filesystem;
+ using namespace phosphor::software::image;
++namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
+
+ void Activation::flashWrite()
+ {
++#ifndef FWUPD_SCRIPT
+ // 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.
+@@ -36,11 +38,47 @@ void Activation::flashWrite()
+ fs::copy_file(uploadDir / versionId / bmcImage, toPath / bmcImage,
+ fs::copy_options::overwrite_existing);
+ }
++
++#else
++ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
++ SYSTEMD_INTERFACE, "StartUnit");
++ method.append("fwupd@" + versionId + ".service", "replace");
++ bus.call_noreply(method);
++#endif
+ }
+
+-void Activation::onStateChanges(sdbusplus::message::message& /*msg*/)
++void Activation::onStateChanges(__attribute__((unused))
++ sdbusplus::message::message& msg)
+ {
+- // Empty
++#ifndef FWUPD_SCRIPT
++ uint32_t newStateID{};
++ sdbusplus::message::object_path newStateObjPath;
++ std::string newStateUnit{};
++ std::string newStateResult{};
++
++ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
++
++ auto rwServiceFile = "fwupdw@" + versionId + ".service";
++
++ if (newStateUnit == rwServiceFile && newStateResult == "done")
++ {
++ activationProgress->progress(100);
++ }
++
++ if (newStateUnit == rwServiceFile)
++ {
++ if (newStateResult == "failed" || newStateResult == "dependency")
++ {
++ Activation::activation(
++ softwareServer::Activation::Activations::Failed);
++ }
++ else
++ {
++ Activation::activation(
++ softwareServer::Activation::Activations::Activating);
++ }
++ }
++#endif
+ }
+
+ } // namespace updater
+diff --git a/ubi/flash.cpp b/ubi/flash.cpp
+index a263bfb81116..c58eefc4ec48 100644
+--- a/ubi/flash.cpp
++++ b/ubi/flash.cpp
+@@ -15,13 +15,10 @@ void Activation::flashWrite()
+ {
+ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+- std::string rwServiceFile =
+- "obmc-flash-bmc-ubirw@" + versionId + ".service";
+- method.append(rwServiceFile, "replace");
++ method.append("obmc-flash-bmc-ubirw.service", "replace");
+ bus.call_noreply(method);
+
+- std::string roServiceFile =
+- "obmc-flash-bmc-ubiro@" + versionId + ".service";
++ auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+ method.append(roServiceFile, "replace");
+@@ -40,7 +37,7 @@ void Activation::onStateChanges(sdbusplus::message::message& msg)
+ // Read the msg and populate each variable
+ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+- auto rwServiceFile = "obmc-flash-bmc-ubirw@" + versionId + ".service";
++ auto rwServiceFile = "obmc-flash-bmc-ubirw.service";
+ auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ auto ubootVarsServiceFile =
+ "obmc-flash-bmc-updateubootvars@" + versionId + ".service";
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch
new file mode 100644
index 000000000..1f2a86fb9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch
@@ -0,0 +1,44 @@
+From 9b3c44e9fb3d907c0152f14b967e23ab964c0e0b Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Thu, 14 Feb 2019 14:54:45 -0800
+Subject: [PATCH 6/6] Modify the ID of software image updater object on DBus to
+ allow force update onto same version image
+
+In the original design of image update, it does not allow the same version of image to be flashed onto itself.
+But this blocks validation tests and in most of the cases we don't prevent user from doing such update.
+
+This patch appends a random number after the version ID hash string to unblock such limitation.
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Change-Id: I16aba4804ae1bc2e8784320f91c0419fb8b23c35
+---
+ image_manager.cpp | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/image_manager.cpp b/image_manager.cpp
+index 5b2ff49..e3d26e3 100644
+--- a/image_manager.cpp
++++ b/image_manager.cpp
+@@ -9,6 +9,7 @@
+ #include <stdlib.h>
+ #include <sys/stat.h>
+ #include <sys/wait.h>
++#include <time.h>
+ #include <unistd.h>
+
+ #include <elog-errors.hpp>
+@@ -174,6 +175,11 @@ int Manager::processImage(const std::string& tarFilePath)
+ // Compute id
+ auto id = Version::getId(version);
+
++ // Append a random number after the original version hash
++ // This will allow forcing image update onto the same version
++ srand(time(NULL));
++ id = id + "_" + std::to_string(rand());
++
+ fs::path imageDirPath = std::string{IMG_UPLOAD_DIR};
+ imageDirPath /= id;
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch
new file mode 100644
index 000000000..6039be44b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch
@@ -0,0 +1,76 @@
+From c2ae3ac444f7a5e9674a82f47086874f947bcec6 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+Date: Thu, 5 Dec 2019 12:38:21 +0530
+Subject: [PATCH] Adding StandBySpare for firmware activation
+
+Added new states 'StandBySpare', 'ActivatingAsStandbySpare' for
+firmware activation. If the uploaded firmware image is for
+backup/recovery, then it sets the "StandBySpare" value for
+Activations. When backup/recovery image is in activating state,
+then activations will be set to "ActivatingAsStandbySpare".
+
+Tested:
+Tested using redfish interface.
+Did the GET on "/redfish/v1/UpdateService/FirmwareInventory/<backup image>"
+Response:
+ ....
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "StandbySpare"
+ }
+.......
+
+Change-Id: I7f1608fac3196774a6d593b6128d58da3f5c88fc
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+---
+ activation.cpp | 22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+diff --git a/activation.cpp b/activation.cpp
+index 2966b2f..a098784 100644
+--- a/activation.cpp
++++ b/activation.cpp
+@@ -81,12 +81,16 @@ void Activation::unsubscribeFromSystemdSignals()
+ auto Activation::activation(Activations value) -> Activations
+ {
+ if ((value != softwareServer::Activation::Activations::Active) &&
+- (value != softwareServer::Activation::Activations::Activating))
++ (value != softwareServer::Activation::Activations::Activating) &&
++ (value !=
++ softwareServer::Activation::Activations::ActivatingAsStandbySpare))
+ {
+ redundancyPriority.reset(nullptr);
+ }
+
+- if (value == softwareServer::Activation::Activations::Activating)
++ if (value == softwareServer::Activation::Activations::Activating ||
++ value ==
++ softwareServer::Activation::Activations::ActivatingAsStandbySpare)
+ {
+ #ifdef FWUPD_SCRIPT
+ if (!activationProgress)
+@@ -309,6 +313,20 @@ auto Activation::requestedActivation(RequestedActivations value)
+ softwareServer::Activation::Activations::Activating);
+ }
+ }
++ else if ((value ==
++ softwareServer::Activation::RequestedActivations::StandbySpare) &&
++ (softwareServer::Activation::requestedActivation() !=
++ softwareServer::Activation::RequestedActivations::StandbySpare))
++ {
++ if ((softwareServer::Activation::activation() ==
++ softwareServer::Activation::Activations::Ready) ||
++ (softwareServer::Activation::activation() ==
++ softwareServer::Activation::Activations::Failed))
++ {
++ Activation::activation(softwareServer::Activation::Activations::
++ ActivatingAsStandbySpare);
++ }
++ }
+ return softwareServer::Activation::requestedActivation(value);
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch
new file mode 100644
index 000000000..e1a7f1746
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch
@@ -0,0 +1,411 @@
+From 51fd06346ff492d5d4862886cb34e024d05edb45 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Tue, 13 Aug 2019 22:43:12 +0530
+Subject: [PATCH] PFR images support in phosphor-software-manager
+
+This commit adds support for handling the PFR images
+upload and processing.
+
+Testing:
+tested PFR image uploads and updates
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+
+---
+ item_updater.cpp | 7 +-
+ meson.build | 8 +-
+ meson_options.txt | 3 +
+ pfr_image_manager.cpp | 218 ++++++++++++++++++++++++++++++++++++++++++
+ pfr_image_manager.hpp | 76 +++++++++++++++
+ 5 files changed, 308 insertions(+), 4 deletions(-)
+ create mode 100644 pfr_image_manager.cpp
+ create mode 100644 pfr_image_manager.hpp
+
+diff --git a/item_updater.cpp b/item_updater.cpp
+index 81fc01f..60e7d23 100644
+--- a/item_updater.cpp
++++ b/item_updater.cpp
+@@ -65,10 +65,10 @@ void ItemUpdater::createActivation(sdbusplus::message::message& msg)
+ auto value = SVersion::convertVersionPurposeFromString(
+ std::get<std::string>(property.second));
+ if (value == VersionPurpose::BMC ||
+-#ifdef HOST_BIOS_UPGRADE
++#if defined(HOST_BIOS_UPGRADE) || defined(PFR_UPDATE)
+ value == VersionPurpose::Host ||
+ #endif
+- value == VersionPurpose::System)
++ value == VersionPurpose::Other)
+ {
+ purpose = value;
+ }
+@@ -414,6 +414,7 @@ void ItemUpdater::deleteAll()
+ ItemUpdater::ActivationStatus
+ ItemUpdater::validateSquashFSImage(const std::string& filePath)
+ {
++#ifndef PFR_UPDATE
+ bool valid = true;
+
+ // Record the images which are being updated
+@@ -431,7 +432,7 @@ ItemUpdater::ActivationStatus
+ return ItemUpdater::ActivationStatus::invalid;
+ }
+ }
+-
++#endif
+ return ItemUpdater::ActivationStatus::ready;
+ }
+
+diff --git a/meson.build b/meson.build
+index 5c79009..e33998d 100644
+--- a/meson.build
++++ b/meson.build
+@@ -60,6 +60,7 @@ conf.set('WANT_SIGNATURE_VERIFY', \
+ conf.set('WANT_SIGNATURE_FULL_VERIFY', get_option('verify-full-signature').enabled())
+
+ conf.set('FWUPD_SCRIPT', get_option('fwupd-script').enabled())
++conf.set('PFR_UPDATE', get_option('pfr-update').enabled())
+
+ # Configurable variables
+ conf.set('ACTIVE_BMC_MAX_ALLOWED', get_option('active-bmc-max-allowed'))
+@@ -205,12 +206,17 @@ executable(
+ install: true
+ )
+
++image_manager_source = files('image_manager.cpp')
++if get_option('pfr-update').enabled()
++ image_manager_source = files('pfr_image_manager.cpp')
++endif
++
+ executable(
+ 'phosphor-version-software-manager',
+ image_error_cpp,
+ image_error_hpp,
+- 'image_manager.cpp',
+ 'image_manager_main.cpp',
++ image_manager_source,
+ 'version.cpp',
+ 'watch.cpp',
+ dependencies: [deps, ssl],
+diff --git a/meson_options.txt b/meson_options.txt
+index da257b7..2204e04 100644
+--- a/meson_options.txt
++++ b/meson_options.txt
+@@ -28,6 +28,9 @@ option('verify-full-signature', type: 'feature',
+ option('fwupd-script', type: 'feature',
+ description: 'Enable fwupd script support.')
+
++option('pfr-update', type: 'feature',
++ description: 'Enable PFR image support.')
++
+ # Variables
+ option(
+ 'active-bmc-max-allowed', type: 'integer',
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+new file mode 100644
+index 0000000..fec1e94
+--- /dev/null
++++ b/pfr_image_manager.cpp
+@@ -0,0 +1,218 @@
++#include "config.h"
++
++#include "pfr_image_manager.hpp"
++
++#include "version.hpp"
++#include "watch.hpp"
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/stat.h>
++#include <sys/wait.h>
++#include <time.h>
++#include <unistd.h>
++
++#include <elog-errors.hpp>
++#include <xyz/openbmc_project/Software/Image/error.hpp>
++
++#include <algorithm>
++#include <cstring>
++#include <filesystem>
++#include <fstream>
++#include <iomanip>
++#include <sstream>
++#include <string>
++
++namespace phosphor
++{
++namespace software
++{
++namespace manager
++{
++
++using namespace sdbusplus::xyz::openbmc_project::Software::Image::Error;
++namespace Software = phosphor::logging::xyz::openbmc_project::Software;
++
++static constexpr const uint32_t pfmPos = 2054;
++
++static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
++ std::string& version)
++{
++ struct pfrImgBlock0 block0Data;
++ uint8_t verData[2];
++
++ if (std::filesystem::exists(imgPath))
++ {
++ try
++ {
++ std::ifstream imgFile(imgPath, std::ios::binary | std::ios::in);
++
++ if (!imgFile.good())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Image file read failed");
++ return -1;
++ }
++
++ imgFile.read(reinterpret_cast<char*>(&block0Data),
++ sizeof(block0Data));
++ imgType = block0Data.pcType[0];
++ imgFile.seekg(pfmPos,
++ std::ios::beg); // Version is at 0x806 in the PFM
++ imgFile.read(reinterpret_cast<char*>(&verData), sizeof(verData));
++ imgFile.close();
++ version =
++ std::to_string(verData[0]) + "." + std::to_string(verData[1]);
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "PFR image",
++ phosphor::logging::entry("PCType=%d", block0Data.pcType[0]),
++ phosphor::logging::entry("VERSION=%s", version.c_str()));
++ }
++ catch (std::exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++int Manager::processImage(const std::string& imgFilePath)
++{
++ std::filesystem::path imgPath(imgFilePath);
++
++ if (!std::filesystem::exists(imgPath))
++ return -1;
++
++ uint8_t imgType;
++ int retry = 3;
++ std::string ver;
++ std::string purposeString;
++
++ if (0 != getPFRImgInfo(imgFilePath, imgType, ver))
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error reading uploaded image type and version");
++ return -1;
++ }
++
++ if (ver.empty())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Empty version from image file");
++ return -1;
++ }
++
++ if (imgType == pfrBMCUpdateCap)
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.BMC";
++ }
++ else if (imgType == pfrPCHUpdateCap)
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Host";
++ }
++ else if (imgType == pfrCPLDUpdateCap)
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Other";
++ }
++ else
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Unknown";
++
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unknown image type");
++ return -1;
++ }
++
++ sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
++ purpose = Version::VersionPurpose::Unknown;
++ try
++ {
++ purpose = Version::convertVersionPurposeFromString(purposeString);
++ }
++ catch (const sdbusplus::exception::InvalidEnumString& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: Failed to convert purpose to enum."
++ " Setting to Unknown.");
++ }
++
++ // Compute id
++ std::string id = Version::getId(ver);
++
++ // Append a random number after the original version hash
++ // This will allow forcing image update onto the same version
++ // with 3 retries on random number generation.
++ do
++ {
++ srand(time(NULL));
++ id = id + "_" + std::to_string(rand());
++ } while ((versions.find(id) != versions.end()) && retry--);
++
++ if (versions.find(id) != versions.end())
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Software Object with the same version already exists, exiting "
++ "the update",
++ phosphor::logging::entry("VERSION_ID=%s", id.c_str()));
++
++ return -1;
++ }
++
++ std::filesystem::path imageDirPath(IMG_UPLOAD_DIR);
++ imageDirPath /= id;
++
++ std::filesystem::create_directory(imageDirPath);
++
++ std::filesystem::path newFileName = imageDirPath / "image-runtime";
++ std::filesystem::rename(imgFilePath, newFileName);
++
++ // Create Version object
++ std::string objPath = std::string{SOFTWARE_OBJPATH} + '/' + id;
++
++ auto versionPtr = std::make_unique<Version>(
++ bus, objPath, ver, purpose, imageDirPath.string(),
++ std::bind(&Manager::erase, this, std::placeholders::_1));
++ versionPtr->deleteObject =
++ std::make_unique<phosphor::software::manager::Delete>(bus, objPath,
++ *versionPtr);
++ versions.insert(std::make_pair(id, std::move(versionPtr)));
++
++ return 0;
++}
++
++void Manager::erase(std::string entryId)
++{
++ auto it = versions.find(entryId);
++ if (it == versions.end())
++ {
++ return;
++ }
++
++ if (it->second->isFunctional())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ ("Error: Version " + entryId +
++ " is currently running on the BMC."
++ " Unable to remove.")
++ .c_str());
++ return;
++ }
++
++ // Delete image dir
++ std::filesystem::path imageDirPath = (*(it->second)).path();
++ if (std::filesystem::exists(imageDirPath))
++ {
++ std::filesystem::remove_all(imageDirPath);
++ }
++ this->versions.erase(entryId);
++}
++
++} // namespace manager
++} // namespace software
++} // namespace phosphor
+diff --git a/pfr_image_manager.hpp b/pfr_image_manager.hpp
+new file mode 100644
+index 0000000..b9a5822
+--- /dev/null
++++ b/pfr_image_manager.hpp
+@@ -0,0 +1,76 @@
++#pragma once
++#include "version.hpp"
++
++#include <sdbusplus/server.hpp>
++
++namespace phosphor
++{
++namespace software
++{
++namespace manager
++{
++
++enum pfrImgPCType
++{
++ pfrCPLDUpdateCap = 0x00,
++ pfrPCHPFM = 0x01,
++ pfrPCHUpdateCap = 0x02,
++ pfrBMCPFM = 0x03,
++ pfrBMCUpdateCap = 0x04
++};
++
++/* PFR image block 0 - As defined in HAS */
++struct pfrImgBlock0
++{
++ uint8_t tag[4];
++ uint8_t pcLength[4];
++ uint8_t pcType[4];
++ uint8_t reserved1[4];
++ uint8_t hash256[32];
++ uint8_t hash384[48];
++ uint8_t reserved2[32];
++} __attribute__((packed));
++
++/** @class Manager
++ * @brief Contains a map of Version dbus objects.
++ * @details The software image manager class that contains the Version dbus
++ * objects and their version ids.
++ */
++class Manager
++{
++ public:
++ /** @brief Constructs Manager Class
++ *
++ * @param[in] bus - The Dbus bus object
++ */
++ Manager(sdbusplus::bus::bus& bus) : bus(bus){};
++
++ /**
++ * @brief Verify the image and provide the image to updater.
++ * Create and populate the version and file path interfaces.
++ *
++ * @param[in] uploaded image.
++ * @param[out] result - 0 if successful.
++ */
++ int processImage(const std::string& imageFilePath);
++
++ /**
++ * @brief Erase specified entry d-bus object
++ * and deletes the image file.
++ *
++ * @param[in] entryId - unique identifier of the entry
++ */
++ void erase(std::string entryId);
++
++ private:
++ /** @brief Persistent map of Version dbus objects and their
++ * version id */
++ std::map<std::string, std::unique_ptr<Version>> versions;
++
++ /** @brief Persistent sdbusplus DBus bus connection. */
++ sdbusplus::bus::bus& bus;
++};
++
++} // namespace manager
++} // namespace software
++} // namespace phosphor
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch
new file mode 100644
index 000000000..72eb0beba
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch
@@ -0,0 +1,415 @@
+From ac6e0c217a1b136d82f93b691aff1acb40009f26 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+Date: Thu, 5 Dec 2019 11:55:36 +0530
+Subject: [PATCH] PFR image HASH verification
+
+This adds HASH verification on PFR images uploaded for
+firmware updates
+
+Tested: tested firmware update with good and bad HASH images.
+
+A)
+1. Upload the corrupted image for fw update.
+2. Image present in /tmp/images/
+-rw-r--r-- 1 root root 22969344 Jun 3 09:27
+5dea710b-8b85-4065-8af7-3149ada81edf
+
+3. Journalctl logs during image verification
+Jun 03 09:27:20 intel-obmc phosphor-version-software-manager[4755]:
+Firmware image HASH verification failed
+Jun 03 09:27:20 intel-obmc phosphor-version-software-manager[4755]:
+Error verifying uploaded image
+Jun 03 09:27:20 intel-obmc phosphor-version-software-manager[4755]:
+Error processing image
+
+4. image deleted from /tmp/images/
+
+B)
+1. Upload the correct image.
+POST: https://<BMC_IP>/redfish/v1/UpdateService/
+ with <BMC_signed_cap> binary file
+2. Image verification is success and proceeds with update.
+{
+ "@odata.id": "/redfish/v1/TaskService/Tasks/0",
+ "@odata.type": "#Task.v1_4_3.Task",
+ "Id": "0",
+ "TaskState": "Running",
+ "TaskStatus": "OK"
+}
+
+Change-Id: I9336980bfb74c8136690024782bfef45f6b08d56
+Signed-off-by: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+---
+ pfr_image_manager.cpp | 150 +++++++++++++++++++++++++++++++++----------
+ pfr_image_manager.hpp | 112 +++++++++++++++++++++++++++++--
+ 2 files changed, 222 insertions(+), 40 deletions(-)
+
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index 242a6ca..1a41cbe 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -5,6 +5,8 @@
+ #include "version.hpp"
+ #include "watch.hpp"
+
++#include <fcntl.h>
++#include <openssl/err.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sys/stat.h>
+@@ -20,6 +22,7 @@
+ #include <filesystem>
+ #include <fstream>
+ #include <iomanip>
++#include <set>
+ #include <sstream>
+ #include <string>
+
+@@ -34,12 +37,21 @@ using namespace sdbusplus::xyz::openbmc_project::Software::Image::Error;
+ namespace Software = phosphor::logging::xyz::openbmc_project::Software;
+
+ static constexpr const uint32_t pfmPos = 2054;
++static constexpr const uint32_t block0Magic = 0xB6EAFD19;
++static constexpr const uint32_t lengthBlk0Blk1 = 1024;
+
+-static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
+- std::string& version)
++int Manager::verifyPFRImage(const std::filesystem::path imgPath,
++ std::string& version, std::string& purposeString)
+ {
+- struct pfrImgBlock0 block0Data;
+- uint8_t verData[2];
++ uint8_t imgType = 0;
++ uint32_t imgMagic = 0;
++ uint8_t verData[2] = {0};
++ uint32_t hashLen = 0;
++ struct pfrImgBlock0 block0Data = {};
++
++ std::string imageName;
++
++ EVP_MD_CTX* ctx;
+
+ if (std::filesystem::exists(imgPath))
+ {
+@@ -56,17 +68,101 @@ static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
+
+ imgFile.read(reinterpret_cast<char*>(&block0Data),
+ sizeof(block0Data));
++
++ imgMagic = block0Data.tag;
++
++ if (imgMagic != block0Magic)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Image magic number match failed",
++ phosphor::logging::entry("IMAGEMAGIC=0x%x", imgMagic));
++ return -1;
++ }
++
+ imgType = block0Data.pcType[0];
++
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Image Type", phosphor::logging::entry(
++ "IMAGETYPE=0x%x", static_cast<int>(imgType)));
++
++ if (imgType == pfrBMCUpdateCap || imgType == pfrBMCPFM)
++ {
++ imageName = "BMC";
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.BMC";
++ }
++ else if (imgType == pfrPCHUpdateCap || imgType == pfrPCHPFM)
++ {
++ imageName = "BIOS";
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Host";
++ }
++ else if (imgType == pfrCPLDUpdateCap)
++ {
++ imageName = "CPLD";
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Other";
++ }
++ else
++ {
++ purposeString = "xyz.openbmc_project.Software.Version."
++ "VersionPurpose.Unknown";
++
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unknown image type");
++ return -1;
++ }
++
+ imgFile.seekg(pfmPos,
+ std::ios::beg); // Version is at 0x806 in the PFM
+ imgFile.read(reinterpret_cast<char*>(&verData), sizeof(verData));
+ imgFile.close();
+- version =
+- std::to_string(verData[0]) + "." + std::to_string(verData[1]);
++
++ auto size = std::filesystem::file_size(imgPath);
++
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Image Size", phosphor::logging::entry("IMAGESIZE=0x%x",
++ static_cast<int>(size)));
++
++ // Adds all digest algorithms to the internal table
++ OpenSSL_add_all_digests();
++
++ ctx = EVP_MD_CTX_create();
++ EVP_DigestInit(ctx, EVP_sha256());
++
++ // Hash the image file and update the digest
++ auto dataPtr = mapFile(imgPath, size);
++
++ EVP_DigestUpdate(ctx, ((uint8_t*)dataPtr() + lengthBlk0Blk1),
++ (size - lengthBlk0Blk1));
++
++ std::vector<uint8_t> digest(EVP_MD_size(EVP_sha256()));
++ std::vector<uint8_t> expectedDigest(block0Data.hash256,
++ &block0Data.hash256[0] + 32);
++
++ EVP_DigestFinal(ctx, digest.data(), &hashLen);
++ EVP_MD_CTX_destroy(ctx);
++
++ std::string redfishMsgID = "OpenBMC.0.1";
++
++ if (expectedDigest != digest)
++ {
++ redfishMsgID += ".GeneralFirmwareSecurityViolation";
++ sd_journal_send("MESSAGE=%s",
++ "Firmware image HASH verification failed",
++ "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s",
++ redfishMsgID.c_str(), "REDFISH_MESSAGE_ARGS=%s",
++ "Image HASH check fail", NULL);
++ return -1;
++ }
++
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "PFR image",
+ phosphor::logging::entry("PCType=%d", block0Data.pcType[0]),
+ phosphor::logging::entry("VERSION=%s", version.c_str()));
++
++ version =
++ std::to_string(verData[0]) + "." + std::to_string(verData[1]);
+ }
+ catch (std::exception& e)
+ {
+@@ -80,20 +176,21 @@ static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
+
+ int Manager::processImage(const std::string& imgFilePath)
+ {
++
+ std::filesystem::path imgPath(imgFilePath);
+
+ if (!std::filesystem::exists(imgPath))
+ return -1;
+
+- uint8_t imgType;
+ int retry = 3;
+ std::string ver;
+ std::string purposeString;
+
+- if (0 != getPFRImgInfo(imgFilePath, imgType, ver))
++ if (0 != verifyPFRImage(imgFilePath, ver, purposeString))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+- "Error reading uploaded image type and version");
++ "Error verifying uploaded image");
++ std::filesystem::remove_all(imgFilePath);
+ return -1;
+ }
+
+@@ -104,31 +201,6 @@ int Manager::processImage(const std::string& imgFilePath)
+ return -1;
+ }
+
+- if (imgType == pfrBMCUpdateCap)
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.BMC";
+- }
+- else if (imgType == pfrPCHUpdateCap)
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.Host";
+- }
+- else if (imgType == pfrCPLDUpdateCap)
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.Other";
+- }
+- else
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.Unknown";
+-
+- phosphor::logging::log<phosphor::logging::level::ERR>(
+- "Unknown image type");
+- return -1;
+- }
+-
+ sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
+ purpose = Version::VersionPurpose::Unknown;
+ try
+@@ -170,6 +242,7 @@ int Manager::processImage(const std::string& imgFilePath)
+ std::filesystem::create_directory(imageDirPath);
+
+ std::filesystem::path newFileName = imageDirPath / "image-runtime";
++
+ std::filesystem::rename(imgFilePath, newFileName);
+
+ // Create Version object
+@@ -213,6 +286,14 @@ void Manager::erase(std::string entryId)
+ this->versions.erase(entryId);
+ }
+
++CustomMap Manager::mapFile(const std::filesystem::path& path, size_t size)
++{
++
++ CustomFd fd(open(path.c_str(), O_RDONLY));
++
++ return CustomMap(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd(), 0),
++ size);
++}
+ } // namespace manager
+ } // namespace software
+ } // namespace phosphor
+diff --git a/pfr_image_manager.hpp b/pfr_image_manager.hpp
+index c6ee6a4..5b7b2c3 100644
+--- a/pfr_image_manager.hpp
++++ b/pfr_image_manager.hpp
+@@ -1,8 +1,16 @@
+ #pragma once
+ #include "version.hpp"
+
++#include <openssl/evp.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <sys/mman.h>
++#include <unistd.h>
++
+ #include <sdbusplus/server.hpp>
+
++#include <filesystem>
++
+ namespace phosphor
+ {
+ namespace software
+@@ -22,7 +30,7 @@ enum pfrImgPCType
+ /* PFR image block 0 - As defined in HAS */
+ struct pfrImgBlock0
+ {
+- uint8_t tag[4];
++ uint32_t tag;
+ uint8_t pcLength[4];
+ uint8_t pcType[4];
+ uint8_t reserved1[4];
+@@ -31,6 +39,82 @@ struct pfrImgBlock0
+ uint8_t reserved2[32];
+ } __attribute__((packed));
+
++/** @struct CustomFd
++ *
++ * RAII wrapper for file descriptor.
++ */
++struct CustomFd
++{
++ public:
++ CustomFd() = delete;
++ CustomFd(const CustomFd&) = delete;
++ CustomFd& operator=(const CustomFd&) = delete;
++ CustomFd(CustomFd&&) = default;
++ CustomFd& operator=(CustomFd&&) = default;
++ /** @brief Saves File descriptor and uses it to do file operation
++ *
++ * @param[in] fd - File descriptor
++ */
++ CustomFd(int fd) : fd(fd)
++ {}
++
++ ~CustomFd()
++ {
++ if (fd >= 0)
++ {
++ close(fd);
++ }
++ }
++
++ int operator()() const
++ {
++ return fd;
++ }
++
++ private:
++ /** @brief File descriptor */
++ int fd = -1;
++};
++
++/** @struct CustomMap
++ *
++ * RAII wrapper for mmap.
++ */
++struct CustomMap
++{
++ private:
++ /** @brief starting address of the map */
++ void* addr;
++
++ /** @brief length of the mapping */
++ size_t length;
++
++ public:
++ CustomMap() = delete;
++ CustomMap(const CustomMap&) = delete;
++ CustomMap& operator=(const CustomMap&) = delete;
++ CustomMap(CustomMap&&) = default;
++ CustomMap& operator=(CustomMap&&) = default;
++
++ /** @brief Saves starting address of the map and
++ * and length of the file.
++ * @param[in] addr - Starting address of the map
++ * @param[in] length - length of the map
++ */
++ CustomMap(void* addr, size_t length) : addr(addr), length(length)
++ {}
++
++ ~CustomMap()
++ {
++ munmap(addr, length);
++ }
++
++ void* operator()() const
++ {
++ return addr;
++ }
++};
++
+ /** @class Manager
+ * @brief Contains a map of Version dbus objects.
+ * @details The software image manager class that contains the Version dbus
+@@ -63,6 +147,22 @@ class Manager
+ void erase(std::string entryId);
+
+ private:
++ /**
++ * @brief Memory map the file
++ * @param[in] - file path
++ * @param[in] - file size
++ * @param[out] - Custom Mmap address
++ */
++ CustomMap mapFile(const std::filesystem::path& path, size_t size);
++
++ /**
++ * @brief Verify the PFR image and return version and purpose
++ * @param[in] - file path
++ * @param[out] - version
++ * @param[out] - purpose
++ */
++ int verifyPFRImage(const std::filesystem::path imgPath,
++ std::string& version, std::string& purposeString);
+ /** @brief Persistent map of Version dbus objects and their
+ * version id */
+ std::map<std::string, std::unique_ptr<Version>> versions;
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch
new file mode 100644
index 000000000..e0ff79795
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch
@@ -0,0 +1,50 @@
+From d9e50ecf8bd8bc764838e7244084184644a3f0fc Mon Sep 17 00:00:00 2001
+From: Chalapathi <chalapathix.venkataramashetty@intel.com>
+Date: Thu, 23 Apr 2020 19:06:19 +0000
+Subject: [PATCH] item_updater: update the bmc_active objectPath
+
+Update the Software object path to bmc_active instead of random Id.
+
+Signed-off-by: Chalapathi <chalapathix.venkataramashetty@intel.com>
+
+---
+ item_updater.cpp | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/item_updater.cpp b/item_updater.cpp
+index e6dd298..c3a846d 100644
+--- a/item_updater.cpp
++++ b/item_updater.cpp
+@@ -175,7 +175,8 @@ void ItemUpdater::processBMCImage()
+ if (0 ==
+ iter.path().native().compare(0, BMC_RO_PREFIX_LEN, BMC_ROFS_PREFIX))
+ {
+- // Get the version to calculate the id
++ std::string id = "bmc_active";
++ // upstream changed this to relative_path ... is that right?
+ fs::path releaseFile(OS_RELEASE_FILE);
+ auto osRelease = iter.path() / releaseFile.relative_path();
+ if (!fs::is_regular_file(osRelease))
+@@ -189,7 +190,6 @@ void ItemUpdater::processBMCImage()
+ // volumes created by the UBI layout for example have the id in
+ // the mount directory name. The worst that can happen is that
+ // erase() is called with an non-existent id and returns.
+- auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
+ ItemUpdater::erase(id);
+
+ continue;
+@@ -203,14 +203,11 @@ void ItemUpdater::processBMCImage()
+
+ // Try to delete the version, same as above if the
+ // OS_RELEASE_FILE does not exist.
+- auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
+ ItemUpdater::erase(id);
+
+ continue;
+ }
+
+- auto id = VersionClass::getId(version);
+-
+ // Check if the id has already been added. This can happen if the
+ // BMC partitions / devices were manually flashed with the same
+ // image.
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0009-Add-ApplyOptions-D-bus-property-under-Software.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0009-Add-ApplyOptions-D-bus-property-under-Software.patch
new file mode 100644
index 000000000..f150c1027
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0009-Add-ApplyOptions-D-bus-property-under-Software.patch
@@ -0,0 +1,44 @@
+From 76f169e71be10b50b9617e606c38aff9553e6de8 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Fri, 15 May 2020 21:17:08 +0530
+Subject: [PATCH] Add ApplyOptions D-bus property under Software
+
+This change adds the ApplyOptions D-bus property
+under xyz.openbmc_project.Software.BMC.Updater.
+ApplyOptions is needed for BIOS NVRAM clear during
+BIOS firmware update. ClearConfig attribute is passed
+from RF to fwupd script.
+
+Tested: Set and Get of ClearConfig from fwupd.sh works
+ fine.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ item_updater.hpp | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/item_updater.hpp b/item_updater.hpp
+index 3f0530f..5c1a779 100644
+--- a/item_updater.hpp
++++ b/item_updater.hpp
+@@ -9,6 +9,7 @@
+ #include <xyz/openbmc_project/Association/Definitions/server.hpp>
+ #include <xyz/openbmc_project/Common/FactoryReset/server.hpp>
+ #include <xyz/openbmc_project/Control/FieldMode/server.hpp>
++#include <xyz/openbmc_project/Software/ApplyOptions/server.hpp>
+
+ #include <string>
+ #include <vector>
+@@ -24,7 +25,8 @@ using ItemUpdaterInherit = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Common::server::FactoryReset,
+ sdbusplus::xyz::openbmc_project::Control::server::FieldMode,
+ sdbusplus::xyz::openbmc_project::Association::server::Definitions,
+- sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll>;
++ sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll,
++ sdbusplus::xyz::openbmc_project::Software::server::ApplyOptions>;
+
+ namespace MatchRules = sdbusplus::bus::match::rules;
+ using VersionClass = phosphor::software::manager::Version;
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0010-Add-error-reporting-to-pfr_image_manager.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0010-Add-error-reporting-to-pfr_image_manager.patch
new file mode 100644
index 000000000..e72398efd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0010-Add-error-reporting-to-pfr_image_manager.patch
@@ -0,0 +1,190 @@
+From ffa3642e436b559d8062f777f00458cc7b5ecb01 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Thu, 11 Jun 2020 13:30:02 -0700
+Subject: [PATCH 1/1] Add error reporting to pfr_image_manager
+
+This uses report functionality to update error
+return status for redfish updates.
+
+Tested: Got 400 error with different messages based
+on failure type
+
+{
+ "error": {
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "/redfish/v1/$metadata#Message.v1_0_0.Message",
+ "Message": "Invalid file uploaded to /redfish/v1/UpdateService: invalid archive.",
+ "MessageArgs": [
+ "/redfish/v1/UpdateService",
+ "invalid archive"
+ ],
+ "MessageId": "OpenBMC.0.1.0.InvalidFile",
+ "Resolution": "None.",
+ "Severity": "Warning"
+ }
+ ],
+ "code": "OpenBMC.0.1.0.InvalidFile",
+ "message": "Invalid file uploaded to /redfish/v1/UpdateService: invalid archive."
+ }
+}
+
+{
+ "error": {
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "/redfish/v1/$metadata#Message.v1_0_0.Message",
+ "Message": "Invalid file uploaded to /redfish/v1/UpdateService: invalid image format.",
+ "MessageArgs": [
+ "/redfish/v1/UpdateService",
+ "invalid image format"
+ ],
+ "MessageId": "OpenBMC.0.1.0.InvalidFile",
+ "Resolution": "None.",
+ "Severity": "Warning"
+ }
+ ],
+ "code": "OpenBMC.0.1.0.InvalidFile",
+ "message": "Invalid file uploaded to /redfish/v1/UpdateService: invalid image format."
+ }
+}
+
+{
+ "error": {
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "#Message.v1_0_0.Message",
+ "Message": "The resource /redfish/v1/UpdateService was unable to satisfy the request due to unavailability of resources.",
+ "MessageArgs": [
+ "/redfish/v1/UpdateService"
+ ],
+ "MessageId": "Base.1.4.0.ResourceExhaustion",
+ "Resolution": "Ensure that the resources are available and resubmit the request.",
+ "Severity": "Critical"
+ }
+ ],
+ "code": "Base.1.4.0.ResourceExhaustion",
+ "message": "The resource /redfish/v1/UpdateService was unable to satisfy the request due to unavailability of resources."
+ }
+}
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ dbus_helpers.hpp | 30 ++++++++++++++++++++++++++++++
+ pfr_image_manager.cpp | 18 ++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+ create mode 100644 dbus_helpers.hpp
+
+diff --git a/dbus_helpers.hpp b/dbus_helpers.hpp
+new file mode 100644
+index 0000000..b9ffa36
+--- /dev/null
++++ b/dbus_helpers.hpp
+@@ -0,0 +1,30 @@
++#pragma once
++
++#include "config.h"
++
++#include <sdbusplus/bus.hpp>
++inline bool isFwupdScriptRunning(sdbusplus::bus::bus& bus)
++{
++ using ObjectPath = sdbusplus::message::object_path;
++ // type is ssssssouso
++ using ListUnitsType =
++ std::tuple<std::string, std::string, std::string, std::string,
++ std::string, std::string, ObjectPath, uint32_t, std::string,
++ ObjectPath>;
++ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
++ SYSTEMD_INTERFACE, "ListUnits");
++
++ auto reply = bus.call(method);
++ std::vector<ListUnitsType> resp;
++ reply.read(resp);
++
++ for (const auto& unit : resp)
++ {
++ if (std::get<0>(unit).find("fwupd@") != std::string::npos &&
++ std::get<3>(unit) != "failed")
++ {
++ return true;
++ }
++ }
++ return false;
++}
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index 1a41cbe..fe1e6f9 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -2,6 +2,7 @@
+
+ #include "pfr_image_manager.hpp"
+
++#include "dbus_helpers.hpp"
+ #include "version.hpp"
+ #include "watch.hpp"
+
+@@ -33,6 +34,9 @@ namespace manager
+
+ using namespace sdbusplus::xyz::openbmc_project::Software::Image::Error;
+ namespace Software = phosphor::logging::xyz::openbmc_project::Software;
++using UnTarFail = Software::Image::UnTarFailure;
++using ImageFail = Software::Image::ImageFailure;
++using BusyFail = Software::Image::BusyFailure;
+
+ static constexpr const uint32_t pfmPos = 2054;
+ static constexpr const uint32_t block0Magic = 0xB6EAFD19;
+@@ -76,6 +80,8 @@ int Manager::verifyPFRImage(const std::filesystem::path imgPath,
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Image magic number match failed",
+ phosphor::logging::entry("IMAGEMAGIC=0x%x", imgMagic));
++ phosphor::logging::report<UnTarFailure>(
++ UnTarFail::PATH(imgPath.c_str()));
+ return -1;
+ }
+
+@@ -110,6 +116,9 @@ int Manager::verifyPFRImage(const std::filesystem::path imgPath,
+
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Unknown image type");
++ phosphor::logging::report<ImageFailure>(
++ ImageFail::FAIL("Unknown image type"),
++ ImageFail::PATH(imgPath.c_str()));
+ return -1;
+ }
+
+@@ -153,6 +162,9 @@ int Manager::verifyPFRImage(const std::filesystem::path imgPath,
+ "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s",
+ redfishMsgID.c_str(), "REDFISH_MESSAGE_ARGS=%s",
+ "Image HASH check fail", NULL);
++ phosphor::logging::report<ImageFailure>(
++ ImageFail::FAIL("Security violation: hash mismatch"),
++ ImageFail::PATH(imgPath.c_str()));
+ return -1;
+ }
+
+@@ -167,6 +179,9 @@ int Manager::verifyPFRImage(const std::filesystem::path imgPath,
+ catch (std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ phosphor::logging::report<ImageFailure>(
++ ImageFail::FAIL("Unhandled exception"),
++ ImageFail::PATH(imgPath.c_str()));
+ return -1;
+ }
+ }
+@@ -182,6 +197,12 @@ int Manager::processImage(const std::string& imgFilePath)
+ if (!std::filesystem::exists(imgPath))
+ return -1;
+
++ if (isFwupdScriptRunning(bus))
++ {
++ phosphor::logging::report<BusyFailure>(BusyFail::PATH(imgPath.c_str()));
++ return -1;
++ }
++
+ int retry = 3;
+ std::string ver;
+ std::string purposeString;
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch
new file mode 100644
index 000000000..6bbd59918
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch
@@ -0,0 +1,40 @@
+From 0628db177655e6f890c4da8c7de7c3cd7487d528 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Thu, 16 Jul 2020 14:16:28 -0700
+Subject: [PATCH] remove image file on pre-script failures
+
+Multiple back-to-back updates of bad images will cause the software
+manager to leave junk images hanging around. This is part of a fix that
+will remove them if the software manager never gets around to launching
+the fwupd.sh script. The other part is that the fwupd.sh script must
+always delete the image file on exit, success or failure.
+
+Tested: posted a garbage file, saw that it was deleted even though
+ fwupd.sh was never invoked.
+
+Change-Id: I6b049916a3edcb48f9d4ebe0d4715b94214b4feb
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+---
+ watch.cpp | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/watch.cpp b/watch.cpp
+index d6c09a946fd0..5d70edbf52b4 100644
+--- a/watch.cpp
++++ b/watch.cpp
+@@ -106,6 +106,12 @@ int Watch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
+ {
+ error("Error ({RC}) processing image {IMAGE}", "RC", rc,
+ "IMAGE", tarballPath);
++ std::error_code ec{};
++ fs::remove_all(tarballPath, ec);
++ if (!ec)
++ {
++ error("Unable to remove image on processing failure");
++ }
+ }
+ }
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0014-PFR-image-verification.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0014-PFR-image-verification.patch
new file mode 100644
index 000000000..dfc7f2e58
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0014-PFR-image-verification.patch
@@ -0,0 +1,116 @@
+From 9d82d53b50769506926dd99273f197a268d68fa3 Mon Sep 17 00:00:00 2001
+From: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
+Date: Thu, 30 Jul 2020 09:50:40 +0000
+Subject: [PATCH] PFR-image-verification
+
+Add support verify the complete fw image by using mtd-util repo's
+pfr_authenticate function.
+
+Tested.
+1. Upload the corrupted image.
+POST: https://<BMC_IP>/redfish/v1/UpdateService/
+ with <Corrupted BMC_signed_cap> binary file
+Response:
+{
+ "error": {
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "/redfish/v1/$metadata#Message.v1_0_0.Message",
+ "Message": "Invalid file uploaded to /redfish/v1/UpdateService:
+ Invalid image format.",
+ "MessageArgs": [
+ "/redfish/v1/UpdateService",
+ "Invalid image format"
+ ],
+ "MessageId": "OpenBMC.0.1.0.InvalidUpload",
+ "Resolution": "None.",
+ "Severity": "Warning"
+ }
+ ],
+ "code": "OpenBMC.0.1.0.InvalidUpload",
+ "message": "Invalid file uploaded to /redfish/v1/UpdateService:
+ Invalid image format."
+ }
+}
+
+2. Upload the correct image.
+POST: https://<BMC_IP>/redfish/v1/UpdateService/
+ with <BMC_signed_cap> binary file
+
+Image verified and firmware updated.
+{
+ "@odata.id": "/redfish/v1/TaskService/Tasks/0",
+ "@odata.type": "#Task.v1_4_3.Task",
+ "Id": "0",
+ "TaskState": "Running",
+ "TaskStatus": "OK"
+}
+
+Command:
+GET: https://<BMC_IP>/redfish/v1/Systems/system/LogServices/EventLog/
+ Entries
+
+Response:
+{
+ "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/
+ Entries/1596082187",
+ "@odata.type": "#LogEntry.v1_4_0.LogEntry",
+ "Created": "2020-07-30T04:09:47+00:00",
+ "EntryType": "Event",
+ "Id": "1596082187",
+ "Message": "BMC firmware update to version 00.72 completed
+ successfully.",
+ "MessageArgs": [
+ "BMC",
+ "00.72"
+ ],
+ "MessageId": "OpenBMC.0.1.FirmwareUpdateCompleted",
+ "Name": "System Event Log Entry",
+ "Severity": "OK"
+ },
+
+Signed-off-by: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
+---
+ pfr_image_manager.cpp | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index eeed4fe..16231fa 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -15,6 +15,7 @@
+ #include <time.h>
+ #include <unistd.h>
+
++#include <boost/process/child.hpp>
+ #include <elog-errors.hpp>
+ #include <xyz/openbmc_project/Software/Image/error.hpp>
+
+@@ -122,6 +123,24 @@ int Manager::verifyPFRImage(const std::filesystem::path imgPath,
+ return -1;
+ }
+
++ // Verify the complete image
++ std::string mtdUtilfile = "/usr/bin/mtd-util";
++ std::vector<std::string> mtdUtilCmd = {"p", "a"};
++ mtdUtilCmd.push_back(imgPath);
++
++ boost::process::child execProg(mtdUtilfile, mtdUtilCmd);
++ execProg.wait();
++ if (execProg.exit_code())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Image authentication failed");
++ phosphor::logging::report<ImageFailure>(
++ ImageFail::FAIL(
++ "Security violation: image authentication failure"),
++ ImageFail::PATH(imgPath.c_str()));
++ return -1;
++ }
++
+ imgFile.seekg(pfmPos,
+ std::ios::beg); // Version is at 0x806 in the PFM
+ imgFile.read(reinterpret_cast<char*>(&verData), sizeof(verData));
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0016-Process-PLDM-image-type.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0016-Process-PLDM-image-type.patch
new file mode 100644
index 000000000..bc94f00af
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0016-Process-PLDM-image-type.patch
@@ -0,0 +1,234 @@
+From a78b7a609f58ac82623c357426ef0590d6d76971 Mon Sep 17 00:00:00 2001
+From: Ayushi Smriti <smriti.ayushi@intel.com>
+Date: Mon, 9 Nov 2020 23:04:58 +0530
+Subject: [PATCH] Process PLDM image type
+
+This change is to check whether the image uploaded is of PLDM image
+type based on the PackageHeaderIdentifier check which is a 16 bytes
+uuid field in the pldm package header.
+
+Also, determine image purpose and version.
+Purpose is set to pldm enum type and for version, PackageVersionString
+is concluded based on PackageVersionStringLength value.
+
+Tested:
+- On uploading a pldm image through Redfish. Uuid is identified and
+matched correctly.
+- Purpose and version is given to the image as expected and activation
+intf got added.
+ - verified same with busctl cmd on xyz.openbmc_project.Software.Version
+ and xyz.openbmc_project.Software.BMC.Updater
+- Verified the regular PFR update procedure works
+ - received expected redfish response from postman
+ - verified fwupd.sh script is reached
+
+Signed-off-by: Ayushi Smriti <smriti.ayushi@intel.com>
+---
+ item_updater.cpp | 4 +-
+ pfr_image_manager.cpp | 95 +++++++++++++++++++++++++++++++++++++++++--
+ pfr_image_manager.hpp | 6 +--
+ pldm.hpp | 21 ++++++++++
+ 4 files changed, 119 insertions(+), 7 deletions(-)
+ create mode 100644 pldm.hpp
+
+diff --git a/item_updater.cpp b/item_updater.cpp
+index db255d6..7af80e3 100644
+--- a/item_updater.cpp
++++ b/item_updater.cpp
+@@ -67,6 +67,7 @@ void ItemUpdater::createActivation(sdbusplus::message::message& msg)
+ #if defined(HOST_BIOS_UPGRADE) || defined(PFR_UPDATE)
+ value == VersionPurpose::Host ||
+ #endif
++ value == VersionPurpose::PLDM ||
+ value == VersionPurpose::Other)
+ {
+ purpose = value;
+@@ -397,7 +398,8 @@ void ItemUpdater::deleteAll()
+ }
+
+ ItemUpdater::ActivationStatus
+- ItemUpdater::validateSquashFSImage(const std::string& filePath)
++ ItemUpdater::validateSquashFSImage(__attribute__((unused))
++ const std::string& filePath)
+ {
+ #ifndef PFR_UPDATE
+ bool valid = true;
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index 178367f..c923494 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -3,6 +3,7 @@
+ #include "pfr_image_manager.hpp"
+
+ #include "dbus_helpers.hpp"
++#include "pldm.hpp"
+ #include "version.hpp"
+ #include "watch.hpp"
+
+@@ -44,9 +45,10 @@ using BusyFail = Software::Image::BusyFailure;
+ static constexpr const uint32_t pfmPos = 2054;
+ static constexpr const uint32_t block0Magic = 0xB6EAFD19;
+ static constexpr const uint32_t lengthBlk0Blk1 = 1024;
++static constexpr const uint32_t pldmMagic = 0xF018878C;
+
+-int Manager::verifyPFRImage(const std::filesystem::path imgPath,
+- std::string& version, std::string& purposeString)
++int Manager::verifyImage(const std::filesystem::path imgPath,
++ std::string& version, std::string& purposeString)
+ {
+ uint8_t imgType = 0;
+ uint32_t imgMagic = 0;
+@@ -76,6 +78,93 @@ int Manager::verifyPFRImage(const std::filesystem::path imgPath,
+
+ imgMagic = block0Data.tag;
+
++ if (htobe32(imgMagic) == pldmMagic)
++ {
++ if (!version.empty())
++ {
++ version.clear();
++ }
++
++ imgFile.seekg(0, std::ios_base::end);
++
++ const size_t length = imgFile.tellg();
++ constexpr size_t readBytes = 36;
++
++ if (length < readBytes)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Insufficient file length to read the required "
++ "bytes");
++ return -1;
++ }
++
++ imgFile.seekg(0, std::ios::beg);
++
++ std::array<char, readBytes> buffer = {};
++
++ imgFile.read(
++ buffer.data(),
++ buffer.size()); // read 36 bytes of PLDM Package Header
++
++ if (!imgFile.good())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Image file read is not successful");
++ return -1;
++ }
++
++ if (!std::equal(buffer.begin(),
++ buffer.begin() + pldm::headerIdLen,
++ pldm::pldmPkgHeaderId
++ .begin())) // comparing 16 bytes of
++ // PackageHeaderIdentifier field
++ {
++ std::string redfishMsgID =
++ "OpenBMC.0.1.FirmwareUpdateFailed";
++ sd_journal_send(
++ "MESSAGE=%s", "Firmware image verification failed",
++ "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s",
++ redfishMsgID.c_str(), "REDFISH_MESSAGE_ARGS=%s",
++ "PLDM Image package header identifier check fail",
++ NULL);
++
++ return -1;
++ }
++
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Package header identifier matched");
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.PLDM";
++
++ const uint8_t pkgVerStrLen = static_cast<uint8_t>(
++ buffer[35]); // PackageVersionStringLen byte
++
++ imgFile.seekg(readBytes,
++ std::ios::beg); // point to the begin of
++ // PackageVersionString field
++ // i.e. 36th pos
++
++ std::array<char, 255> ver = {};
++ imgFile.read(ver.data(),
++ pkgVerStrLen); // read PackageVersionString bytes
++
++ if (!imgFile.good())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Image file read is not successful");
++ return -1;
++ }
++
++ version.assign(ver.data(), pkgVerStrLen);
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Package version string value",
++ phosphor::logging::entry("IMAGE_VERSION=%s",
++ version.c_str()));
++
++ imgFile.close();
++ return 0;
++ }
++
+ if (imgMagic != block0Magic)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+@@ -226,7 +315,7 @@ int Manager::processImage(const std::string& imgFilePath)
+ std::string ver;
+ std::string purposeString;
+
+- if (0 != verifyPFRImage(imgFilePath, ver, purposeString))
++ if (0 != verifyImage(imgFilePath, ver, purposeString))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Error verifying uploaded image");
+diff --git a/pfr_image_manager.hpp b/pfr_image_manager.hpp
+index 3591f1a..2facfe6 100644
+--- a/pfr_image_manager.hpp
++++ b/pfr_image_manager.hpp
+@@ -156,13 +156,13 @@ class Manager
+ CustomMap mapFile(const std::filesystem::path& path, size_t size);
+
+ /**
+- * @brief Verify the PFR image and return version and purpose
++ * @brief Verify the uploaded image type and return version and purpose
+ * @param[in] - file path
+ * @param[out] - version
+ * @param[out] - purpose
+ */
+- int verifyPFRImage(const std::filesystem::path imgPath,
+- std::string& version, std::string& purposeString);
++ int verifyImage(const std::filesystem::path imgPath, std::string& version,
++ std::string& purposeString);
+ /** @brief Persistent map of Version dbus objects and their
+ * version id */
+ std::map<std::string, std::unique_ptr<Version>> versions;
+diff --git a/pldm.hpp b/pldm.hpp
+new file mode 100644
+index 0000000..edbd6ae
+--- /dev/null
++++ b/pldm.hpp
+@@ -0,0 +1,21 @@
++namespace pldm
++{
++
++struct PldmPkgHeader
++{
++ uint8_t uuid[16]; // PackageHeaderIdentifier
++ uint8_t formatRev; // PackageHeaderFormatRevision
++ uint16_t headerSize; // PackageHeaderSize
++ uint8_t timestamp[13]; // PackageReleaseDateTime
++ uint16_t bitmapLen; // ComponentBitmapBitLength
++ uint8_t verStringType; // PackageVersionStringType
++ uint8_t verStringLen; // PackageVersionStringLength
++} __attribute__((packed));
++
++constexpr size_t headerIdLen = 16;
++
++const std::array<char, headerIdLen> pldmPkgHeaderId = {
++ 0xF0, 0x18, 0x87, 0x8C, 0xCB, 0x7D, 0x49, 0x43,
++ 0x98, 0x00, 0xA0, 0x2F, 0x05, 0x9A, 0xCA, 0x02}; // 16 bytes package header
++ // identifier uuid
++} // namespace pldm
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0017-Fix-build-error.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0017-Fix-build-error.patch
new file mode 100644
index 000000000..d21dbd63c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0017-Fix-build-error.patch
@@ -0,0 +1,34 @@
+From 1f3531eff8a05bb5375dea89c1ca9292f69863b0 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 11 Mar 2021 11:42:39 -0800
+Subject: [PATCH] Fix build error
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ pfr_image_manager.cpp | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index f844b8e79565..55ad21f8a3d4 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -333,6 +333,7 @@ int Manager::processImage(const std::string& imgFilePath)
+
+ int retry = 3;
+ std::string ver;
++ std::string extVer;
+ std::string purposeString;
+
+ if (0 != verifyImage(imgFilePath, ver, purposeString))
+@@ -398,7 +399,7 @@ int Manager::processImage(const std::string& imgFilePath)
+ std::string objPath = std::string{SOFTWARE_OBJPATH} + '/' + id;
+
+ auto versionPtr = std::make_unique<Version>(
+- bus, objPath, ver, purpose, imageDirPath.string(),
++ bus, objPath, ver, purpose, extVer, imageDirPath.string(),
+ std::bind(&Manager::erase, this, std::placeholders::_1));
+ versionPtr->deleteObject =
+ std::make_unique<phosphor::software::manager::Delete>(bus, objPath,
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0018-Fix-delete-image-by-ID-and-inhibit-removal-of-bmc_ac.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0018-Fix-delete-image-by-ID-and-inhibit-removal-of-bmc_ac.patch
new file mode 100644
index 000000000..0b2026c92
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0018-Fix-delete-image-by-ID-and-inhibit-removal-of-bmc_ac.patch
@@ -0,0 +1,171 @@
+From 77b861136b6780ce4eabfe9589a0b584e6ed2b43 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Wed, 21 Apr 2021 21:16:47 +0000
+Subject: [PATCH] Fix delete image by ID and inhibit removal of bmc_active
+
+Delete image by ID was broken because when hitting the delete dbus
+interface, it recalculated the ID from the parent version, which then
+does not match because of the random number addition that was added
+to the ID when the parent interface was created. This saves away the
+parent interface ID and recalls it rather than recalculating it.
+
+Also, there was a logic error in deleting images that would delete the
+active BMC image. This fixes up that error.
+
+Tested: run multiple back-to back updates and see that when the fwupd
+ script calls delete, the interfaces are deleted and that the
+ bmc_active interface is not deleted.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ image_manager.cpp | 2 +-
+ item_updater.cpp | 16 +++++++++++-----
+ pfr_image_manager.cpp | 2 +-
+ version.cpp | 2 +-
+ version.hpp | 19 +++++++++++++++----
+ 5 files changed, 29 insertions(+), 12 deletions(-)
+
+diff --git a/image_manager.cpp b/image_manager.cpp
+index 6334704cd980..4fefd221e6d2 100644
+--- a/image_manager.cpp
++++ b/image_manager.cpp
+@@ -221,7 +221,7 @@ int Manager::processImage(const std::string& tarFilePath)
+ {
+ // Create Version object
+ auto versionPtr = std::make_unique<Version>(
+- bus, objPath, version, purpose, extendedVersion,
++ bus, objPath, id, version, purpose, extendedVersion,
+ imageDirPath.string(),
+ std::bind(&Manager::erase, this, std::placeholders::_1));
+ versionPtr->deleteObject =
+diff --git a/item_updater.cpp b/item_updater.cpp
+index 26b52b3f7846..3f64feb43c55 100644
+--- a/item_updater.cpp
++++ b/item_updater.cpp
+@@ -145,7 +145,7 @@ void ItemUpdater::createActivation(sdbusplus::message::message& msg)
+ activationState, associations)));
+
+ auto versionPtr = std::make_unique<VersionClass>(
+- bus, path, version, purpose, extendedVersion, filePath,
++ bus, path, versionId, version, purpose, extendedVersion, filePath,
+ std::bind(&ItemUpdater::erase, this, std::placeholders::_1));
+ versionPtr->deleteObject =
+ std::make_unique<phosphor::software::manager::Delete>(bus, path,
+@@ -260,7 +260,7 @@ void ItemUpdater::processBMCImage()
+
+ // Create Version instance for this version.
+ auto versionPtr = std::make_unique<VersionClass>(
+- bus, path, version, purpose, extendedVersion, "",
++ bus, path, id, version, purpose, extendedVersion, "",
+ std::bind(&ItemUpdater::erase, this, std::placeholders::_1));
+ auto isVersionFunctional = versionPtr->isFunctional();
+ if (!isVersionFunctional)
+@@ -336,9 +336,9 @@ void ItemUpdater::erase(std::string entryId)
+ auto it = versions.find(entryId);
+ if (it != versions.end())
+ {
+- if (it->second->isFunctional() && ACTIVE_BMC_MAX_ALLOWED > 1)
++ if (it->second->isFunctional())
+ {
+- error(
++ info(
+ "Version ({VERSIONID}) is currently running on the BMC; unable to remove.",
+ "VERSIONID", entryId);
+ return;
+@@ -679,6 +679,12 @@ void ItemUpdater::freeSpace(Activation& caller)
+ std::size_t count = 0;
+ for (const auto& iter : activations)
+ {
++ if (versions.find(iter.second->versionId)->second->isFunctional())
++ {
++ // don't bother with function versions
++ continue;
++ }
++
+ if ((iter.second.get()->activation() ==
+ server::Activation::Activations::Active) ||
+ (iter.second.get()->activation() ==
+@@ -772,7 +778,7 @@ void ItemUpdater::createBIOSObject()
+ // Do nothing;
+ };
+ biosVersion = std::make_unique<VersionClass>(
+- bus, path, version, VersionPurpose::Host, "", "",
++ bus, path, versionId, version, VersionPurpose::Host, "", "",
+ std::bind(dummyErase, std::placeholders::_1));
+ biosVersion->deleteObject =
+ std::make_unique<phosphor::software::manager::Delete>(bus, path,
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index 80db63ca4d85..03bc34a3a78b 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -399,7 +399,7 @@ int Manager::processImage(const std::string& imgFilePath)
+ std::string objPath = std::string{SOFTWARE_OBJPATH} + '/' + id;
+
+ auto versionPtr = std::make_unique<Version>(
+- bus, objPath, ver, purpose, extVer, imageDirPath.string(),
++ bus, objPath, id, ver, purpose, extVer, imageDirPath.string(),
+ std::bind(&Manager::erase, this, std::placeholders::_1));
+ versionPtr->deleteObject =
+ std::make_unique<phosphor::software::manager::Delete>(bus, objPath,
+diff --git a/version.cpp b/version.cpp
+index 97f3be94b4aa..5410c38887f8 100644
+--- a/version.cpp
++++ b/version.cpp
+@@ -208,7 +208,7 @@ void Delete::delete_()
+ {
+ if (parent.eraseCallback)
+ {
+- parent.eraseCallback(parent.getId(parent.version()));
++ parent.eraseCallback(parent.getExtId());
+ }
+ }
+
+diff --git a/version.hpp b/version.hpp
+index 8a68cb5f7b1f..afc589c0226c 100644
+--- a/version.hpp
++++ b/version.hpp
+@@ -77,11 +77,11 @@ class Version : public VersionInherit
+ * @param[in] callback - The eraseFunc callback
+ */
+ Version(sdbusplus::bus::bus& bus, const std::string& objPath,
+- const std::string& versionString, VersionPurpose versionPurpose,
+- const std::string& extVersion, const std::string& filePath,
+- eraseFunc callback) :
++ const std::string& extId, const std::string& versionString,
++ VersionPurpose versionPurpose, const std::string& extVersion,
++ const std::string& filePath, eraseFunc callback) :
+ VersionInherit(bus, (objPath).c_str(), true),
+- eraseCallback(callback), versionStr(versionString)
++ eraseCallback(callback), versionStr(versionString), extId(extId)
+ {
+ // Set properties.
+ extendedVersion(extVersion);
+@@ -150,6 +150,15 @@ class Version : public VersionInherit
+ */
+ bool isFunctional();
+
++ /* @brief Return the extended ID of this version object
++ *
++ * @ return - returns the extended ID string
++ */
++ std::string getExtId()
++ {
++ return extId;
++ }
++
+ /** @brief Persistent Delete D-Bus object */
+ std::unique_ptr<Delete> deleteObject;
+
+@@ -159,6 +168,8 @@ class Version : public VersionInherit
+ private:
+ /** @brief This Version's version string */
+ const std::string versionStr;
++ /** @brief This is extended version string */
++ const std::string extId;
+ };
+
+ } // namespace manager
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0019-log-redfish-errors-on-all-pfr-image-auth-failures.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0019-log-redfish-errors-on-all-pfr-image-auth-failures.patch
new file mode 100644
index 000000000..3a245c944
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0019-log-redfish-errors-on-all-pfr-image-auth-failures.patch
@@ -0,0 +1,100 @@
+From 8d3eb2a57a70715b2cc6088904e8be007ab921b2 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Fri, 27 Aug 2021 11:44:02 -0700
+Subject: [PATCH 1/4] log redfish errors on all pfr image auth failures
+
+Previous code was doing a 'mtd-util pfr authenticate' prior to manually
+calculating and comparing the hashes. This is incorrect behavior. There
+is no need to manually calculate hashes since that is part of the pfr
+authentication process.
+
+An unintended side effect of this is that if pfr authenticate fails for
+some reason other than hash compare, the redfish log does not happen.
+
+Tested: phosphor-version-software-mananger logs a redfish log on rom id
+ mismatch as expected.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+---
+ pfr_image_manager.cpp | 51 +++++--------------------------------------
+ 1 file changed, 5 insertions(+), 46 deletions(-)
+
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index ce850cb..aa96a99 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -53,13 +53,10 @@ int Manager::verifyImage(const std::filesystem::path imgPath,
+ uint8_t imgType = 0;
+ uint32_t imgMagic = 0;
+ uint8_t verData[2] = {0};
+- uint32_t hashLen = 0;
+ struct pfrImgBlock0 block0Data = {};
+
+ std::string imageName;
+
+- EVP_MD_CTX* ctx;
+-
+ if (std::filesystem::exists(imgPath))
+ {
+ try
+@@ -227,52 +224,14 @@ int Manager::verifyImage(const std::filesystem::path imgPath,
+ ImageFail::FAIL(
+ "Security violation: image authentication failure"),
+ ImageFail::PATH(imgPath.c_str()));
+- return -1;
+- }
+-
+- imgFile.seekg(pfmPos,
+- std::ios::beg); // Version is at 0x806 in the PFM
+- imgFile.read(reinterpret_cast<char*>(&verData), sizeof(verData));
+- imgFile.close();
+-
+- auto size = std::filesystem::file_size(imgPath);
+-
+- phosphor::logging::log<phosphor::logging::level::INFO>(
+- "Image Size", phosphor::logging::entry("IMAGESIZE=0x%x",
+- static_cast<int>(size)));
+-
+- // Adds all digest algorithms to the internal table
+- OpenSSL_add_all_digests();
+-
+- ctx = EVP_MD_CTX_create();
+- EVP_DigestInit(ctx, EVP_sha256());
+
+- // Hash the image file and update the digest
+- auto dataPtr = mapFile(imgPath, size);
+-
+- EVP_DigestUpdate(ctx, ((uint8_t*)dataPtr() + lengthBlk0Blk1),
+- (size - lengthBlk0Blk1));
+-
+- std::vector<uint8_t> digest(EVP_MD_size(EVP_sha256()));
+- std::vector<uint8_t> expectedDigest(block0Data.hash256,
+- &block0Data.hash256[0] + 32);
+-
+- EVP_DigestFinal(ctx, digest.data(), &hashLen);
+- EVP_MD_CTX_destroy(ctx);
+-
+- std::string redfishMsgID = "OpenBMC.0.1";
+-
+- if (expectedDigest != digest)
+- {
+- redfishMsgID += ".GeneralFirmwareSecurityViolation";
++ constexpr const char* redfishMsgID =
++ "OpenBMC.0.1.GeneralFirmwareSecurityViolation";
+ sd_journal_send("MESSAGE=%s",
+- "Firmware image HASH verification failed",
++ "Firmware image authentication failed",
+ "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s",
+- redfishMsgID.c_str(), "REDFISH_MESSAGE_ARGS=%s",
+- "Image HASH check fail", NULL);
+- phosphor::logging::report<ImageFailure>(
+- ImageFail::FAIL("Security violation: hash mismatch"),
+- ImageFail::PATH(imgPath.c_str()));
++ redfishMsgID, "REDFISH_MESSAGE_ARGS=%s",
++ "Image authentication check fail", NULL);
+ return -1;
+ }
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
new file mode 100644
index 000000000..d21647611
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Flash BMC with fwupd script : %I
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/bin/systemd-inhibit --what=shutdown:sleep --who=fwupd --why "Firmware Update %i" --mode=block /usr/bin/fwupd.sh %i
+SyslogIdentifier=fwupd
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
new file mode 100644
index 000000000..53d09387b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
@@ -0,0 +1,30 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+EXTRA_OEMESON += "-Dfwupd-script=enabled"
+
+SYSTEMD_SERVICE:${PN}-updater += "fwupd@.service"
+
+EXTRA_OEMESON += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '-Dpfr-update=enabled', '', d)}"
+
+SRC_URI += " \
+ file://0002-Redfish-firmware-activation.patch \
+ file://0004-Changed-the-condition-of-software-version-service-wa.patch \
+ file://0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch \
+ file://0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch \
+ file://0007-Adding-StandBySpare-for-firmware-activation.patch \
+ file://0008-item_updater-update-the-bmc_active-objectPath.patch \
+ file://0009-Add-ApplyOptions-D-bus-property-under-Software.patch \
+ file://0013-remove-image-file-on-pre-script-failures.patch \
+ "
+
+SRC_URI_PFR = " \
+ file://0007-PFR-images-support.patch \
+ file://0008-PFR-image-HASH-verification.patch \
+ file://0010-Add-error-reporting-to-pfr_image_manager.patch \
+ file://0014-PFR-image-verification.patch \
+ file://0016-Process-PLDM-image-type.patch \
+ file://0017-Fix-build-error.patch \
+ file://0018-Fix-delete-image-by-ID-and-inhibit-removal-of-bmc_ac.patch \
+ file://0019-log-redfish-errors-on-all-pfr-image-auth-failures.patch \
+ "
+
+SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', SRC_URI_PFR, '', d)}"