1 /**
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"
22 
23 #include <phosphor-logging/log.hpp>
24 #include <tuple>
25 
26 using json = nlohmann::json;
27 
28 using namespace phosphor::logging;
29 
30 // PsuInfo contains the device path, pmbus read type, and the version string
31 using PsuVersionInfo =
32     std::tuple<std::string, phosphor::pmbus::Type, std::string>;
33 
34 namespace utils
35 {
36 PsuVersionInfo getVersionInfo(const std::string& psuInventoryPath)
37 {
38     auto data = phosphor::power::util::loadJSONFromFile(PSU_JSON_PATH);
39 
40     if (data == nullptr)
41     {
42         return {};
43     }
44 
45     auto devices = data.find("psuDevices");
46     if (devices == data.end())
47     {
48         log<level::WARNING>("Unable to find psuDevices");
49         return {};
50     }
51     auto devicePath = devices->find(psuInventoryPath);
52     if (devicePath == devices->end())
53     {
54         log<level::WARNING>("Unable to find path for PSU",
55                             entry("PATH=%s", psuInventoryPath.c_str()));
56         return {};
57     }
58 
59     auto type = phosphor::power::util::getPMBusAccessType(data);
60 
61     std::string versionStr;
62     for (const auto& fru : data["fruConfigs"])
63     {
64         if (fru["propertyName"] == "Version")
65         {
66             versionStr = fru["fileName"];
67             break;
68         }
69     }
70     if (versionStr.empty())
71     {
72         log<level::WARNING>("Unable to find Version file");
73         return {};
74     }
75     return std::make_tuple(*devicePath, type, versionStr);
76 }
77 } // namespace utils
78 
79 namespace version
80 {
81 
82 std::string getVersion(const std::string& psuInventoryPath)
83 {
84     const auto& [devicePath, type, versionStr] =
85         utils::getVersionInfo(psuInventoryPath);
86     if (devicePath.empty() || versionStr.empty())
87     {
88         return {};
89     }
90     std::string version;
91     try
92     {
93         phosphor::pmbus::PMBus pmbus(devicePath);
94         version = pmbus.readString(versionStr, type);
95     }
96     catch (const std::exception& ex)
97     {
98         log<level::ERR>(ex.what());
99     }
100     return version;
101 }
102 
103 } // namespace version
104