xref: /openbmc/phosphor-power/utility.cpp (revision f8e8bc19fa720b6b348a3dddefd8eca7650b3e26)
1 /**
2  * Copyright © 2017 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 "utility.hpp"
17 
18 #include "types.hpp"
19 
20 #include <fstream>
21 
22 namespace phosphor
23 {
24 namespace power
25 {
26 namespace util
27 {
28 
29 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
30 constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
31 constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
32 
33 using json = nlohmann::json;
34 
getService(const std::string & path,const std::string & interface,sdbusplus::bus_t & bus,bool logError)35 std::string getService(const std::string& path, const std::string& interface,
36                        sdbusplus::bus_t& bus, bool logError)
37 {
38     auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
39                                       MAPPER_INTERFACE, "GetObject");
40 
41     method.append(path);
42     method.append(std::vector<std::string>({interface}));
43 
44     auto reply = bus.call(method);
45 
46     std::map<std::string, std::vector<std::string>> response;
47     reply.read(response);
48 
49     if (response.empty())
50     {
51         if (logError)
52         {
53             lg2::error("Error in mapper response for getting service name "
54                        "PATH={PATH} INTERFACE={INTERFACE}",
55                        "PATH", path, "INTERFACE", interface);
56         }
57         return std::string{};
58     }
59 
60     return response.begin()->first;
61 }
62 
getAllProperties(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,const std::string & service)63 DbusPropertyMap getAllProperties(sdbusplus::bus_t& bus, const std::string& path,
64                                  const std::string& interface,
65                                  const std::string& service)
66 {
67     DbusPropertyMap properties;
68 
69     auto serviceStr = service;
70     if (serviceStr.empty())
71     {
72         serviceStr = getService(path, interface, bus);
73         if (serviceStr.empty())
74         {
75             return properties;
76         }
77     }
78 
79     auto method = bus.new_method_call(serviceStr.c_str(), path.c_str(),
80                                       PROPERTY_INTF, "GetAll");
81     method.append(interface);
82     auto reply = bus.call(method);
83     reply.read(properties);
84     return properties;
85 }
86 
getSubTree(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,int32_t depth)87 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
88                        const std::string& interface, int32_t depth)
89 {
90     return getSubTree(bus, path, std::vector<std::string>({interface}), depth);
91 }
92 
getSubTree(sdbusplus::bus_t & bus,const std::string & path,const std::vector<std::string> & interfaces,int32_t depth)93 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
94                        const std::vector<std::string>& interfaces,
95                        int32_t depth)
96 {
97     auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
98                                           MAPPER_INTERFACE, "GetSubTree");
99     mapperCall.append(path);
100     mapperCall.append(depth);
101     mapperCall.append(interfaces);
102 
103     auto reply = bus.call(mapperCall);
104 
105     DbusSubtree response;
106     reply.read(response);
107     return response;
108 }
109 
getAssociatedSubTreePaths(sdbusplus::bus_t & bus,const sdbusplus::message::object_path & associationPath,const sdbusplus::message::object_path & path,const std::vector<std::string> & interfaces,int32_t depth)110 std::vector<DbusPath> getAssociatedSubTreePaths(
111     sdbusplus::bus_t& bus,
112     const sdbusplus::message::object_path& associationPath,
113     const sdbusplus::message::object_path& path,
114     const std::vector<std::string>& interfaces, int32_t depth)
115 {
116     auto mapperCall =
117         bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
118                             "GetAssociatedSubTreePaths");
119     mapperCall.append(associationPath);
120     mapperCall.append(path);
121     mapperCall.append(depth);
122     mapperCall.append(interfaces);
123 
124     auto reply = bus.call(mapperCall);
125 
126     std::vector<DbusPath> response;
127     reply.read(response);
128     return response;
129 }
130 
loadJSONFromFile(const char * path)131 json loadJSONFromFile(const char* path)
132 {
133     std::ifstream ifs(path);
134     if (!ifs.good())
135     {
136         lg2::error("Unable to open file PATH={PATH}", "PATH", path);
137         return nullptr;
138     }
139     auto data = json::parse(ifs, nullptr, false);
140     if (data.is_discarded())
141     {
142         lg2::error("Failed to parse json PATH={PATH}", "PATH", path);
143         return nullptr;
144     }
145     return data;
146 }
147 
getPMBusAccessType(const json & json)148 phosphor::pmbus::Type getPMBusAccessType(const json& json)
149 {
150     using namespace phosphor::pmbus;
151     Type type;
152 
153     auto typeStr = json.at("inventoryPMBusAccessType");
154 
155     if (typeStr == "Hwmon")
156     {
157         type = Type::Hwmon;
158     }
159     else if (typeStr == "DeviceDebug")
160     {
161         type = Type::DeviceDebug;
162     }
163     else if (typeStr == "Debug")
164     {
165         type = Type::Debug;
166     }
167     else if (typeStr == "HwmonDeviceDebug")
168     {
169         type = Type::HwmonDeviceDebug;
170     }
171     else
172     {
173         type = Type::Base;
174     }
175     return type;
176 }
177 
isPoweredOn(sdbusplus::bus_t & bus,bool defaultState)178 bool isPoweredOn(sdbusplus::bus_t& bus, bool defaultState)
179 {
180     int32_t state = defaultState;
181 
182     try
183     {
184         // When state = 1, system is powered on
185         auto service = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
186         getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH, service, bus,
187                              state);
188     }
189     catch (const std::exception& e)
190     {
191         lg2::info("Failed to get power state.");
192     }
193     return state != 0;
194 }
195 
getPSUInventoryPaths(sdbusplus::bus_t & bus)196 std::vector<std::string> getPSUInventoryPaths(sdbusplus::bus_t& bus)
197 {
198     std::vector<std::string> paths;
199     auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
200                                       MAPPER_INTERFACE, "GetSubTreePaths");
201     method.append(INVENTORY_OBJ_PATH);
202     method.append(0); // Depth 0 to search all
203     method.append(std::vector<std::string>({PSU_INVENTORY_IFACE}));
204     auto reply = bus.call(method);
205 
206     reply.read(paths);
207     return paths;
208 }
209 
210 } // namespace util
211 } // namespace power
212 } // namespace phosphor
213