-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a new binary that checks the msl (minimum ship level) of the PNOR and logs an error message if the version on the system is older. The msl can be specified via a config flag. Change-Id: I6f477400f7a8cf56557bd0caf5d6e08d73320028 Signed-off-by: Adriana Kobylak <[email protected]>
- Loading branch information
Showing
7 changed files
with
329 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
#include "config.h" | ||
|
||
#include "msl_verify.hpp" | ||
|
||
#include <experimental/filesystem> | ||
#include <fstream> | ||
#include <phosphor-logging/log.hpp> | ||
#include <regex> | ||
|
||
namespace openpower | ||
{ | ||
namespace software | ||
{ | ||
namespace image | ||
{ | ||
|
||
namespace fs = std::experimental::filesystem; | ||
using namespace phosphor::logging; | ||
|
||
int MinimumShipLevel::compare(const Version& a, const Version& b) | ||
{ | ||
if (a.major < b.major) | ||
{ | ||
return -1; | ||
} | ||
else if (a.major > b.major) | ||
{ | ||
return 1; | ||
} | ||
|
||
if (a.minor < b.minor) | ||
{ | ||
return -1; | ||
} | ||
else if (a.minor > b.minor) | ||
{ | ||
return 1; | ||
} | ||
|
||
if (a.rev < b.rev) | ||
{ | ||
return -1; | ||
} | ||
else if (a.rev > b.rev) | ||
{ | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
void MinimumShipLevel::parse(const std::string& versionStr, Version& version) | ||
{ | ||
std::smatch match; | ||
version = {0, 0, 0}; | ||
|
||
// Match for vX.Y.Z | ||
std::regex regex{"v([0-9]+)\\.([0-9]+)\\.([0-9]+)", std::regex::extended}; | ||
|
||
if (!std::regex_search(versionStr, match, regex)) | ||
{ | ||
// Match for vX.Y | ||
std::regex regexShort{"v([0-9]+)\\.([0-9]+)", std::regex::extended}; | ||
if (!std::regex_search(versionStr, match, regexShort)) | ||
{ | ||
log<level::ERR>("Unable to parse PNOR version", | ||
entry("VERSION=%s", versionStr.c_str())); | ||
return; | ||
} | ||
} | ||
else | ||
{ | ||
// Populate Z | ||
version.rev = std::stoi(match[3]); | ||
} | ||
version.major = std::stoi(match[1]); | ||
version.minor = std::stoi(match[2]); | ||
} | ||
|
||
std::string MinimumShipLevel::getFunctionalVersion() | ||
{ | ||
if (!fs::exists(PNOR_RO_ACTIVE_PATH)) | ||
{ | ||
return {}; | ||
} | ||
|
||
fs::path versionPath(PNOR_RO_ACTIVE_PATH); | ||
versionPath /= PNOR_VERSION_PARTITION; | ||
if (!fs::is_regular_file(versionPath)) | ||
{ | ||
return {}; | ||
} | ||
|
||
std::ifstream versionFile(versionPath); | ||
std::string versionStr; | ||
std::getline(versionFile, versionStr); | ||
|
||
return versionStr; | ||
} | ||
|
||
bool MinimumShipLevel::verify() | ||
{ | ||
if (minShipLevel.empty()) | ||
{ | ||
return true; | ||
} | ||
|
||
auto actual = getFunctionalVersion(); | ||
if (actual.empty()) | ||
{ | ||
return true; | ||
} | ||
|
||
Version minVersion = {0, 0, 0}; | ||
parse(minShipLevel, minVersion); | ||
|
||
Version actualVersion = {0, 0, 0}; | ||
parse(actual, actualVersion); | ||
|
||
auto rc = compare(actualVersion, minVersion); | ||
if (rc < 0) | ||
{ | ||
log<level::ERR>( | ||
"PNOR Mininum Ship Level NOT met", | ||
entry("MIN_VERSION=%s", minShipLevel.c_str()), | ||
entry("ACTUAL_VERSION=%s", actual.c_str()), | ||
entry("VERSION_PURPOSE=%s", | ||
"xyz.openbmc_project.Software.Version.VersionPurpose.Host")); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
} // namespace image | ||
} // namespace software | ||
} // namespace openpower |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
namespace openpower | ||
{ | ||
namespace software | ||
{ | ||
namespace image | ||
{ | ||
|
||
/** @class MinimumShipLevel | ||
* @brief Contains minimum ship level verification functions. | ||
*/ | ||
class MinimumShipLevel | ||
{ | ||
public: | ||
MinimumShipLevel() = delete; | ||
MinimumShipLevel(const MinimumShipLevel&) = delete; | ||
MinimumShipLevel& operator=(const MinimumShipLevel&) = delete; | ||
MinimumShipLevel(MinimumShipLevel&&) = default; | ||
MinimumShipLevel& operator=(MinimumShipLevel&&) = default; | ||
~MinimumShipLevel() = default; | ||
|
||
/** @brief Constructs MinimumShipLevel. | ||
* @param[in] minShipLevel - Minimum Ship Level string | ||
*/ | ||
MinimumShipLevel(const std::string& minShipLevel) : | ||
minShipLevel(minShipLevel){}; | ||
|
||
/** @brief Verify if the current PNOR version meets the min ship level | ||
* @return true if the verification succeeded, false otherwise | ||
*/ | ||
bool verify(); | ||
|
||
/** @brief Version components */ | ||
struct Version | ||
{ | ||
uint8_t major; | ||
uint8_t minor; | ||
uint8_t rev; | ||
}; | ||
|
||
/** @brief Get the functional PNOR version on the system | ||
* @details If the PNOR version file is not found, don't log an error since | ||
* all PNOR images may had been deleted. If there is an issue with | ||
* the VERSION partition, it should be caught by the host fw code. | ||
* @return The populated or empty version string | ||
*/ | ||
std::string getFunctionalVersion(); | ||
|
||
/** @brief Parse the version components into a struct | ||
* @details Version format follows a git tag convention: vX.Y[.Z] | ||
* Reference: | ||
* https://github.com/open-power/op-build/blob/master/openpower/package/VERSION.readme | ||
* @param[in] versionStr - The version string to be parsed | ||
* @param[out] version - The version struct to be populated | ||
*/ | ||
void parse(const std::string& versionStr, Version& version); | ||
|
||
/** @brief Compare the versions provided | ||
* @param[in] a - The first version to compare | ||
* @param[in] b - The second version to compare | ||
* @return 1 if a > b | ||
* 0 if a = b | ||
* -1 if a < b | ||
*/ | ||
int compare(const Version& a, const Version& b); | ||
|
||
private: | ||
/** Minimum Ship Level to compare against */ | ||
std::string minShipLevel; | ||
}; | ||
|
||
} // namespace image | ||
} // namespace software | ||
} // namespace openpower |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include "config.h" | ||
|
||
#include "msl_verify.hpp" | ||
|
||
int main(int argc, char* argv[]) | ||
{ | ||
using MinimumShipLevel = openpower::software::image::MinimumShipLevel; | ||
MinimumShipLevel minimumShipLevel(PNOR_MSL); | ||
|
||
if (!minimumShipLevel.verify()) | ||
{ | ||
// TODO Create error log | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#include "msl_verify.hpp" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace openpower | ||
{ | ||
namespace software | ||
{ | ||
namespace image | ||
{ | ||
|
||
class MinimumShipLevelTest : public testing::Test | ||
{ | ||
protected: | ||
std::string minShipLevel = "v.2.2"; | ||
std::unique_ptr<MinimumShipLevel> minimumShipLevel; | ||
|
||
virtual void SetUp() | ||
{ | ||
minimumShipLevel = std::make_unique<MinimumShipLevel>(minShipLevel); | ||
} | ||
}; | ||
|
||
TEST_F(MinimumShipLevelTest, compare) | ||
{ | ||
MinimumShipLevel::Version min; | ||
MinimumShipLevel::Version actual; | ||
|
||
min = {3, 5, 7}; | ||
|
||
// actual = min | ||
actual = {3, 5, 7}; | ||
EXPECT_EQ(0, minimumShipLevel->compare(actual, min)); | ||
|
||
// actual < min | ||
actual = {3, 5, 6}; | ||
EXPECT_EQ(-1, minimumShipLevel->compare(actual, min)); | ||
actual = {3, 4, 7}; | ||
EXPECT_EQ(-1, minimumShipLevel->compare(actual, min)); | ||
actual = {2, 5, 7}; | ||
EXPECT_EQ(-1, minimumShipLevel->compare(actual, min)); | ||
|
||
// actual > min | ||
actual = {3, 5, 8}; | ||
EXPECT_EQ(1, minimumShipLevel->compare(actual, min)); | ||
actual = {3, 6, 7}; | ||
EXPECT_EQ(1, minimumShipLevel->compare(actual, min)); | ||
actual = {4, 5, 7}; | ||
EXPECT_EQ(1, minimumShipLevel->compare(actual, min)); | ||
} | ||
|
||
TEST_F(MinimumShipLevelTest, parse) | ||
{ | ||
MinimumShipLevel::Version version; | ||
std::string versionStr; | ||
|
||
versionStr = "nomatch-1.2.3-abc"; | ||
minimumShipLevel->parse(versionStr, version); | ||
EXPECT_EQ(0, version.major); | ||
EXPECT_EQ(0, version.minor); | ||
EXPECT_EQ(0, version.rev); | ||
|
||
versionStr = "xyzformat-v1.2.3-4.5abc"; | ||
minimumShipLevel->parse(versionStr, version); | ||
EXPECT_EQ(1, version.major); | ||
EXPECT_EQ(2, version.minor); | ||
EXPECT_EQ(3, version.rev); | ||
|
||
versionStr = "xyformat-system-v6.7-abc"; | ||
minimumShipLevel->parse(versionStr, version); | ||
EXPECT_EQ(6, version.major); | ||
EXPECT_EQ(7, version.minor); | ||
EXPECT_EQ(0, version.rev); | ||
} | ||
|
||
} // namespace image | ||
} // namespace software | ||
} // namespace openpower |