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
compare(const Version & versionToCompare,const Version & mslVersion)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}.
parse(const std::string & inpVersion,Version & outVersion)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
verify(const std::string & versionManifest)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
enabled()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
getMinimumVersion()126 std::string minimum_ship_level::getMinimumVersion()
127 {
128 return BMC_MSL;
129 }
130