blob: 1a6234cbb3ed499958cc49d4257feda1248e1a17 [file] [log] [blame]
Adriana Kobylak4772a942018-10-09 15:26:44 -05001#include "config.h"
2
3#include "msl_verify.hpp"
4
5#include <experimental/filesystem>
6#include <fstream>
7#include <phosphor-logging/log.hpp>
8#include <regex>
9
10namespace openpower
11{
12namespace software
13{
14namespace image
15{
16
17namespace fs = std::experimental::filesystem;
18using namespace phosphor::logging;
19
20int MinimumShipLevel::compare(const Version& a, const Version& b)
21{
22 if (a.major < b.major)
23 {
24 return -1;
25 }
26 else if (a.major > b.major)
27 {
28 return 1;
29 }
30
31 if (a.minor < b.minor)
32 {
33 return -1;
34 }
35 else if (a.minor > b.minor)
36 {
37 return 1;
38 }
39
40 if (a.rev < b.rev)
41 {
42 return -1;
43 }
44 else if (a.rev > b.rev)
45 {
46 return 1;
47 }
48
49 return 0;
50}
51
52void MinimumShipLevel::parse(const std::string& versionStr, Version& version)
53{
54 std::smatch match;
55 version = {0, 0, 0};
56
57 // Match for vX.Y.Z
58 std::regex regex{"v([0-9]+)\\.([0-9]+)\\.([0-9]+)", std::regex::extended};
59
60 if (!std::regex_search(versionStr, match, regex))
61 {
62 // Match for vX.Y
63 std::regex regexShort{"v([0-9]+)\\.([0-9]+)", std::regex::extended};
64 if (!std::regex_search(versionStr, match, regexShort))
65 {
66 log<level::ERR>("Unable to parse PNOR version",
67 entry("VERSION=%s", versionStr.c_str()));
68 return;
69 }
70 }
71 else
72 {
73 // Populate Z
74 version.rev = std::stoi(match[3]);
75 }
76 version.major = std::stoi(match[1]);
77 version.minor = std::stoi(match[2]);
78}
79
80std::string MinimumShipLevel::getFunctionalVersion()
81{
82 if (!fs::exists(PNOR_RO_ACTIVE_PATH))
83 {
84 return {};
85 }
86
87 fs::path versionPath(PNOR_RO_ACTIVE_PATH);
88 versionPath /= PNOR_VERSION_PARTITION;
89 if (!fs::is_regular_file(versionPath))
90 {
91 return {};
92 }
93
94 std::ifstream versionFile(versionPath);
95 std::string versionStr;
96 std::getline(versionFile, versionStr);
97
98 return versionStr;
99}
100
101bool MinimumShipLevel::verify()
102{
103 if (minShipLevel.empty())
104 {
105 return true;
106 }
107
108 auto actual = getFunctionalVersion();
109 if (actual.empty())
110 {
111 return true;
112 }
113
114 Version minVersion = {0, 0, 0};
115 parse(minShipLevel, minVersion);
116
117 Version actualVersion = {0, 0, 0};
118 parse(actual, actualVersion);
119
120 auto rc = compare(actualVersion, minVersion);
121 if (rc < 0)
122 {
123 log<level::ERR>(
124 "PNOR Mininum Ship Level NOT met",
125 entry("MIN_VERSION=%s", minShipLevel.c_str()),
126 entry("ACTUAL_VERSION=%s", actual.c_str()),
127 entry("VERSION_PURPOSE=%s",
128 "xyz.openbmc_project.Software.Version.VersionPurpose.Host"));
129 return false;
130 }
131
132 return true;
133}
134
135} // namespace image
136} // namespace software
137} // namespace openpower