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 */ 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 */ 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 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 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