blob: f6bc363324d84cdb913f743d4098a42fb29fae16 [file] [log] [blame]
Eddie James6d873712017-09-01 11:29:07 -05001#include "config.h"
Gunnar Millsb0ce9962018-09-07 13:39:10 -05002
Gunnar Mills392f2942017-04-12 11:04:37 -05003#include "version.hpp"
4
Gunnar Millsb0ce9962018-09-07 13:39:10 -05005#include "xyz/openbmc_project/Common/error.hpp"
6
7#include <openssl/sha.h>
8
Gunnar Millsb0ce9962018-09-07 13:39:10 -05009#include <phosphor-logging/elog-errors.hpp>
10#include <phosphor-logging/log.hpp>
Adriana Kobylak58aa7502020-06-08 11:12:11 -050011
12#include <fstream>
13#include <iostream>
Gunnar Millsb0ce9962018-09-07 13:39:10 -050014#include <sstream>
15#include <stdexcept>
16#include <string>
17
Gunnar Mills392f2942017-04-12 11:04:37 -050018namespace phosphor
19{
20namespace software
21{
22namespace manager
23{
24
25using namespace phosphor::logging;
Gunnar Millsaae1b2b2017-10-06 13:42:39 -050026using Argument = xyz::openbmc_project::Common::InvalidArgument;
27using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Gunnar Mills392f2942017-04-12 11:04:37 -050028
Gunnar Millscebd1022017-04-17 16:10:15 -050029std::string Version::getValue(const std::string& manifestFilePath,
30 std::string key)
Gunnar Mills392f2942017-04-12 11:04:37 -050031{
Gunnar Millscebd1022017-04-17 16:10:15 -050032 key = key + "=";
33 auto keySize = key.length();
Gunnar Mills392f2942017-04-12 11:04:37 -050034
35 if (manifestFilePath.empty())
36 {
37 log<level::ERR>("Error MANIFESTFilePath is empty");
Gunnar Millsaae1b2b2017-10-06 13:42:39 -050038 elog<InvalidArgument>(
Adriana Kobylak2285fe02018-02-27 15:36:59 -060039 Argument::ARGUMENT_NAME("manifestFilePath"),
40 Argument::ARGUMENT_VALUE(manifestFilePath.c_str()));
Gunnar Mills392f2942017-04-12 11:04:37 -050041 }
42
Gunnar Millscebd1022017-04-17 16:10:15 -050043 std::string value{};
Gunnar Mills392f2942017-04-12 11:04:37 -050044 std::ifstream efile;
45 std::string line;
Adriana Kobylak2285fe02018-02-27 15:36:59 -060046 efile.exceptions(std::ifstream::failbit | std::ifstream::badbit |
Gunnar Millsaae1b2b2017-10-06 13:42:39 -050047 std::ifstream::eofbit);
Gunnar Mills392f2942017-04-12 11:04:37 -050048
49 // Too many GCC bugs (53984, 66145) to do this the right way...
50 try
51 {
52 efile.open(manifestFilePath);
53 while (getline(efile, line))
54 {
Lei YU5a7363b2019-10-18 16:50:59 +080055 if (!line.empty() && line.back() == '\r')
56 {
57 // If the manifest has CRLF line terminators, e.g. is created on
58 // Windows, the line will contain \r at the end, remove it.
59 line.pop_back();
60 }
Gunnar Millscebd1022017-04-17 16:10:15 -050061 if (line.compare(0, keySize, key) == 0)
Gunnar Mills392f2942017-04-12 11:04:37 -050062 {
Gunnar Millscebd1022017-04-17 16:10:15 -050063 value = line.substr(keySize);
Gunnar Mills392f2942017-04-12 11:04:37 -050064 break;
65 }
66 }
67 efile.close();
68 }
69 catch (const std::exception& e)
70 {
Isaac Kurthfa799142021-06-03 14:04:31 -050071 log<level::ERR>("Error occurred when reading MANIFEST file",
72 entry("KEY=%s", key.c_str()),
73 entry("ERROR=%s", e.what()));
Gunnar Mills392f2942017-04-12 11:04:37 -050074 }
75
Gunnar Millscebd1022017-04-17 16:10:15 -050076 return value;
Gunnar Mills392f2942017-04-12 11:04:37 -050077}
78
79std::string Version::getId(const std::string& version)
80{
Gunnar Mills392f2942017-04-12 11:04:37 -050081
82 if (version.empty())
83 {
Gunnar Millscebd1022017-04-17 16:10:15 -050084 log<level::ERR>("Error version is empty");
Gunnar Millsaae1b2b2017-10-06 13:42:39 -050085 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Version"),
86 Argument::ARGUMENT_VALUE(version.c_str()));
Gunnar Mills392f2942017-04-12 11:04:37 -050087 }
88
Saqib Khan26a960d2017-09-19 14:23:28 -050089 unsigned char digest[SHA512_DIGEST_LENGTH];
90 SHA512_CTX ctx;
91 SHA512_Init(&ctx);
92 SHA512_Update(&ctx, version.c_str(), strlen(version.c_str()));
93 SHA512_Final(digest, &ctx);
Adriana Kobylak2285fe02018-02-27 15:36:59 -060094 char mdString[SHA512_DIGEST_LENGTH * 2 + 1];
Saqib Khan26a960d2017-09-19 14:23:28 -050095 for (int i = 0; i < SHA512_DIGEST_LENGTH; i++)
96 {
Adriana Kobylak2285fe02018-02-27 15:36:59 -060097 snprintf(&mdString[i * 2], 3, "%02x", (unsigned int)digest[i]);
Saqib Khan26a960d2017-09-19 14:23:28 -050098 }
99
100 // Only need 8 hex digits.
101 std::string hexId = std::string(mdString);
102 return (hexId.substr(0, 8));
Gunnar Mills392f2942017-04-12 11:04:37 -0500103}
104
Vijay Khemkab7c062e2019-09-18 17:15:57 -0700105std::string Version::getBMCMachine(const std::string& releaseFilePath)
106{
107 std::string machineKey = "OPENBMC_TARGET_MACHINE=";
108 std::string machine{};
109 std::ifstream efile(releaseFilePath);
110 std::string line;
111
112 while (getline(efile, line))
113 {
114 if (line.substr(0, machineKey.size()).find(machineKey) !=
115 std::string::npos)
116 {
117 std::size_t pos = line.find_first_of('"') + 1;
118 machine = line.substr(pos, line.find_last_of('"') - pos);
119 break;
120 }
121 }
122
123 if (machine.empty())
124 {
125 log<level::ERR>("Unable to find OPENBMC_TARGET_MACHINE");
126 elog<InternalFailure>();
127 }
128
129 return machine;
130}
131
Chanh Nguyen1fd6ddd2021-01-06 11:09:09 +0700132std::string Version::getBMCExtendedVersion(const std::string& releaseFilePath)
133{
134 std::string extendedVersionKey = "EXTENDED_VERSION=";
135 std::string extendedVersionValue{};
136 std::string extendedVersion{};
137 std::ifstream efile(releaseFilePath);
138 std::string line;
139
140 while (getline(efile, line))
141 {
142 if (line.substr(0, extendedVersionKey.size())
143 .find(extendedVersionKey) != std::string::npos)
144 {
145 extendedVersionValue = line.substr(extendedVersionKey.size());
146 std::size_t pos = extendedVersionValue.find_first_of('"') + 1;
147 extendedVersion = extendedVersionValue.substr(
148 pos, extendedVersionValue.find_last_of('"') - pos);
149 break;
150 }
151 }
152
153 return extendedVersion;
154}
155
Saqib Khan1eef62d2017-08-10 15:29:34 -0500156std::string Version::getBMCVersion(const std::string& releaseFilePath)
Saqib Khanba239882017-05-26 08:41:54 -0500157{
158 std::string versionKey = "VERSION_ID=";
Adriana Kobylak2a3d9f52020-05-06 10:46:32 -0500159 std::string versionValue{};
Saqib Khanba239882017-05-26 08:41:54 -0500160 std::string version{};
161 std::ifstream efile;
162 std::string line;
Saqib Khan1eef62d2017-08-10 15:29:34 -0500163 efile.open(releaseFilePath);
Saqib Khanba239882017-05-26 08:41:54 -0500164
165 while (getline(efile, line))
166 {
167 if (line.substr(0, versionKey.size()).find(versionKey) !=
168 std::string::npos)
169 {
Adriana Kobylak2a3d9f52020-05-06 10:46:32 -0500170 // Support quoted and unquoted values
171 // 1. Remove the versionKey so that we process the value only.
172 versionValue = line.substr(versionKey.size());
173
174 // 2. Look for a starting quote, then increment the position by 1 to
175 // skip the quote character. If no quote is found,
176 // find_first_of() returns npos (-1), which by adding +1 sets pos
177 // to 0 (beginning of unquoted string).
178 std::size_t pos = versionValue.find_first_of('"') + 1;
179
180 // 3. Look for ending quote, then decrease the position by pos to
181 // get the size of the string up to before the ending quote. If
182 // no quote is found, find_last_of() returns npos (-1), and pos
183 // is 0 for the unquoted case, so substr() is called with a len
184 // parameter of npos (-1) which according to the documentation
185 // indicates to use all characters until the end of the string.
186 version =
187 versionValue.substr(pos, versionValue.find_last_of('"') - pos);
Saqib Khanba239882017-05-26 08:41:54 -0500188 break;
189 }
190 }
191 efile.close();
192
193 if (version.empty())
194 {
195 log<level::ERR>("Error BMC current version is empty");
Gunnar Millsaae1b2b2017-10-06 13:42:39 -0500196 elog<InternalFailure>();
Saqib Khanba239882017-05-26 08:41:54 -0500197 }
198
199 return version;
200}
201
Eddie James6d873712017-09-01 11:29:07 -0500202bool Version::isFunctional()
203{
204 return versionStr == getBMCVersion(OS_RELEASE_FILE);
205}
206
Saqib Khanee13e832017-10-23 12:53:11 -0500207void Delete::delete_()
208{
209 if (parent.eraseCallback)
210 {
211 parent.eraseCallback(parent.getId(parent.version()));
212 }
213}
214
Gunnar Mills392f2942017-04-12 11:04:37 -0500215} // namespace manager
216} // namespace software
Gunnar Millsfa34e022018-09-04 10:05:45 -0500217} // namespace phosphor