blob: 26507ee14600e25836f28668ab417cbb51f85db6 [file] [log] [blame]
Lei YU0bf1b782019-08-29 16:02:30 +08001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "config.h"
17
18#include "version.hpp"
19
20#include "pmbus.hpp"
21#include "utility.hpp"
Shawn McCarney14572cf2024-11-06 12:17:57 -060022#include "utils.hpp"
Lei YU0bf1b782019-08-29 16:02:30 +080023
Shawn McCarney14572cf2024-11-06 12:17:57 -060024#include <nlohmann/json.hpp>
Lei YU0bf1b782019-08-29 16:02:30 +080025#include <phosphor-logging/log.hpp>
Brandon Wymand1bc4ce2019-12-13 14:20:34 -060026
Faisal Awada5dce1a72024-08-19 15:51:44 -050027#include <exception>
Lei YU0bf1b782019-08-29 16:02:30 +080028#include <tuple>
29
30using json = nlohmann::json;
31
Shawn McCarney14572cf2024-11-06 12:17:57 -060032using namespace utils;
Lei YU0bf1b782019-08-29 16:02:30 +080033using namespace phosphor::logging;
Faisal Awada5dce1a72024-08-19 15:51:44 -050034using namespace phosphor::power::util;
Lei YU0bf1b782019-08-29 16:02:30 +080035
Faisal Awada5dce1a72024-08-19 15:51:44 -050036namespace version
37{
Shawn McCarney14572cf2024-11-06 12:17:57 -060038
39namespace internal
Lei YU0bf1b782019-08-29 16:02:30 +080040{
Faisal Awada5dce1a72024-08-19 15:51:44 -050041
Lei YU0bf1b782019-08-29 16:02:30 +080042PsuVersionInfo getVersionInfo(const std::string& psuInventoryPath)
43{
Shawn McCarney14572cf2024-11-06 12:17:57 -060044 auto data = loadJSONFromFile(PSU_JSON_PATH);
Lei YU0bf1b782019-08-29 16:02:30 +080045
46 if (data == nullptr)
47 {
48 return {};
49 }
50
51 auto devices = data.find("psuDevices");
52 if (devices == data.end())
53 {
54 log<level::WARNING>("Unable to find psuDevices");
55 return {};
56 }
57 auto devicePath = devices->find(psuInventoryPath);
58 if (devicePath == devices->end())
59 {
60 log<level::WARNING>("Unable to find path for PSU",
61 entry("PATH=%s", psuInventoryPath.c_str()));
62 return {};
63 }
64
Shawn McCarney14572cf2024-11-06 12:17:57 -060065 auto type = getPMBusAccessType(data);
Lei YU0bf1b782019-08-29 16:02:30 +080066
67 std::string versionStr;
68 for (const auto& fru : data["fruConfigs"])
69 {
70 if (fru["propertyName"] == "Version")
71 {
Matt Spinlerc0b9e9e2023-07-17 14:09:58 -050072 versionStr = fru["fileName"].get<std::string>();
Lei YU0bf1b782019-08-29 16:02:30 +080073 break;
74 }
75 }
76 if (versionStr.empty())
77 {
78 log<level::WARNING>("Unable to find Version file");
79 return {};
80 }
81 return std::make_tuple(*devicePath, type, versionStr);
82}
Lei YU093b5912019-10-22 15:28:51 +080083
84// A default implemention compare the string itself
85std::string getLatestDefault(const std::vector<std::string>& versions)
86{
87 std::string latest;
88 for (const auto& version : versions)
89 {
90 if (latest < version)
91 {
92 latest = version;
93 }
94 }
95 return latest;
96}
97
Shawn McCarney14572cf2024-11-06 12:17:57 -060098} // namespace internal
Lei YU0bf1b782019-08-29 16:02:30 +080099
100std::string getVersion(const std::string& psuInventoryPath)
101{
Patrick Williamsf5402192024-08-16 15:20:53 -0400102 const auto& [devicePath, type, versionStr] =
Shawn McCarney14572cf2024-11-06 12:17:57 -0600103 internal::getVersionInfo(psuInventoryPath);
Lei YU0bf1b782019-08-29 16:02:30 +0800104 if (devicePath.empty() || versionStr.empty())
105 {
Faisal Awada5dce1a72024-08-19 15:51:44 -0500106 return "";
Lei YU0bf1b782019-08-29 16:02:30 +0800107 }
108 std::string version;
109 try
110 {
111 phosphor::pmbus::PMBus pmbus(devicePath);
112 version = pmbus.readString(versionStr, type);
113 }
114 catch (const std::exception& ex)
115 {
116 log<level::ERR>(ex.what());
117 }
118 return version;
119}
120
Faisal Awada5dce1a72024-08-19 15:51:44 -0500121std::string getVersion(sdbusplus::bus_t& bus,
122 const std::string& psuInventoryPath)
123{
Shawn McCarney37c26122024-10-24 13:58:31 -0500124 std::string version;
Faisal Awada5dce1a72024-08-19 15:51:44 -0500125 try
126 {
Shawn McCarney14572cf2024-11-06 12:17:57 -0600127 const auto& [i2cbus, i2caddr] = getPsuI2c(bus, psuInventoryPath);
128 auto pmbus = getPmbusIntf(i2cbus, i2caddr);
Shawn McCarney37c26122024-10-24 13:58:31 -0500129 std::string name = "fw_version";
130 auto type = phosphor::pmbus::Type::HwmonDeviceDebug;
131 version = pmbus->readString(name, type);
Faisal Awada5dce1a72024-08-19 15:51:44 -0500132 }
133 catch (const std::exception& e)
134 {
135 log<level::ERR>(std::format("Error: {}", e.what()).c_str());
Faisal Awada5dce1a72024-08-19 15:51:44 -0500136 }
Shawn McCarney37c26122024-10-24 13:58:31 -0500137 return version;
Faisal Awada5dce1a72024-08-19 15:51:44 -0500138}
139
Lei YU093b5912019-10-22 15:28:51 +0800140std::string getLatest(const std::vector<std::string>& versions)
141{
142 // TODO: when multiple PSU/Machines are supported, add configuration options
143 // to implement machine-specific logic.
144 // For now IBM AC Servers and Inspur FP5280G2 are supported.
145 //
146 // IBM AC servers' PSU version has two types:
147 // * XXXXYYYYZZZZ: XXXX is the primary version
148 // YYYY is the secondary version
149 // ZZZZ is the communication version
150 //
151 // * XXXXYYYY: XXXX is the primary version
152 // YYYY is the seconday version
153 //
154 // Inspur FP5280G2 PSU version is human readable text and a larger string
155 // means a newer version.
156 //
157 // So just compare by strings is OK for these cases
Shawn McCarney14572cf2024-11-06 12:17:57 -0600158 return internal::getLatestDefault(versions);
Lei YU093b5912019-10-22 15:28:51 +0800159}
Lei YU0bf1b782019-08-29 16:02:30 +0800160} // namespace version