1 #include "platform_config.hpp"
2 
3 namespace pldm
4 {
5 namespace responder
6 {
7 
8 namespace platform_config
9 {
10 /** @brief callback function invoked when interfaces get added from
11  *      Entity manager
12  *
13  *  @param[in] msg - Data associated with subscribed signal
14  */
15 void Handler::systemCompatibleCallback(sdbusplus::message_t& msg)
16 {
17     sdbusplus::message::object_path path;
18 
19     pldm::utils::InterfaceMap interfaceMap;
20 
21     msg.read(path, interfaceMap);
22 
23     if (!interfaceMap.contains(compatibleInterface))
24     {
25         return;
26     }
27     // Get the "Name" property value of the
28     // "xyz.openbmc_project.Inventory.Decorator.Compatible" interface
29     const auto& properties = interfaceMap.at(compatibleInterface);
30 
31     if (!properties.contains(namesProperty))
32     {
33         return;
34     }
35     auto names =
36         std::get<pldm::utils::Interfaces>(properties.at(namesProperty));
37 
38     std::string systemType;
39     if (!names.empty())
40     {
41         // get only the first system type
42         systemType = names.front();
43         if (sysTypeCallback)
44         {
45             sysTypeCallback(systemType, true);
46         }
47     }
48 
49     if (!systemType.empty())
50     {
51         systemCompatibleMatchCallBack.reset();
52     }
53 }
54 
55 /** @brief Method to get the system type information
56  *
57  *  @return - the system type information
58  */
59 std::optional<std::filesystem::path> Handler::getPlatformName()
60 {
61     if (!systemType.empty())
62     {
63         return fs::path{systemType};
64     }
65 
66     namespace fs = std::filesystem;
67     static const std::string entityMangerService =
68         "xyz.openbmc_project.EntityManager";
69 
70     static constexpr auto searchpath = "/xyz/openbmc_project/";
71     int depth = 0;
72     std::vector<std::string> systemCompatible = {compatibleInterface};
73 
74     try
75     {
76         pldm::utils::GetSubTreeResponse response =
77             pldm::utils::DBusHandler().getSubtree(searchpath, depth,
78                                                   systemCompatible);
79         auto& bus = pldm::utils::DBusHandler::getBus();
80 
81         for (const auto& [objectPath, serviceMap] : response)
82         {
83             try
84             {
85                 auto record = std::find_if(
86                     serviceMap.begin(), serviceMap.end(),
87                     [](auto map) { return map.first == entityMangerService; });
88 
89                 if (record != serviceMap.end())
90                 {
91                     auto method = bus.new_method_call(
92                         entityMangerService.c_str(), objectPath.c_str(),
93                         "org.freedesktop.DBus.Properties", "Get");
94                     method.append(compatibleInterface, namesProperty);
95                     auto propSystemList =
96                         bus.call(method, dbusTimeout).unpack<PropertyValue>();
97                     auto systemList =
98                         std::get<std::vector<std::string>>(propSystemList);
99 
100                     if (!systemList.empty())
101                     {
102                         systemType = systemList.at(0);
103                         // once systemtype received,then resetting a callback
104                         systemCompatibleMatchCallBack.reset();
105                         return fs::path{systemType};
106                     }
107                 }
108             }
109             catch (const std::exception& e)
110             {
111                 error(
112                     "Error getting Names property at '{PATH}' on '{INTERFACE}': {ERROR}",
113                     "PATH", objectPath, "INTERFACE", compatibleInterface,
114                     "ERROR", e);
115             }
116         }
117     }
118     catch (const std::exception& e)
119     {
120         error("Failed to make a d-bus call to get platform name {ERROR}",
121               "ERROR", e);
122     }
123     return std::nullopt;
124 }
125 
126 void Handler::registerSystemTypeCallback(SystemTypeCallback callback)
127 {
128     sysTypeCallback = callback;
129 }
130 
131 } // namespace platform_config
132 
133 } // namespace responder
134 
135 } // namespace pldm
136