summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/flash
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2019-12-16 23:21:26 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2019-12-17 00:07:50 +0300
commit4aeb24cf629a60980d4ad270fc1750754826613d (patch)
tree2b1448d35f422dfc4762616a1b9adbb8ff9d6ca0 /meta-openbmc-mods/meta-common/recipes-phosphor/flash
parent506611d226c82d05215ec3d2dab50a43a531b691 (diff)
downloadopenbmc-4aeb24cf629a60980d4ad270fc1750754826613d.tar.xz
Update to internal 2019-12-16
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
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/0007-Adding-StandBySpare-for-firmware-activation.patch76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch408
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend7
4 files changed, 492 insertions, 3 deletions
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/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..31373104f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch
@@ -0,0 +1,408 @@
+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.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+---
+ pfr_image_manager.cpp | 149 ++++++++++++++++++++++++++++++++----------
+ pfr_image_manager.hpp | 112 +++++++++++++++++++++++++++++--
+ 2 files changed, 221 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,20 @@ 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");
+ 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/fwupd@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
index d51fee312..64d9a47a6 100644
--- 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
@@ -4,5 +4,5 @@ Description=Flash BMC with fwupd script : %I
[Service]
Type=oneshot
RemainAfterExit=no
-ExecStart=/usr/bin/fwupd.sh file:////tmp/images/%i/image-runtime
-SyslogIdentifier=fwupd \ No newline at end of file
+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
index 90da32ac2..96ddfc3ca 100644
--- 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
@@ -9,6 +9,11 @@ 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 \
"
-SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'file://0007-PFR-images-support.patch', '', d)}"
+SRC_URI_PFR = "file://0007-PFR-images-support.patch \
+ file://0008-PFR-image-HASH-verification.patch \
+ "
+
+SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', SRC_URI_PFR, '', d)}"