1 #include "config.h" 2 3 #include "msl_verify.hpp" 4 5 #include "version.hpp" 6 7 #include <phosphor-logging/elog-errors.hpp> 8 #include <phosphor-logging/elog.hpp> 9 #include <phosphor-logging/lg2.hpp> 10 #include <xyz/openbmc_project/Software/Version/error.hpp> 11 12 #include <regex> 13 14 PHOSPHOR_LOG2_USING; 15 16 int minimum_ship_level::compare(const Version& versionToCompare, 17 const Version& mslVersion) 18 { 19 if (versionToCompare.major > mslVersion.major) 20 { 21 return (1); 22 } 23 if (versionToCompare.major < mslVersion.major) 24 { 25 return (-1); 26 } 27 28 if (versionToCompare.minor > mslVersion.minor) 29 { 30 return (1); 31 } 32 if (versionToCompare.minor < mslVersion.minor) 33 { 34 return (-1); 35 } 36 37 if (versionToCompare.rev > mslVersion.rev) 38 { 39 return (1); 40 } 41 if (versionToCompare.rev < mslVersion.rev) 42 { 43 return (-1); 44 } 45 46 // Both string are equal and there is no need to make an upgrade return 0. 47 return 0; 48 } 49 50 // parse Function copy inpVersion onto outVersion in Version format 51 // {major,minor,rev}. 52 void minimum_ship_level::parse(const std::string& inpVersion, 53 Version& outVersion) 54 { 55 std::smatch match; 56 outVersion = {0, 0, 0}; 57 58 std::regex rx{REGEX_BMC_MSL, std::regex::extended}; 59 60 if (!std::regex_search(inpVersion, match, rx)) 61 { 62 error("Unable to parse BMC version: {VERSION}", "VERSION", inpVersion); 63 return; 64 } 65 66 outVersion.major = std::stoi(match[2]); 67 outVersion.minor = std::stoi(match[3]); 68 outVersion.rev = std::stoi(match[4]); 69 } 70 71 bool minimum_ship_level::verify(const std::string& versionManifest) 72 { 73 // If there is no msl or mslRegex return upgrade is needed. 74 if (!enabled()) 75 { 76 return true; 77 } 78 79 // Define mslVersion variable and populate in Version format 80 // {major,minor,rev} using parse function. 81 82 std::string msl = getMinimumVersion(); 83 Version mslVersion = {0, 0, 0}; 84 parse(msl, mslVersion); 85 86 // Define actualVersion variable and populate in Version format 87 // {major,minor,rev} using parse function. 88 std::string tmpStr{}; 89 90 tmpStr = versionManifest; 91 Version actualVersion = {0, 0, 0}; 92 parse(versionManifest, actualVersion); 93 94 // Compare actualVersion vs MSL. 95 auto rc = compare(actualVersion, mslVersion); 96 if (rc < 0) 97 { 98 using namespace phosphor::logging; 99 using IncompatibleErr = sdbusplus::error::xyz::openbmc_project:: 100 software::version::Incompatible; 101 using Incompatible = 102 xyz::openbmc_project::software::version::Incompatible; 103 std::string purpose = 104 "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"; 105 106 error( 107 "BMC Minimum Ship Level ({MIN_VERSION}) NOT met by {ACTUAL_VERSION}", 108 "MIN_VERSION", msl, "ACTUAL_VERSION", tmpStr, "VERSION_PURPOSE", 109 purpose); 110 report<IncompatibleErr>(Incompatible::MIN_VERSION(msl.c_str()), 111 Incompatible::ACTUAL_VERSION(tmpStr.c_str()), 112 Incompatible::VERSION_PURPOSE(purpose.c_str())); 113 return false; 114 } 115 116 return true; 117 } 118 119 bool minimum_ship_level::enabled() 120 { 121 std::string msl = getMinimumVersion(); 122 std::string mslRegex{REGEX_BMC_MSL}; 123 return !msl.empty() && !mslRegex.empty(); 124 } 125 126 std::string minimum_ship_level::getMinimumVersion() 127 { 128 return BMC_MSL; 129 } 130