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     }
44 
45     if (!systemType.empty())
46     {
47         systemCompatibleMatchCallBack.reset();
48     }
49 }
50 
51 /** @brief Method to get the system type information
52  *
53  *  @return - the system type information
54  */
55 std::optional<std::filesystem::path> Handler::getPlatformName()
56 {
57     if (!systemType.empty())
58     {
59         return fs::path{systemType};
60     }
61 
62     namespace fs = std::filesystem;
63     static const std::string entityMangerService =
64         "xyz.openbmc_project.EntityManager";
65 
66     static constexpr auto searchpath = "/xyz/openbmc_project/";
67     int depth = 0;
68     std::vector<std::string> systemCompatible = {compatibleInterface};
69 
70     try
71     {
72         pldm::utils::GetSubTreeResponse response =
73             pldm::utils::DBusHandler().getSubtree(searchpath, depth,
74                                                   systemCompatible);
75         auto& bus = pldm::utils::DBusHandler::getBus();
76 
77         for (const auto& [objectPath, serviceMap] : response)
78         {
79             try
80             {
81                 auto record = std::find_if(
82                     serviceMap.begin(), serviceMap.end(),
83                     [](auto map) { return map.first == entityMangerService; });
84 
85                 if (record != serviceMap.end())
86                 {
87                     auto method = bus.new_method_call(
88                         entityMangerService.c_str(), objectPath.c_str(),
89                         "org.freedesktop.DBus.Properties", "Get");
90                     method.append(compatibleInterface, namesProperty);
91                     auto propSystemList =
92                         bus.call(method, dbusTimeout).unpack<PropertyValue>();
93                     auto systemList =
94                         std::get<std::vector<std::string>>(propSystemList);
95 
96                     if (!systemList.empty())
97                     {
98                         systemType = systemList.at(0);
99                         // once systemtype received,then resetting a callback
100                         systemCompatibleMatchCallBack.reset();
101                         return fs::path{systemType};
102                     }
103                 }
104             }
105             catch (const std::exception& e)
106             {
107                 error(
108                     "Error getting Names property at '{PATH}' on '{INTERFACE}': {ERROR}",
109                     "PATH", objectPath, "INTERFACE", compatibleInterface,
110                     "ERROR", e);
111             }
112         }
113     }
114     catch (const std::exception& e)
115     {
116         error("Failed to make a d-bus call to get platform name {ERROR}",
117               "ERROR", e);
118     }
119     return std::nullopt;
120 }
121 
122 } // namespace platform_config
123 
124 } // namespace responder
125 
126 } // namespace pldm
127