| #include "config.h" |
| |
| #include "msl_verify.hpp" |
| |
| #include "version.hpp" |
| |
| #include <phosphor-logging/elog-errors.hpp> |
| #include <phosphor-logging/elog.hpp> |
| #include <phosphor-logging/lg2.hpp> |
| #include <xyz/openbmc_project/Software/Version/error.hpp> |
| |
| #include <regex> |
| |
| PHOSPHOR_LOG2_USING; |
| |
| int minimum_ship_level::compare(const Version& versionToCompare, |
| const Version& mslVersion) |
| { |
| if (versionToCompare.major > mslVersion.major) |
| return (1); |
| if (versionToCompare.major < mslVersion.major) |
| return (-1); |
| |
| if (versionToCompare.minor > mslVersion.minor) |
| return (1); |
| if (versionToCompare.minor < mslVersion.minor) |
| return (-1); |
| |
| if (versionToCompare.rev > mslVersion.rev) |
| return (1); |
| if (versionToCompare.rev < mslVersion.rev) |
| return (-1); |
| |
| // Both string are equal and there is no need to make an upgrade return 0. |
| return 0; |
| } |
| |
| // parse Function copy inpVersion onto outVersion in Version format |
| // {major,minor,rev}. |
| void minimum_ship_level::parse(const std::string& inpVersion, |
| Version& outVersion) |
| { |
| std::smatch match; |
| outVersion = {0, 0, 0}; |
| |
| std::regex rx{REGEX_BMC_MSL, std::regex::extended}; |
| |
| if (!std::regex_search(inpVersion, match, rx)) |
| { |
| error("Unable to parse BMC version: {VERSION}", "VERSION", inpVersion); |
| return; |
| } |
| |
| outVersion.major = std::stoi(match[2]); |
| outVersion.minor = std::stoi(match[3]); |
| outVersion.rev = std::stoi(match[4]); |
| } |
| |
| bool minimum_ship_level::verify(const std::string& versionManifest) |
| { |
| // If there is no msl or mslRegex return upgrade is needed. |
| if (!enabled()) |
| { |
| return true; |
| } |
| |
| // Define mslVersion variable and populate in Version format |
| // {major,minor,rev} using parse function. |
| |
| std::string msl = getMinimumVersion(); |
| Version mslVersion = {0, 0, 0}; |
| parse(msl, mslVersion); |
| |
| // Define actualVersion variable and populate in Version format |
| // {major,minor,rev} using parse function. |
| std::string tmpStr{}; |
| |
| tmpStr = versionManifest; |
| Version actualVersion = {0, 0, 0}; |
| parse(versionManifest, actualVersion); |
| |
| // Compare actualVersion vs MSL. |
| auto rc = compare(actualVersion, mslVersion); |
| if (rc < 0) |
| { |
| using namespace phosphor::logging; |
| using IncompatibleErr = sdbusplus::error::xyz::openbmc_project:: |
| software::version::Incompatible; |
| using Incompatible = |
| xyz::openbmc_project::software::version::Incompatible; |
| std::string purpose = |
| "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"; |
| |
| error( |
| "BMC Minimum Ship Level ({MIN_VERSION}) NOT met by {ACTUAL_VERSION}", |
| "MIN_VERSION", msl, "ACTUAL_VERSION", tmpStr, "VERSION_PURPOSE", |
| purpose); |
| report<IncompatibleErr>(Incompatible::MIN_VERSION(msl.c_str()), |
| Incompatible::ACTUAL_VERSION(tmpStr.c_str()), |
| Incompatible::VERSION_PURPOSE(purpose.c_str())); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool minimum_ship_level::enabled() |
| { |
| std::string msl = getMinimumVersion(); |
| std::string mslRegex{REGEX_BMC_MSL}; |
| if (!msl.empty() && !mslRegex.empty()) |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| std::string minimum_ship_level::getMinimumVersion() |
| { |
| return BMC_MSL; |
| } |