xref: /openbmc/phosphor-power/tools/power-utils/version.cpp (revision d1bc4cec3bd77312b9ed3798739f949b4570deaf)
10bf1b782SLei YU /**
20bf1b782SLei YU  * Copyright © 2019 IBM Corporation
30bf1b782SLei YU  *
40bf1b782SLei YU  * Licensed under the Apache License, Version 2.0 (the "License");
50bf1b782SLei YU  * you may not use this file except in compliance with the License.
60bf1b782SLei YU  * You may obtain a copy of the License at
70bf1b782SLei YU  *
80bf1b782SLei YU  *     http://www.apache.org/licenses/LICENSE-2.0
90bf1b782SLei YU  *
100bf1b782SLei YU  * Unless required by applicable law or agreed to in writing, software
110bf1b782SLei YU  * distributed under the License is distributed on an "AS IS" BASIS,
120bf1b782SLei YU  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130bf1b782SLei YU  * See the License for the specific language governing permissions and
140bf1b782SLei YU  * limitations under the License.
150bf1b782SLei YU  */
160bf1b782SLei YU #include "config.h"
170bf1b782SLei YU 
180bf1b782SLei YU #include "version.hpp"
190bf1b782SLei YU 
200bf1b782SLei YU #include "pmbus.hpp"
210bf1b782SLei YU #include "utility.hpp"
220bf1b782SLei YU 
230bf1b782SLei YU #include <phosphor-logging/log.hpp>
24*d1bc4cecSBrandon Wyman 
250bf1b782SLei YU #include <tuple>
260bf1b782SLei YU 
270bf1b782SLei YU using json = nlohmann::json;
280bf1b782SLei YU 
290bf1b782SLei YU using namespace phosphor::logging;
300bf1b782SLei YU 
310bf1b782SLei YU // PsuInfo contains the device path, pmbus read type, and the version string
320bf1b782SLei YU using PsuVersionInfo =
330bf1b782SLei YU     std::tuple<std::string, phosphor::pmbus::Type, std::string>;
340bf1b782SLei YU 
350bf1b782SLei YU namespace utils
360bf1b782SLei YU {
370bf1b782SLei YU PsuVersionInfo getVersionInfo(const std::string& psuInventoryPath)
380bf1b782SLei YU {
390bf1b782SLei YU     auto data = phosphor::power::util::loadJSONFromFile(PSU_JSON_PATH);
400bf1b782SLei YU 
410bf1b782SLei YU     if (data == nullptr)
420bf1b782SLei YU     {
430bf1b782SLei YU         return {};
440bf1b782SLei YU     }
450bf1b782SLei YU 
460bf1b782SLei YU     auto devices = data.find("psuDevices");
470bf1b782SLei YU     if (devices == data.end())
480bf1b782SLei YU     {
490bf1b782SLei YU         log<level::WARNING>("Unable to find psuDevices");
500bf1b782SLei YU         return {};
510bf1b782SLei YU     }
520bf1b782SLei YU     auto devicePath = devices->find(psuInventoryPath);
530bf1b782SLei YU     if (devicePath == devices->end())
540bf1b782SLei YU     {
550bf1b782SLei YU         log<level::WARNING>("Unable to find path for PSU",
560bf1b782SLei YU                             entry("PATH=%s", psuInventoryPath.c_str()));
570bf1b782SLei YU         return {};
580bf1b782SLei YU     }
590bf1b782SLei YU 
600bf1b782SLei YU     auto type = phosphor::power::util::getPMBusAccessType(data);
610bf1b782SLei YU 
620bf1b782SLei YU     std::string versionStr;
630bf1b782SLei YU     for (const auto& fru : data["fruConfigs"])
640bf1b782SLei YU     {
650bf1b782SLei YU         if (fru["propertyName"] == "Version")
660bf1b782SLei YU         {
670bf1b782SLei YU             versionStr = fru["fileName"];
680bf1b782SLei YU             break;
690bf1b782SLei YU         }
700bf1b782SLei YU     }
710bf1b782SLei YU     if (versionStr.empty())
720bf1b782SLei YU     {
730bf1b782SLei YU         log<level::WARNING>("Unable to find Version file");
740bf1b782SLei YU         return {};
750bf1b782SLei YU     }
760bf1b782SLei YU     return std::make_tuple(*devicePath, type, versionStr);
770bf1b782SLei YU }
78093b5917SLei YU 
79093b5917SLei YU // A default implemention compare the string itself
80093b5917SLei YU std::string getLatestDefault(const std::vector<std::string>& versions)
81093b5917SLei YU {
82093b5917SLei YU     std::string latest;
83093b5917SLei YU     for (const auto& version : versions)
84093b5917SLei YU     {
85093b5917SLei YU         if (latest < version)
86093b5917SLei YU         {
87093b5917SLei YU             latest = version;
88093b5917SLei YU         }
89093b5917SLei YU     }
90093b5917SLei YU     return latest;
91093b5917SLei YU }
92093b5917SLei YU 
930bf1b782SLei YU } // namespace utils
940bf1b782SLei YU 
950bf1b782SLei YU namespace version
960bf1b782SLei YU {
970bf1b782SLei YU 
980bf1b782SLei YU std::string getVersion(const std::string& psuInventoryPath)
990bf1b782SLei YU {
1000bf1b782SLei YU     const auto& [devicePath, type, versionStr] =
1010bf1b782SLei YU         utils::getVersionInfo(psuInventoryPath);
1020bf1b782SLei YU     if (devicePath.empty() || versionStr.empty())
1030bf1b782SLei YU     {
1040bf1b782SLei YU         return {};
1050bf1b782SLei YU     }
1060bf1b782SLei YU     std::string version;
1070bf1b782SLei YU     try
1080bf1b782SLei YU     {
1090bf1b782SLei YU         phosphor::pmbus::PMBus pmbus(devicePath);
1100bf1b782SLei YU         version = pmbus.readString(versionStr, type);
1110bf1b782SLei YU     }
1120bf1b782SLei YU     catch (const std::exception& ex)
1130bf1b782SLei YU     {
1140bf1b782SLei YU         log<level::ERR>(ex.what());
1150bf1b782SLei YU     }
1160bf1b782SLei YU     return version;
1170bf1b782SLei YU }
1180bf1b782SLei YU 
119093b5917SLei YU std::string getLatest(const std::vector<std::string>& versions)
120093b5917SLei YU {
121093b5917SLei YU     // TODO: when multiple PSU/Machines are supported, add configuration options
122093b5917SLei YU     // to implement machine-specific logic.
123093b5917SLei YU     // For now IBM AC Servers and Inspur FP5280G2 are supported.
124093b5917SLei YU     //
125093b5917SLei YU     // IBM AC servers' PSU version has two types:
126093b5917SLei YU     // * XXXXYYYYZZZZ: XXXX is the primary version
127093b5917SLei YU     //                 YYYY is the secondary version
128093b5917SLei YU     //                 ZZZZ is the communication version
129093b5917SLei YU     //
130093b5917SLei YU     // * XXXXYYYY:     XXXX is the primary version
131093b5917SLei YU     //                 YYYY is the seconday version
132093b5917SLei YU     //
133093b5917SLei YU     // Inspur FP5280G2 PSU version is human readable text and a larger string
134093b5917SLei YU     // means a newer version.
135093b5917SLei YU     //
136093b5917SLei YU     // So just compare by strings is OK for these cases
137093b5917SLei YU     return utils::getLatestDefault(versions);
138093b5917SLei YU }
139093b5917SLei YU 
1400bf1b782SLei YU } // namespace version
141