121dad047SMiguel Gomez #include "config.h"
221dad047SMiguel Gomez 
321dad047SMiguel Gomez #include "msl_verify.hpp"
421dad047SMiguel Gomez 
521dad047SMiguel Gomez #include "version.hpp"
621dad047SMiguel Gomez 
7*c9bb6425SPatrick Williams #include <phosphor-logging/lg2.hpp>
8*c9bb6425SPatrick Williams #include <xyz/openbmc_project/Software/Version/server.hpp>
921dad047SMiguel Gomez 
1021dad047SMiguel Gomez #include <regex>
1121dad047SMiguel Gomez 
12*c9bb6425SPatrick Williams PHOSPHOR_LOG2_USING;
1321dad047SMiguel Gomez 
1421dad047SMiguel Gomez int minimum_ship_level::compare(const Version& versionToCompare,
1521dad047SMiguel Gomez                                 const Version& mslVersion)
1621dad047SMiguel Gomez {
1721dad047SMiguel Gomez     if (versionToCompare.major > mslVersion.major)
1821dad047SMiguel Gomez         return (1);
1921dad047SMiguel Gomez     if (versionToCompare.major < mslVersion.major)
2021dad047SMiguel Gomez         return (-1);
2121dad047SMiguel Gomez 
2221dad047SMiguel Gomez     if (versionToCompare.minor > mslVersion.minor)
2321dad047SMiguel Gomez         return (1);
2421dad047SMiguel Gomez     if (versionToCompare.minor < mslVersion.minor)
2521dad047SMiguel Gomez         return (-1);
2621dad047SMiguel Gomez 
2721dad047SMiguel Gomez     if (versionToCompare.rev > mslVersion.rev)
2821dad047SMiguel Gomez         return (1);
2921dad047SMiguel Gomez     if (versionToCompare.rev < mslVersion.rev)
3021dad047SMiguel Gomez         return (-1);
3121dad047SMiguel Gomez 
3221dad047SMiguel Gomez     // Both string are equal and there is no need to make an upgrade return 0.
3321dad047SMiguel Gomez     return 0;
3421dad047SMiguel Gomez }
3521dad047SMiguel Gomez 
3621dad047SMiguel Gomez // parse Function copy  inpVersion onto outVersion in Version format
3721dad047SMiguel Gomez // {major,minor,rev}.
3821dad047SMiguel Gomez void minimum_ship_level::parse(const std::string& inpVersion,
3921dad047SMiguel Gomez                                Version& outVersion)
4021dad047SMiguel Gomez {
4121dad047SMiguel Gomez     std::smatch match;
4221dad047SMiguel Gomez     outVersion = {0, 0, 0};
4321dad047SMiguel Gomez 
4421dad047SMiguel Gomez     std::regex rx{REGEX_BMC_MSL, std::regex::extended};
4521dad047SMiguel Gomez 
4621dad047SMiguel Gomez     if (!std::regex_search(inpVersion, match, rx))
4721dad047SMiguel Gomez     {
48*c9bb6425SPatrick Williams         error("Unable to parse BMC version: {VERSION}", "VERSION", inpVersion);
4921dad047SMiguel Gomez         return;
5021dad047SMiguel Gomez     }
5121dad047SMiguel Gomez 
5221dad047SMiguel Gomez     outVersion.major = std::stoi(match[2]);
5321dad047SMiguel Gomez     outVersion.minor = std::stoi(match[3]);
5421dad047SMiguel Gomez     outVersion.rev = std::stoi(match[4]);
5521dad047SMiguel Gomez }
5621dad047SMiguel Gomez 
5721dad047SMiguel Gomez bool minimum_ship_level::verify(const std::string& versionManifest)
5821dad047SMiguel Gomez {
5921dad047SMiguel Gomez 
6021dad047SMiguel Gomez     //  If there is no msl or mslRegex return upgrade is needed.
6121dad047SMiguel Gomez     std::string msl{BMC_MSL};
6221dad047SMiguel Gomez     std::string mslRegex{REGEX_BMC_MSL};
6321dad047SMiguel Gomez     if (msl.empty() || mslRegex.empty())
6421dad047SMiguel Gomez     {
6521dad047SMiguel Gomez         return true;
6621dad047SMiguel Gomez     }
6721dad047SMiguel Gomez 
6821dad047SMiguel Gomez     // Define mslVersion variable and populate in Version format
6921dad047SMiguel Gomez     // {major,minor,rev} using parse function.
7021dad047SMiguel Gomez 
7121dad047SMiguel Gomez     Version mslVersion = {0, 0, 0};
7221dad047SMiguel Gomez     parse(msl, mslVersion);
7321dad047SMiguel Gomez 
7421dad047SMiguel Gomez     // Define actualVersion variable and populate in Version format
7521dad047SMiguel Gomez     // {major,minor,rev} using parse function.
7621dad047SMiguel Gomez     std::string tmpStr{};
7721dad047SMiguel Gomez 
7821dad047SMiguel Gomez     tmpStr = versionManifest;
7921dad047SMiguel Gomez     Version actualVersion = {0, 0, 0};
8021dad047SMiguel Gomez     parse(versionManifest, actualVersion);
8121dad047SMiguel Gomez 
8221dad047SMiguel Gomez     // Compare actualVersion vs MSL.
8321dad047SMiguel Gomez     auto rc = compare(actualVersion, mslVersion);
8421dad047SMiguel Gomez     if (rc < 0)
8521dad047SMiguel Gomez     {
86*c9bb6425SPatrick Williams         auto purpose = sdbusplus::xyz::openbmc_project::Software::server::
87*c9bb6425SPatrick Williams             Version::VersionPurpose::BMC;
88*c9bb6425SPatrick Williams         error(
89*c9bb6425SPatrick Williams             "BMC Minimum Ship Level ({MIN_VERSION}) NOT met by {ACTUAL_VERSION}",
90*c9bb6425SPatrick Williams             "MIN_VERSION", msl, "ACTUAL_VERSION", tmpStr, "VERSION_PURPOSE",
91*c9bb6425SPatrick Williams             purpose);
9221dad047SMiguel Gomez         return false;
9321dad047SMiguel Gomez     }
9421dad047SMiguel Gomez 
9521dad047SMiguel Gomez     return true;
9621dad047SMiguel Gomez }
97