1 #include "platform_config.hpp"
2
3 #include <phosphor-logging/lg2.hpp>
4
5 PHOSPHOR_LOG2_USING;
6
7 namespace pldm
8 {
9 namespace responder
10 {
11
12 namespace platform_config
13 {
14 /** @brief callback function invoked when interfaces get added from
15 * Entity manager
16 *
17 * @param[in] msg - Data associated with subscribed signal
18 */
systemCompatibleCallback(sdbusplus::message_t & msg)19 void Handler::systemCompatibleCallback(sdbusplus::message_t& msg)
20 {
21 sdbusplus::message::object_path path;
22
23 pldm::utils::InterfaceMap interfaceMap;
24
25 msg.read(path, interfaceMap);
26
27 if (!interfaceMap.contains(compatibleInterface))
28 {
29 return;
30 }
31 // Get the "Name" property value of the
32 // "xyz.openbmc_project.Inventory.Decorator.Compatible" interface
33 const auto& properties = interfaceMap.at(compatibleInterface);
34
35 if (!properties.contains(namesProperty))
36 {
37 return;
38 }
39 auto names =
40 std::get<pldm::utils::Interfaces>(properties.at(namesProperty));
41
42 if (!names.empty())
43 {
44 std::optional<std::string> sysType =
45 getSysSpecificJsonDir(sysDirPath, names);
46 if (sysType.has_value())
47 {
48 systemType = sysType.value();
49 }
50 if (sysTypeCallback)
51 {
52 sysTypeCallback(systemType, true);
53 }
54 }
55
56 if (!systemType.empty())
57 {
58 systemCompatibleMatchCallBack.reset();
59 }
60 }
61
62 /** @brief Method to get the system type information
63 *
64 * @return - the system type information
65 */
getPlatformName()66 std::optional<std::filesystem::path> Handler::getPlatformName()
67 {
68 if (!systemType.empty())
69 {
70 return fs::path{systemType};
71 }
72
73 namespace fs = std::filesystem;
74 static const std::string entityMangerService =
75 "xyz.openbmc_project.EntityManager";
76
77 static constexpr auto searchpath = "/xyz/openbmc_project/";
78 int depth = 0;
79 std::vector<std::string> systemCompatible = {compatibleInterface};
80
81 try
82 {
83 pldm::utils::GetSubTreeResponse response =
84 pldm::utils::DBusHandler().getSubtree(searchpath, depth,
85 systemCompatible);
86 auto& bus = pldm::utils::DBusHandler::getBus();
87
88 for (const auto& [objectPath, serviceMap] : response)
89 {
90 try
91 {
92 auto record = std::find_if(
93 serviceMap.begin(), serviceMap.end(),
94 [](auto map) { return map.first == entityMangerService; });
95
96 if (record != serviceMap.end())
97 {
98 auto method = bus.new_method_call(
99 entityMangerService.c_str(), objectPath.c_str(),
100 "org.freedesktop.DBus.Properties", "Get");
101 method.append(compatibleInterface, namesProperty);
102 auto propSystemList =
103 bus.call(method, dbusTimeout).unpack<PropertyValue>();
104 auto systemList =
105 std::get<std::vector<std::string>>(propSystemList);
106
107 if (!systemList.empty())
108 {
109 std::optional<std::string> sysType =
110 getSysSpecificJsonDir(sysDirPath, systemList);
111 // once systemtype received,then resetting a callback
112 systemCompatibleMatchCallBack.reset();
113 if (sysType.has_value())
114 {
115 systemType = sysType.value();
116 }
117 return fs::path{systemType};
118 }
119 }
120 }
121 catch (const std::exception& e)
122 {
123 error(
124 "Failed to get Names property at '{PATH}' on interface '{INTERFACE}', error - {ERROR}",
125 "PATH", objectPath, "INTERFACE", compatibleInterface,
126 "ERROR", e);
127 }
128 }
129 }
130 catch (const std::exception& e)
131 {
132 error(
133 "Failed to make a d-bus call to get platform name, error - {ERROR}",
134 "ERROR", e);
135 }
136 return std::nullopt;
137 }
138
getSysSpecificJsonDir(const fs::path & dirPath,const std::vector<std::string> & dirNames)139 std::optional<std::string> Handler::getSysSpecificJsonDir(
140 const fs::path& dirPath, const std::vector<std::string>& dirNames)
141 {
142 // The current setup assumes that the BIOS and PDR configurations always
143 // come from the same system type. If, in the future, we need to use BIOS
144 // and PDR configurations from different system types, we should create
145 // separate system type folders for each and update the logic to support
146 // this.
147
148 if (dirPath.empty())
149 {
150 return std::nullopt;
151 }
152
153 for (const auto& dirEntry : std::filesystem::directory_iterator{dirPath})
154 {
155 if (dirEntry.is_directory())
156 {
157 const auto sysDir = dirEntry.path().filename().string();
158 if (std::find(dirNames.begin(), dirNames.end(), sysDir) !=
159 dirNames.end())
160 {
161 return sysDir;
162 }
163 }
164 }
165
166 return std::nullopt;
167 }
168
registerSystemTypeCallback(SystemTypeCallback callback)169 void Handler::registerSystemTypeCallback(SystemTypeCallback callback)
170 {
171 sysTypeCallback = callback;
172 }
173
174 } // namespace platform_config
175
176 } // namespace responder
177
178 } // namespace pldm
179