summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch411
1 files changed, 411 insertions, 0 deletions
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
+