xref: /openbmc/phosphor-power/utility.cpp (revision f661ecb9383c25986a8769f9b5b65d13993437b0)
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 constexpr auto DECORATOR_CHASSIS_ID =
34     "xyz.openbmc_project.Inventory.Decorator.Slot";
35 constexpr auto CHASSIS_ID_PROPERTY = "SlotNumber";
36 
37 using json = nlohmann::json;
38 
getService(const std::string & path,const std::string & interface,sdbusplus::bus_t & bus,bool logError)39 std::string getService(const std::string& path, const std::string& interface,
40                        sdbusplus::bus_t& bus, bool logError)
41 {
42     auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
43                                       MAPPER_INTERFACE, "GetObject");
44 
45     method.append(path);
46     method.append(std::vector<std::string>({interface}));
47 
48     auto reply = bus.call(method);
49 
50     std::map<std::string, std::vector<std::string>> response;
51     reply.read(response);
52 
53     if (response.empty())
54     {
55         if (logError)
56         {
57             lg2::error("Error in mapper response for getting service name "
58                        "PATH={PATH} INTERFACE={INTERFACE}",
59                        "PATH", path, "INTERFACE", interface);
60         }
61         return std::string{};
62     }
63 
64     return response.begin()->first;
65 }
66 
getAllProperties(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,const std::string & service)67 DbusPropertyMap getAllProperties(sdbusplus::bus_t& bus, const std::string& path,
68                                  const std::string& interface,
69                                  const std::string& service)
70 {
71     DbusPropertyMap properties;
72 
73     auto serviceStr = service;
74     if (serviceStr.empty())
75     {
76         serviceStr = getService(path, interface, bus);
77         if (serviceStr.empty())
78         {
79             return properties;
80         }
81     }
82 
83     auto method = bus.new_method_call(serviceStr.c_str(), path.c_str(),
84                                       PROPERTY_INTF, "GetAll");
85     method.append(interface);
86     auto reply = bus.call(method);
87     reply.read(properties);
88     return properties;
89 }
90 
getSubTree(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,int32_t depth)91 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
92                        const std::string& interface, int32_t depth)
93 {
94     return getSubTree(bus, path, std::vector<std::string>({interface}), depth);
95 }
96 
getSubTree(sdbusplus::bus_t & bus,const std::string & path,const std::vector<std::string> & interfaces,int32_t depth)97 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
98                        const std::vector<std::string>& interfaces,
99                        int32_t depth)
100 {
101     auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
102                                           MAPPER_INTERFACE, "GetSubTree");
103     mapperCall.append(path);
104     mapperCall.append(depth);
105     mapperCall.append(interfaces);
106 
107     auto reply = bus.call(mapperCall);
108 
109     DbusSubtree response;
110     reply.read(response);
111     return response;
112 }
113 
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)114 std::vector<DbusPath> getAssociatedSubTreePaths(
115     sdbusplus::bus_t& bus,
116     const sdbusplus::message::object_path& associationPath,
117     const sdbusplus::message::object_path& path,
118     const std::vector<std::string>& interfaces, int32_t depth)
119 {
120     auto mapperCall =
121         bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
122                             "GetAssociatedSubTreePaths");
123     mapperCall.append(associationPath);
124     mapperCall.append(path);
125     mapperCall.append(depth);
126     mapperCall.append(interfaces);
127 
128     auto reply = bus.call(mapperCall);
129 
130     std::vector<DbusPath> response;
131     reply.read(response);
132     return response;
133 }
134 
loadJSONFromFile(const char * path)135 json loadJSONFromFile(const char* path)
136 {
137     std::ifstream ifs(path);
138     if (!ifs.good())
139     {
140         lg2::error("Unable to open file PATH={PATH}", "PATH", path);
141         return nullptr;
142     }
143     auto data = json::parse(ifs, nullptr, false);
144     if (data.is_discarded())
145     {
146         lg2::error("Failed to parse json PATH={PATH}", "PATH", path);
147         return nullptr;
148     }
149     return data;
150 }
151 
getPMBusAccessType(const json & json)152 phosphor::pmbus::Type getPMBusAccessType(const json& json)
153 {
154     using namespace phosphor::pmbus;
155     Type type;
156 
157     auto typeStr = json.at("inventoryPMBusAccessType");
158 
159     if (typeStr == "Hwmon")
160     {
161         type = Type::Hwmon;
162     }
163     else if (typeStr == "DeviceDebug")
164     {
165         type = Type::DeviceDebug;
166     }
167     else if (typeStr == "Debug")
168     {
169         type = Type::Debug;
170     }
171     else if (typeStr == "HwmonDeviceDebug")
172     {
173         type = Type::HwmonDeviceDebug;
174     }
175     else
176     {
177         type = Type::Base;
178     }
179     return type;
180 }
181 
isPoweredOn(sdbusplus::bus_t & bus,bool defaultState)182 bool isPoweredOn(sdbusplus::bus_t& bus, bool defaultState)
183 {
184     int32_t state = defaultState;
185 
186     try
187     {
188         // When state = 1, system is powered on
189         auto service = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
190         getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH, service, bus,
191                              state);
192     }
193     catch (const std::exception& e)
194     {
195         lg2::info("Failed to get power state.");
196     }
197     return state != 0;
198 }
199 
getPSUInventoryPaths(sdbusplus::bus_t & bus)200 std::vector<std::string> getPSUInventoryPaths(sdbusplus::bus_t& bus)
201 {
202     std::vector<std::string> paths;
203     auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
204                                       MAPPER_INTERFACE, "GetSubTreePaths");
205     method.append(INVENTORY_OBJ_PATH);
206     method.append(0); // Depth 0 to search all
207     method.append(std::vector<std::string>({PSU_INVENTORY_IFACE}));
208     auto reply = bus.call(method);
209 
210     reply.read(paths);
211     return paths;
212 }
213 
getChassisInventoryPaths(sdbusplus::bus_t & bus)214 std::vector<std::string> getChassisInventoryPaths(sdbusplus::bus_t& bus)
215 {
216     std::vector<std::string> paths;
217     auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
218                                       MAPPER_INTERFACE, "GetSubTreePaths");
219     method.append(INVENTORY_OBJ_PATH);
220     method.append(0); // Depth 0 to search all
221     method.append(std::vector<std::string>({CHASSIS_IFACE}));
222     auto reply = bus.call(method);
223 
224     reply.read(paths);
225     return paths;
226 }
227 
getChassisInventoryUniqueId(sdbusplus::bus_t & bus,const std::string & path)228 uint64_t getChassisInventoryUniqueId(sdbusplus::bus_t& bus,
229                                      const std::string& path)
230 {
231     uint32_t chassisId;
232     getProperty(DECORATOR_CHASSIS_ID, CHASSIS_ID_PROPERTY, path,
233                 INVENTORY_MGR_IFACE, bus, chassisId);
234     return static_cast<uint64_t>(chassisId);
235 }
236 
getParentEMUniqueId(sdbusplus::bus_t & bus,const std::string & path)237 uint64_t getParentEMUniqueId(sdbusplus::bus_t& bus, const std::string& path)
238 {
239     namespace fs = std::filesystem;
240     uint64_t chassisId;
241     fs::path fspath(path);
242     getProperty(DECORATOR_CHASSIS_ID, CHASSIS_ID_PROPERTY, fspath.parent_path(),
243                 ENTITY_MGR_SERVICE, bus, chassisId);
244     return chassisId;
245 }
246 
247 } // namespace util
248 } // namespace power
249 } // namespace phosphor
250