diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/flash')
15 files changed, 2103 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-Add-more-error-types.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-Add-more-error-types.patch new file mode 100644 index 000000000..d43256bf4 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-Add-more-error-types.patch @@ -0,0 +1,459 @@ +From e710df3123c382fc735c451a048f7c51250c1a92 Mon Sep 17 00:00:00 2001 +From: James Feist <james.feist@linux.intel.com> +Date: Thu, 11 Jun 2020 13:14:11 -0700 +Subject: [PATCH 1/2] Add more error types + +This adds ImageFailure and Busy error types +to updates status in bmcweb. + +elog-errors.hpp is a generated file. + +Tested: Could create errors + +Signed-off-by: James Feist <james.feist@linux.intel.com> +--- + elog-errors.hpp | 269 ++++++++++++------ + .../Software/Image.errors.yaml | 5 + + .../Software/Image.metadata.yaml | 11 + + 3 files changed, 204 insertions(+), 81 deletions(-) + +diff --git a/elog-errors.hpp b/elog-errors.hpp +index 2888f0d..38016e1 100644 +--- a/elog-errors.hpp ++++ b/elog-errors.hpp +@@ -2,12 +2,12 @@ + // See elog-gen.py for more details + #pragma once + +-#include <phosphor-logging/elog.hpp> +-#include <phosphor-logging/log.hpp> +-#include <sdbusplus/exception.hpp> + #include <string> + #include <tuple> + #include <type_traits> ++#include <sdbusplus/exception.hpp> ++#include <phosphor-logging/log.hpp> ++#include <phosphor-logging/elog.hpp> + + namespace sdbusplus + { +@@ -21,7 +21,7 @@ namespace Image + { + namespace Error + { +-struct UnTarFailure; ++ struct InternalFailure; + } // namespace Error + } // namespace Image + } // namespace Software +@@ -41,7 +41,7 @@ namespace Image + { + namespace Error + { +-struct InternalFailure; ++ struct UnTarFailure; + } // namespace Error + } // namespace Image + } // namespace Software +@@ -61,7 +61,7 @@ namespace Image + { + namespace Error + { +-struct ManifestFileFailure; ++ struct BusyFailure; + } // namespace Error + } // namespace Image + } // namespace Software +@@ -69,6 +69,47 @@ struct ManifestFileFailure; + } // namespace xyz + } // namespace sdbusplus + ++namespace sdbusplus ++{ ++namespace xyz ++{ ++namespace openbmc_project ++{ ++namespace Software ++{ ++namespace Image ++{ ++namespace Error ++{ ++ struct ImageFailure; ++} // namespace Error ++} // namespace Image ++} // namespace Software ++} // namespace openbmc_project ++} // namespace xyz ++} // namespace sdbusplus ++ ++namespace sdbusplus ++{ ++namespace xyz ++{ ++namespace openbmc_project ++{ ++namespace Software ++{ ++namespace Image ++{ ++namespace Error ++{ ++ struct ManifestFileFailure; ++} // namespace Error ++} // namespace Image ++} // namespace Software ++} // namespace openbmc_project ++} // namespace xyz ++} // namespace sdbusplus ++ ++ + namespace phosphor + { + +@@ -88,38 +129,25 @@ namespace _UnTarFailure + + struct PATH + { +- static constexpr auto str = "PATH=%s"; ++ /* ++ * We can't use -fsanitize=undefined if we declare a ++ * 'static constexpr auto str' member, so don't. Instead, open-code the ++ * mako template lookups. ++ */ + static constexpr auto str_short = "PATH"; +- using type = std::tuple<std::decay_t<decltype(str)>, const char*>; +- explicit constexpr PATH(const char* a) : _entry(entry(str, a)){}; ++ using type = std::tuple<std::decay_t<decltype("PATH=%s")>,const char*>; ++ explicit constexpr PATH(const char* a) : _entry(entry("PATH=%s", a)) {}; + type _entry; + }; + +-} // namespace _UnTarFailure ++} // namespace _UnTarFailure + +-struct UnTarFailure : public sdbusplus::exception_t ++struct UnTarFailure + { +- static constexpr auto errName = +- "xyz.openbmc_project.Software.Image.UnTarFailure"; +- static constexpr auto errDesc = "An error occurred during untar."; + static constexpr auto L = level::ERR; + using PATH = _UnTarFailure::PATH; + using metadata_types = std::tuple<PATH>; + +- const char* name() const noexcept +- { +- return errName; +- } +- +- const char* description() const noexcept +- { +- return errDesc; +- } +- +- const char* what() const noexcept +- { +- return errName; +- } + }; + + } // namespace Image +@@ -127,16 +155,17 @@ struct UnTarFailure : public sdbusplus::exception_t + } // namespace openbmc_project + } // namespace xyz + ++ + namespace details + { + + template <> +-struct map_exception_type< +- sdbusplus::xyz::openbmc_project::Software::Image::Error::UnTarFailure> ++struct map_exception_type<sdbusplus::xyz::openbmc_project::Software::Image::Error::UnTarFailure> + { + using type = xyz::openbmc_project::Software::Image::UnTarFailure; + }; +-} // namespace details ++ ++} + + namespace xyz + { +@@ -151,38 +180,25 @@ namespace _ManifestFileFailure + + struct PATH + { +- static constexpr auto str = "PATH=%s"; ++ /* ++ * We can't use -fsanitize=undefined if we declare a ++ * 'static constexpr auto str' member, so don't. Instead, open-code the ++ * mako template lookups. ++ */ + static constexpr auto str_short = "PATH"; +- using type = std::tuple<std::decay_t<decltype(str)>, const char*>; +- explicit constexpr PATH(const char* a) : _entry(entry(str, a)){}; ++ using type = std::tuple<std::decay_t<decltype("PATH=%s")>,const char*>; ++ explicit constexpr PATH(const char* a) : _entry(entry("PATH=%s", a)) {}; + type _entry; + }; + +-} // namespace _ManifestFileFailure ++} // namespace _ManifestFileFailure + +-struct ManifestFileFailure : public sdbusplus::exception_t ++struct ManifestFileFailure + { +- static constexpr auto errName = +- "xyz.openbmc_project.Software.Image.ManifestFileFailure"; +- static constexpr auto errDesc = "An error when reading the Manifest file."; + static constexpr auto L = level::ERR; + using PATH = _ManifestFileFailure::PATH; + using metadata_types = std::tuple<PATH>; + +- const char* name() const noexcept +- { +- return errName; +- } +- +- const char* description() const noexcept +- { +- return errDesc; +- } +- +- const char* what() const noexcept +- { +- return errName; +- } + }; + + } // namespace Image +@@ -190,16 +206,17 @@ struct ManifestFileFailure : public sdbusplus::exception_t + } // namespace openbmc_project + } // namespace xyz + ++ + namespace details + { + + template <> +-struct map_exception_type<sdbusplus::xyz::openbmc_project::Software::Image:: +- Error::ManifestFileFailure> ++struct map_exception_type<sdbusplus::xyz::openbmc_project::Software::Image::Error::ManifestFileFailure> + { + using type = xyz::openbmc_project::Software::Image::ManifestFileFailure; + }; +-} // namespace details ++ ++} + + namespace xyz + { +@@ -214,39 +231,76 @@ namespace _InternalFailure + + struct FAIL + { +- static constexpr auto str = "FAIL=%s"; ++ /* ++ * We can't use -fsanitize=undefined if we declare a ++ * 'static constexpr auto str' member, so don't. Instead, open-code the ++ * mako template lookups. ++ */ + static constexpr auto str_short = "FAIL"; +- using type = std::tuple<std::decay_t<decltype(str)>, const char*>; +- explicit constexpr FAIL(const char* a) : _entry(entry(str, a)){}; ++ using type = std::tuple<std::decay_t<decltype("FAIL=%s")>,const char*>; ++ explicit constexpr FAIL(const char* a) : _entry(entry("FAIL=%s", a)) {}; + type _entry; + }; + +-} // namespace _InternalFailure ++} // namespace _InternalFailure + +-struct InternalFailure : public sdbusplus::exception_t ++struct InternalFailure + { +- static constexpr auto errName = +- "xyz.openbmc_project.Software.Image.InternalFailure"; +- static constexpr auto errDesc = +- "The operation failed internally during processing the image."; + static constexpr auto L = level::ERR; + using FAIL = _InternalFailure::FAIL; + using metadata_types = std::tuple<FAIL>; + +- const char* name() const noexcept +- { +- return errName; +- } ++}; ++ ++} // namespace Image ++} // namespace Software ++} // namespace openbmc_project ++} // namespace xyz ++ ++ ++namespace details ++{ ++ ++template <> ++struct map_exception_type<sdbusplus::xyz::openbmc_project::Software::Image::Error::InternalFailure> ++{ ++ using type = xyz::openbmc_project::Software::Image::InternalFailure; ++}; ++ ++} + +- const char* description() const noexcept +- { +- return errDesc; +- } ++namespace xyz ++{ ++namespace openbmc_project ++{ ++namespace Software ++{ ++namespace Image ++{ ++namespace _ImageFailure ++{ ++ ++struct PATH ++{ ++ /* ++ * We can't use -fsanitize=undefined if we declare a ++ * 'static constexpr auto str' member, so don't. Instead, open-code the ++ * mako template lookups. ++ */ ++ static constexpr auto str_short = "PATH"; ++ using type = std::tuple<std::decay_t<decltype("PATH=%s")>,const char*>; ++ explicit constexpr PATH(const char* a) : _entry(entry("PATH=%s", a)) {}; ++ type _entry; ++}; ++ ++} // namespace _ImageFailure ++ ++struct ImageFailure ++{ ++ static constexpr auto L = level::ERR; ++ using PATH = _ImageFailure::PATH; ++ using metadata_types = std::tuple<PATH>; + +- const char* what() const noexcept +- { +- return errName; +- } + }; + + } // namespace Image +@@ -254,16 +308,69 @@ struct InternalFailure : public sdbusplus::exception_t + } // namespace openbmc_project + } // namespace xyz + ++ + namespace details + { + + template <> +-struct map_exception_type< +- sdbusplus::xyz::openbmc_project::Software::Image::Error::InternalFailure> ++struct map_exception_type<sdbusplus::xyz::openbmc_project::Software::Image::Error::ImageFailure> + { +- using type = xyz::openbmc_project::Software::Image::InternalFailure; ++ using type = xyz::openbmc_project::Software::Image::ImageFailure; + }; +-} // namespace details ++ ++} ++ ++namespace xyz ++{ ++namespace openbmc_project ++{ ++namespace Software ++{ ++namespace Image ++{ ++namespace _BusyFailure ++{ ++ ++struct PATH ++{ ++ /* ++ * We can't use -fsanitize=undefined if we declare a ++ * 'static constexpr auto str' member, so don't. Instead, open-code the ++ * mako template lookups. ++ */ ++ static constexpr auto str_short = "PATH"; ++ using type = std::tuple<std::decay_t<decltype("PATH=%s")>,const char*>; ++ explicit constexpr PATH(const char* a) : _entry(entry("PATH=%s", a)) {}; ++ type _entry; ++}; ++ ++} // namespace _BusyFailure ++ ++struct BusyFailure ++{ ++ static constexpr auto L = level::ERR; ++ using PATH = _BusyFailure::PATH; ++ using metadata_types = std::tuple<PATH>; ++ ++}; ++ ++} // namespace Image ++} // namespace Software ++} // namespace openbmc_project ++} // namespace xyz ++ ++ ++namespace details ++{ ++ ++template <> ++struct map_exception_type<sdbusplus::xyz::openbmc_project::Software::Image::Error::BusyFailure> ++{ ++ using type = xyz::openbmc_project::Software::Image::BusyFailure; ++}; ++ ++} ++ + + } // namespace logging + +diff --git a/xyz/openbmc_project/Software/Image.errors.yaml b/xyz/openbmc_project/Software/Image.errors.yaml +index 67d6c20..2b8f7ee 100644 +--- a/xyz/openbmc_project/Software/Image.errors.yaml ++++ b/xyz/openbmc_project/Software/Image.errors.yaml +@@ -4,3 +4,8 @@ + description: An error when reading the Manifest file. + - name: InternalFailure + description: The operation failed internally during processing the image. ++- name: ImageFailure ++ description: An error occured processing the image. ++- name: BusyFailure ++ description: The device is busy during the update. ++ +diff --git a/xyz/openbmc_project/Software/Image.metadata.yaml b/xyz/openbmc_project/Software/Image.metadata.yaml +index 5e749c9..65d4e1c 100644 +--- a/xyz/openbmc_project/Software/Image.metadata.yaml ++++ b/xyz/openbmc_project/Software/Image.metadata.yaml +@@ -13,3 +13,14 @@ + meta: + - str: "FAIL=%s" + type: string ++- name: ImageFailure ++ level: ERR ++ meta: ++ - str: "PATH=%s" ++ type: string ++- name: BusyFailure ++ level: ERR ++ meta: ++ - str: "PATH=%s" ++ type: string ++ +-- +2.17.1 + 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..3fc3907ba --- /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 +@@ -45,7 +45,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; +@@ -96,7 +96,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..355261e8f --- /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,188 @@ +From 32d90301c494c1b43f8e1d74ac9e7c1dc2fe486a 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 1/1] 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 | 43 +++++++++++++++++++++++++++++++++++++++++++ + configure.ac | 7 +++++++ + static/flash.cpp | 41 +++++++++++++++++++++++++++++++++++++++-- + ubi/flash.cpp | 9 +++------ + 4 files changed, 92 insertions(+), 8 deletions(-) + +diff --git a/activation.cpp b/activation.cpp +index ab76420..91e3a10 100644 +--- a/activation.cpp ++++ b/activation.cpp +@@ -200,6 +200,49 @@ auto Activation::activation(Activations value) -> Activations + softwareServer::Activation::Activations::Active); + } + } ++#elif defined(FWUPD_SCRIPT) ++ if (!activationProgress) ++ { ++ // 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)) ++ { ++ 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) ++ { ++ log<level::ERR>("[Jennifer] 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 // !UBIFS_LAYOUT + + #ifdef WANT_SIGNATURE_VERIFY +diff --git a/configure.ac b/configure.ac +index 5fba420..3b5fdab 100755 +--- a/configure.ac ++++ b/configure.ac +@@ -194,6 +194,13 @@ AS_IF([test "x$enable_host_bios_upgrade" == "xyes"], \ + [AC_DEFINE([HOST_BIOS_UPGRADE],[],[Enable host bios upgrade support.])]) + AM_CONDITIONAL([HOST_BIOS_UPGRADE], [test "x$enable_host_bios_upgrade" == "xyes"]) + ++# setup fwupd script support ++AC_ARG_ENABLE([fwupd_script], ++ AS_HELP_STRING([--enable-fwupd_script], [Enable fwupd script support.])) ++AS_IF([test "x$enable_fwupd_script" == "xyes"], \ ++ [AC_DEFINE([FWUPD_SCRIPT],[],[Enable fwupd script support.])]) ++AM_CONDITIONAL([FWUPD_SCRIPT], [test "x$enable_fwupd_script" == "xyes"]) ++ + # Check for header files. + AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd development package required])]) + AC_CHECK_HEADER(sdbusplus/server.hpp, ,[AC_MSG_ERROR([Could not find sdbusplus/server.hpp...openbmc/sdbusplus package required])]) +diff --git a/static/flash.cpp b/static/flash.cpp +index 82c2393..1bf29d5 100644 +--- a/static/flash.cpp ++++ b/static/flash.cpp +@@ -20,9 +20,11 @@ namespace updater + { + + namespace fs = std::experimental::filesystem; ++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. +@@ -33,11 +35,46 @@ 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(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 5af2a17..ffa9348 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..2d2ac2673 --- /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 <algorithm> +@@ -129,6 +130,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..b63226cce --- /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 +@@ -80,12 +80,16 @@ 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 UBIFS_LAYOUT + if (rwVolumeCreated == false && roVolumeCreated == false) +@@ -256,6 +260,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..92b3ced38 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch @@ -0,0 +1,438 @@ +From 030f918b90ea45104bccf68082c2d634c6694238 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> +--- + Makefile.am | 18 +++- + activation.cpp | 2 +- + configure.ac | 7 ++ + item_updater.cpp | 6 +- + pfr_image_manager.cpp | 217 ++++++++++++++++++++++++++++++++++++++++++ + pfr_image_manager.hpp | 75 +++++++++++++++ + 6 files changed, 320 insertions(+), 5 deletions(-) + create mode 100644 pfr_image_manager.cpp + create mode 100644 pfr_image_manager.hpp + +diff --git a/Makefile.am b/Makefile.am +index 6c3ec16..59ebecc 100755 +--- a/Makefile.am ++++ b/Makefile.am +@@ -6,13 +6,20 @@ noinst_HEADERS = \ + watch.hpp \ + version.hpp \ + images.hpp \ +- image_manager.hpp \ + item_updater.hpp \ + activation.hpp \ + flash.hpp \ + item_updater_helper.hpp \ + utils.hpp + ++if PFR_UPDATE ++noinst_HEADERS += \ ++ pfr_image_manager.hpp ++else ++noinst_HEADERS += \ ++ image_manager.hpp ++endif ++ + bin_PROGRAMS = \ + phosphor-version-software-manager \ + phosphor-download-manager \ +@@ -24,8 +31,15 @@ dist_bin_SCRIPTS = \ + phosphor_version_software_manager_SOURCES = \ + image_manager_main.cpp \ + watch.cpp \ +- version.cpp \ ++ version.cpp ++ ++if PFR_UPDATE ++phosphor_version_software_manager_SOURCES += \ ++ pfr_image_manager.cpp ++else ++phosphor_version_software_manager_SOURCES += \ + image_manager.cpp ++endif + + BUILT_SOURCES = \ + xyz/openbmc_project/Software/Image/error.cpp \ +diff --git a/activation.cpp b/activation.cpp +index cea1e50..7ff4196 100644 +--- a/activation.cpp ++++ b/activation.cpp +@@ -197,7 +197,7 @@ auto Activation::activation(Activations value) -> Activations + } + else if (activationProgress->progress() == 100) + { +- log<level::ERR>("[Jennifer] progress == 100..."); ++ log<level::INFO>("progress == 100..."); + if (!redundancyPriority) + { + redundancyPriority = +diff --git a/configure.ac b/configure.ac +index 720e704..e527682 100755 +--- a/configure.ac ++++ b/configure.ac +@@ -191,6 +191,13 @@ AS_IF([test "x$enable_fwupd_script" == "xyes"], \ + [AC_DEFINE([FWUPD_SCRIPT],[],[Enable fwupd script support.])]) + AM_CONDITIONAL([FWUPD_SCRIPT], [test "x$enable_fwupd_script" == "xyes"]) + ++# setup pfr image update support ++AC_ARG_ENABLE([pfr_update], ++ AS_HELP_STRING([--enable-pfr_update], [Enable pfr image update support.])) ++AS_IF([test "x$enable_pfr_update" == "xyes"], \ ++ [AC_DEFINE([PFR_UPDATE],[],[Enable pfr image update support.])]) ++AM_CONDITIONAL([PFR_UPDATE], [test "x$enable_pfr_update" == "xyes"]) ++ + # Check for header files. + AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd development package required])]) + AC_CHECK_HEADER(sdbusplus/server.hpp, ,[AC_MSG_ERROR([Could not find sdbusplus/server.hpp...openbmc/sdbusplus package required])]) +diff --git a/item_updater.cpp b/item_updater.cpp +index 21fb6e0..fd76a7f 100644 +--- a/item_updater.cpp ++++ b/item_updater.cpp +@@ -64,10 +64,10 @@ void ItemUpdater::createActivation(sdbusplus::message::message& msg) + auto value = SVersion::convertVersionPurposeFromString( + variant_ns::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; + } +@@ -356,6 +357,7 @@ void ItemUpdater::deleteAll() + ItemUpdater::ActivationStatus + ItemUpdater::validateSquashFSImage(const std::string& filePath) + { ++#ifndef PFR_UPDATE + bool invalid = false; + + for (auto& bmcImage : bmcImages) +@@ -375,7 +377,7 @@ ItemUpdater::ActivationStatus + { + return ItemUpdater::ActivationStatus::invalid; + } +- ++#endif + return ItemUpdater::ActivationStatus::ready; + } + +diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp +new file mode 100644 +index 0000000..242a6ca +--- /dev/null ++++ b/pfr_image_manager.cpp +@@ -0,0 +1,217 @@ ++#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 <algorithm> ++#include <cstring> ++#include <elog-errors.hpp> ++#include <filesystem> ++#include <fstream> ++#include <iomanip> ++#include <sstream> ++#include <string> ++#include <xyz/openbmc_project/Software/Image/error.hpp> ++ ++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..c6ee6a4 +--- /dev/null ++++ b/pfr_image_manager.hpp +@@ -0,0 +1,75 @@ ++#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..c65f8318c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch @@ -0,0 +1,441 @@ +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> +@@ -15,9 +17,9 @@ + #include <algorithm> + #include <cstring> + #include <elog-errors.hpp> +-#include <filesystem> + #include <fstream> + #include <iomanip> ++#include <set> + #include <sstream> + #include <string> + #include <xyz/openbmc_project/Software/Image/error.hpp> +@@ -33,12 +35,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)) + { +@@ -55,17 +66,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) + { +@@ -79,20 +174,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; + } + +@@ -103,31 +198,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 +@@ -169,6 +239,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 +@@ -212,6 +283,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,6 +1,13 @@ + #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 <filesystem> + #include <sdbusplus/server.hpp> + + namespace phosphor +@@ -10,7 +17,8 @@ namespace software + namespace manager + { + +-enum pfrImgPCType { ++enum pfrImgPCType ++{ + pfrCPLDUpdateCap = 0x00, + pfrPCHPFM = 0x01, + pfrPCHUpdateCap = 0x02, +@@ -19,15 +27,94 @@ enum pfrImgPCType { + }; + + /* PFR image block 0 - As defined in HAS */ +-struct pfrImgBlock0 { +- uint8_t tag[4]; ++struct pfrImgBlock0 ++{ ++ uint32_t tag; + 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)); ++} __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. +@@ -61,13 +148,28 @@ 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; + + /** @brief Persistent sdbusplus DBus bus connection. */ + sdbusplus::bus::bus& bus; +- + }; + + } // namespace manager +-- +2.17.1 + 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..bac756a18 --- /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,30 @@ +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 | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/item_updater.cpp b/item_updater.cpp +index 7fe69e4..3ce1dbf 100644 +--- a/item_updater.cpp ++++ b/item_updater.cpp +@@ -175,9 +175,7 @@ void ItemUpdater::processBMCImage() + if (0 == + iter.path().native().compare(0, BMC_RO_PREFIX_LEN, BMC_ROFS_PREFIX)) + { +- // The versionId is extracted from the path +- // for example /media/ro-2a1022fe. +- auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN); ++ std::string id = "bmc_active"; + auto osRelease = iter.path() / OS_RELEASE_FILE; + if (!fs::is_regular_file(osRelease)) + { +-- +2.17.1 + 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..3fa6a9a79 --- /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> + + namespace phosphor + { +@@ -21,7 +22,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..9c3ab4dd2 --- /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,187 @@ +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; +@@ -74,6 +78,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; + } + +@@ -108,6 +114,8 @@ int Manager::verifyPFRImage(const std::filesystem::path imgPath, + + phosphor::logging::log<phosphor::logging::level::ERR>( + "Unknown image type"); ++ phosphor::logging::report<ImageFailure>( ++ ImageFail::PATH(imgPath.c_str())); + return -1; + } + +@@ -151,6 +159,8 @@ 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::PATH(imgPath.c_str())); + return -1; + } + +@@ -165,6 +175,8 @@ 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::PATH(imgPath.c_str())); + return -1; + } + } +@@ -180,6 +192,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/0011-Fix-for-RedudancyPriority-in-item_updater.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0011-Fix-for-RedudancyPriority-in-item_updater.patch new file mode 100644 index 000000000..4c8f82aa3 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0011-Fix-for-RedudancyPriority-in-item_updater.patch @@ -0,0 +1,38 @@ +From 0babf82f51561ac92a9b0dd56991d8de01930129 Mon Sep 17 00:00:00 2001 +From: Vikram Bodireddy <vikram.bodireddy@intel.com> +Date: Sun, 5 Jul 2020 00:54:57 +0530 +Subject: [PATCH] Fix for RedudancyPriority in item_updater + +This fixes accessing RedudancyPriority property for the +activated image in item_updater. The downloaded image object +is not actually associated with RedudancyPriority before and +after activation. There exists no RedundancyPriority property +for downloaded image, accessing it causing a crash in +item_updater. + +Tested: Tested for coredumps during Seamless firmware update. + +Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com> +--- + item_updater.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/item_updater.cpp b/item_updater.cpp +index af01e39..8d7bb82 100644 +--- a/item_updater.cpp ++++ b/item_updater.cpp +@@ -655,8 +655,9 @@ void ItemUpdater::freeSpace(Activation& caller) + // Failed activations don't have priority, assign them a large value + // for sorting purposes. + auto priority = 999; +- if (iter.second.get()->activation() == +- server::Activation::Activations::Active) ++ if ((iter.second.get()->activation() == ++ server::Activation::Activations::Active)&& ++ iter.second->redundancyPriority.get()) + { + priority = iter.second->redundancyPriority.get()->priority(); + } +-- +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..d5d0f513e --- /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 ae3a9616b44677f20b4ca534c3f55ccb478fdf55 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 ccdf594..c738945 100644 +--- a/watch.cpp ++++ b/watch.cpp +@@ -106,6 +106,15 @@ int Watch::callback(sd_event_source* /* s */, int fd, uint32_t revents, + { + log<level::ERR>("Error processing image", + entry("IMAGE=%s", tarballPath.c_str())); ++ std::error_code ec{}; ++ fs::remove_all(tarballPath, ec); ++ if (!ec) ++ { ++ log<level::ERR>( ++ "Unable to remove image on processing failure", ++ entry("ERROR=%s", ec.message().c_str()), ++ entry("IMAGE=%s", tarballPath.c_str())); ++ } + } + } + 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..64d9a47a6 --- /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=/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..623c4f77e --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend @@ -0,0 +1,25 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" +EXTRA_OECONF += "--enable-fwupd_script" + +SYSTEMD_SERVICE_${PN}-updater += "fwupd@.service" + +EXTRA_OECONF += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '--enable-pfr_update', '', d)}" + +SRC_URI += "file://0001-Add-more-error-types.patch \ + 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://0011-Fix-for-RedudancyPriority-in-item_updater.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 \ + " + +SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', SRC_URI_PFR, '', d)}" |