15e0dcb39SLei YU #include "config.h"
25e0dcb39SLei YU 
35e0dcb39SLei YU #include "utils.hpp"
45e0dcb39SLei YU 
5ad90ad51SLei YU #include <openssl/sha.h>
6ad90ad51SLei YU 
75e0dcb39SLei YU #include <fstream>
8*f77189f7SLei YU #include <phosphor-logging/log.hpp>
9*f77189f7SLei YU 
10*f77189f7SLei YU using namespace phosphor::logging;
115e0dcb39SLei YU 
125e0dcb39SLei YU namespace utils
135e0dcb39SLei YU {
145e0dcb39SLei YU 
155e0dcb39SLei YU namespace // anonymous
165e0dcb39SLei YU {
175e0dcb39SLei YU constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
185e0dcb39SLei YU constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
195e0dcb39SLei YU constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
205e0dcb39SLei YU } // namespace
215e0dcb39SLei YU 
22*f77189f7SLei YU const UtilsInterface& getUtils()
23*f77189f7SLei YU {
24*f77189f7SLei YU     static Utils utils;
25*f77189f7SLei YU     return utils;
26*f77189f7SLei YU }
27*f77189f7SLei YU 
28*f77189f7SLei YU std::vector<std::string>
29*f77189f7SLei YU     Utils::getPSUInventoryPath(sdbusplus::bus::bus& bus) const
305e0dcb39SLei YU {
315e0dcb39SLei YU     std::vector<std::string> paths;
325e0dcb39SLei YU     auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
335e0dcb39SLei YU                                       MAPPER_INTERFACE, "GetSubTreePaths");
345e0dcb39SLei YU     method.append(PSU_INVENTORY_PATH_BASE);
355e0dcb39SLei YU     method.append(0); // Depth 0 to search all
365e0dcb39SLei YU     method.append(std::vector<std::string>({PSU_INVENTORY_IFACE}));
375e0dcb39SLei YU     auto reply = bus.call(method);
385e0dcb39SLei YU 
395e0dcb39SLei YU     reply.read(paths);
405e0dcb39SLei YU     return paths;
415e0dcb39SLei YU }
425e0dcb39SLei YU 
43*f77189f7SLei YU std::string Utils::getService(sdbusplus::bus::bus& bus, const char* path,
44*f77189f7SLei YU                               const char* interface) const
45ad90ad51SLei YU {
46ad90ad51SLei YU     auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
47ad90ad51SLei YU                                       MAPPER_INTERFACE, "GetObject");
48ad90ad51SLei YU 
49ad90ad51SLei YU     mapper.append(path, std::vector<std::string>({interface}));
50ad90ad51SLei YU     try
51ad90ad51SLei YU     {
52ad90ad51SLei YU         auto mapperResponseMsg = bus.call(mapper);
53ad90ad51SLei YU 
54ad90ad51SLei YU         std::vector<std::pair<std::string, std::vector<std::string>>>
55ad90ad51SLei YU             mapperResponse;
56ad90ad51SLei YU         mapperResponseMsg.read(mapperResponse);
57ad90ad51SLei YU         if (mapperResponse.empty())
58ad90ad51SLei YU         {
59ad90ad51SLei YU             log<level::ERR>("Error reading mapper response");
60ad90ad51SLei YU             throw std::runtime_error("Error reading mapper response");
61ad90ad51SLei YU         }
62ad90ad51SLei YU         if (mapperResponse.size() < 1)
63ad90ad51SLei YU         {
64ad90ad51SLei YU             return "";
65ad90ad51SLei YU         }
66ad90ad51SLei YU         return mapperResponse[0].first;
67ad90ad51SLei YU     }
68ad90ad51SLei YU     catch (const sdbusplus::exception::SdBusError& ex)
69ad90ad51SLei YU     {
70ad90ad51SLei YU         log<level::ERR>("Mapper call failed", entry("METHOD=%d", "GetObject"),
71ad90ad51SLei YU                         entry("PATH=%s", path),
72ad90ad51SLei YU                         entry("INTERFACE=%s", interface));
73ad90ad51SLei YU         throw std::runtime_error("Mapper call failed");
74ad90ad51SLei YU     }
75ad90ad51SLei YU }
76ad90ad51SLei YU 
77*f77189f7SLei YU std::string Utils::getVersionId(const std::string& version) const
78ad90ad51SLei YU {
79ad90ad51SLei YU     if (version.empty())
80ad90ad51SLei YU     {
81ad90ad51SLei YU         log<level::ERR>("Error version is empty");
82ad90ad51SLei YU         return {};
83ad90ad51SLei YU     }
84ad90ad51SLei YU 
85ad90ad51SLei YU     unsigned char digest[SHA512_DIGEST_LENGTH];
86ad90ad51SLei YU     SHA512_CTX ctx;
87ad90ad51SLei YU     SHA512_Init(&ctx);
88ad90ad51SLei YU     SHA512_Update(&ctx, version.c_str(), strlen(version.c_str()));
89ad90ad51SLei YU     SHA512_Final(digest, &ctx);
90ad90ad51SLei YU     char mdString[SHA512_DIGEST_LENGTH * 2 + 1];
91ad90ad51SLei YU     for (int i = 0; i < SHA512_DIGEST_LENGTH; i++)
92ad90ad51SLei YU     {
93ad90ad51SLei YU         snprintf(&mdString[i * 2], 3, "%02x", (unsigned int)digest[i]);
94ad90ad51SLei YU     }
95ad90ad51SLei YU 
96ad90ad51SLei YU     // Only need 8 hex digits.
97ad90ad51SLei YU     std::string hexId = std::string(mdString);
98ad90ad51SLei YU     return (hexId.substr(0, 8));
99ad90ad51SLei YU }
100ad90ad51SLei YU 
101*f77189f7SLei YU any Utils::getPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
102*f77189f7SLei YU                            const char* path, const char* interface,
103*f77189f7SLei YU                            const char* propertyName) const
104*f77189f7SLei YU {
105*f77189f7SLei YU     auto method = bus.new_method_call(service, path,
106*f77189f7SLei YU                                       "org.freedesktop.DBus.Properties", "Get");
107*f77189f7SLei YU     method.append(interface, propertyName);
108*f77189f7SLei YU     try
109*f77189f7SLei YU     {
110*f77189f7SLei YU         PropertyType value{};
111*f77189f7SLei YU         auto reply = bus.call(method);
112*f77189f7SLei YU         reply.read(value);
113*f77189f7SLei YU         return any(value);
114*f77189f7SLei YU     }
115*f77189f7SLei YU     catch (const sdbusplus::exception::SdBusError& ex)
116*f77189f7SLei YU     {
117*f77189f7SLei YU         log<level::ERR>("GetProperty call failed", entry("PATH=%s", path),
118*f77189f7SLei YU                         entry("INTERFACE=%s", interface),
119*f77189f7SLei YU                         entry("PROPERTY=%s", propertyName));
120*f77189f7SLei YU         throw std::runtime_error("GetProperty call failed");
121*f77189f7SLei YU     }
122*f77189f7SLei YU }
123*f77189f7SLei YU 
1245e0dcb39SLei YU } // namespace utils
125