121dad047SMiguel Gomez #include "config.h" 221dad047SMiguel Gomez 321dad047SMiguel Gomez #include "msl_verify.hpp" 421dad047SMiguel Gomez 521dad047SMiguel Gomez #include "version.hpp" 621dad047SMiguel Gomez 710ec9750Szamiseck #include <phosphor-logging/elog-errors.hpp> 810ec9750Szamiseck #include <phosphor-logging/elog.hpp> 9c9bb6425SPatrick Williams #include <phosphor-logging/lg2.hpp> 1010ec9750Szamiseck #include <xyz/openbmc_project/Software/Version/error.hpp> 1121dad047SMiguel Gomez 1221dad047SMiguel Gomez #include <regex> 1321dad047SMiguel Gomez 14c9bb6425SPatrick Williams PHOSPHOR_LOG2_USING; 1521dad047SMiguel Gomez 1621dad047SMiguel Gomez int minimum_ship_level::compare(const Version& versionToCompare, 1721dad047SMiguel Gomez const Version& mslVersion) 1821dad047SMiguel Gomez { 1921dad047SMiguel Gomez if (versionToCompare.major > mslVersion.major) 20*ce9a5c9aSPavithra Barithaya { 2121dad047SMiguel Gomez return (1); 22*ce9a5c9aSPavithra Barithaya } 2321dad047SMiguel Gomez if (versionToCompare.major < mslVersion.major) 24*ce9a5c9aSPavithra Barithaya { 2521dad047SMiguel Gomez return (-1); 26*ce9a5c9aSPavithra Barithaya } 2721dad047SMiguel Gomez 2821dad047SMiguel Gomez if (versionToCompare.minor > mslVersion.minor) 29*ce9a5c9aSPavithra Barithaya { 3021dad047SMiguel Gomez return (1); 31*ce9a5c9aSPavithra Barithaya } 3221dad047SMiguel Gomez if (versionToCompare.minor < mslVersion.minor) 33*ce9a5c9aSPavithra Barithaya { 3421dad047SMiguel Gomez return (-1); 35*ce9a5c9aSPavithra Barithaya } 3621dad047SMiguel Gomez 3721dad047SMiguel Gomez if (versionToCompare.rev > mslVersion.rev) 38*ce9a5c9aSPavithra Barithaya { 3921dad047SMiguel Gomez return (1); 40*ce9a5c9aSPavithra Barithaya } 4121dad047SMiguel Gomez if (versionToCompare.rev < mslVersion.rev) 42*ce9a5c9aSPavithra Barithaya { 4321dad047SMiguel Gomez return (-1); 44*ce9a5c9aSPavithra Barithaya } 4521dad047SMiguel Gomez 4621dad047SMiguel Gomez // Both string are equal and there is no need to make an upgrade return 0. 4721dad047SMiguel Gomez return 0; 4821dad047SMiguel Gomez } 4921dad047SMiguel Gomez 5021dad047SMiguel Gomez // parse Function copy inpVersion onto outVersion in Version format 5121dad047SMiguel Gomez // {major,minor,rev}. 5221dad047SMiguel Gomez void minimum_ship_level::parse(const std::string& inpVersion, 5321dad047SMiguel Gomez Version& outVersion) 5421dad047SMiguel Gomez { 5521dad047SMiguel Gomez std::smatch match; 5621dad047SMiguel Gomez outVersion = {0, 0, 0}; 5721dad047SMiguel Gomez 5821dad047SMiguel Gomez std::regex rx{REGEX_BMC_MSL, std::regex::extended}; 5921dad047SMiguel Gomez 6021dad047SMiguel Gomez if (!std::regex_search(inpVersion, match, rx)) 6121dad047SMiguel Gomez { 62c9bb6425SPatrick Williams error("Unable to parse BMC version: {VERSION}", "VERSION", inpVersion); 6321dad047SMiguel Gomez return; 6421dad047SMiguel Gomez } 6521dad047SMiguel Gomez 6621dad047SMiguel Gomez outVersion.major = std::stoi(match[2]); 6721dad047SMiguel Gomez outVersion.minor = std::stoi(match[3]); 6821dad047SMiguel Gomez outVersion.rev = std::stoi(match[4]); 6921dad047SMiguel Gomez } 7021dad047SMiguel Gomez 7121dad047SMiguel Gomez bool minimum_ship_level::verify(const std::string& versionManifest) 7221dad047SMiguel Gomez { 7321dad047SMiguel Gomez // If there is no msl or mslRegex return upgrade is needed. 7430352a66SAdriana Kobylak if (!enabled()) 7521dad047SMiguel Gomez { 7621dad047SMiguel Gomez return true; 7721dad047SMiguel Gomez } 7821dad047SMiguel Gomez 7921dad047SMiguel Gomez // Define mslVersion variable and populate in Version format 8021dad047SMiguel Gomez // {major,minor,rev} using parse function. 8121dad047SMiguel Gomez 8230352a66SAdriana Kobylak std::string msl = getMinimumVersion(); 8321dad047SMiguel Gomez Version mslVersion = {0, 0, 0}; 8421dad047SMiguel Gomez parse(msl, mslVersion); 8521dad047SMiguel Gomez 8621dad047SMiguel Gomez // Define actualVersion variable and populate in Version format 8721dad047SMiguel Gomez // {major,minor,rev} using parse function. 8821dad047SMiguel Gomez std::string tmpStr{}; 8921dad047SMiguel Gomez 9021dad047SMiguel Gomez tmpStr = versionManifest; 9121dad047SMiguel Gomez Version actualVersion = {0, 0, 0}; 9221dad047SMiguel Gomez parse(versionManifest, actualVersion); 9321dad047SMiguel Gomez 9421dad047SMiguel Gomez // Compare actualVersion vs MSL. 9521dad047SMiguel Gomez auto rc = compare(actualVersion, mslVersion); 9621dad047SMiguel Gomez if (rc < 0) 9721dad047SMiguel Gomez { 9810ec9750Szamiseck using namespace phosphor::logging; 99ce82de51SAdriana Kobylak using IncompatibleErr = sdbusplus::error::xyz::openbmc_project:: 100ce82de51SAdriana Kobylak software::version::Incompatible; 10110ec9750Szamiseck using Incompatible = 102ce82de51SAdriana Kobylak xyz::openbmc_project::software::version::Incompatible; 10310ec9750Szamiseck std::string purpose = 10410ec9750Szamiseck "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"; 10510ec9750Szamiseck 106c9bb6425SPatrick Williams error( 107c9bb6425SPatrick Williams "BMC Minimum Ship Level ({MIN_VERSION}) NOT met by {ACTUAL_VERSION}", 108c9bb6425SPatrick Williams "MIN_VERSION", msl, "ACTUAL_VERSION", tmpStr, "VERSION_PURPOSE", 109c9bb6425SPatrick Williams purpose); 11010ec9750Szamiseck report<IncompatibleErr>(Incompatible::MIN_VERSION(msl.c_str()), 11110ec9750Szamiseck Incompatible::ACTUAL_VERSION(tmpStr.c_str()), 11210ec9750Szamiseck Incompatible::VERSION_PURPOSE(purpose.c_str())); 11321dad047SMiguel Gomez return false; 11421dad047SMiguel Gomez } 11521dad047SMiguel Gomez 11621dad047SMiguel Gomez return true; 11721dad047SMiguel Gomez } 11830352a66SAdriana Kobylak 11930352a66SAdriana Kobylak bool minimum_ship_level::enabled() 12030352a66SAdriana Kobylak { 12130352a66SAdriana Kobylak std::string msl = getMinimumVersion(); 12230352a66SAdriana Kobylak std::string mslRegex{REGEX_BMC_MSL}; 12330352a66SAdriana Kobylak if (!msl.empty() && !mslRegex.empty()) 12430352a66SAdriana Kobylak { 12530352a66SAdriana Kobylak return true; 12630352a66SAdriana Kobylak } 12730352a66SAdriana Kobylak return false; 12830352a66SAdriana Kobylak } 12930352a66SAdriana Kobylak 13030352a66SAdriana Kobylak std::string minimum_ship_level::getMinimumVersion() 13130352a66SAdriana Kobylak { 13230352a66SAdriana Kobylak return BMC_MSL; 13330352a66SAdriana Kobylak } 134