1*099543e4SBrad Bishop // SPDX-License-Identifier: Apache-2.0 2*099543e4SBrad Bishop 3*099543e4SBrad Bishop /**@file functions.cpp*/ 4*099543e4SBrad Bishop 5*099543e4SBrad Bishop #include "functions.hpp" 6*099543e4SBrad Bishop 7*099543e4SBrad Bishop #include <sdbusplus/bus.hpp> 8*099543e4SBrad Bishop #include <sdbusplus/bus/match.hpp> 9*099543e4SBrad Bishop #include <sdbusplus/message.hpp> 10*099543e4SBrad Bishop #include <sdeventplus/event.hpp> 11*099543e4SBrad Bishop 12*099543e4SBrad Bishop #include <filesystem> 13*099543e4SBrad Bishop #include <functional> 14*099543e4SBrad Bishop #include <iostream> 15*099543e4SBrad Bishop #include <map> 16*099543e4SBrad Bishop #include <memory> 17*099543e4SBrad Bishop #include <string> 18*099543e4SBrad Bishop #include <variant> 19*099543e4SBrad Bishop #include <vector> 20*099543e4SBrad Bishop 21*099543e4SBrad Bishop namespace functions 22*099543e4SBrad Bishop { 23*099543e4SBrad Bishop namespace process_hostfirmware 24*099543e4SBrad Bishop { 25*099543e4SBrad Bishop 26*099543e4SBrad Bishop /** 27*099543e4SBrad Bishop * @brief Issue callbacks safely 28*099543e4SBrad Bishop * 29*099543e4SBrad Bishop * std::function can be empty, so this wrapper method checks for that prior to 30*099543e4SBrad Bishop * calling it to avoid std::bad_function_call 31*099543e4SBrad Bishop * 32*099543e4SBrad Bishop * @tparam Sig the types of the std::function arguments 33*099543e4SBrad Bishop * @tparam Args the deduced argument types 34*099543e4SBrad Bishop * @param[in] callback the callback being wrapped 35*099543e4SBrad Bishop * @param[in] args the callback arguments 36*099543e4SBrad Bishop */ 37*099543e4SBrad Bishop template <typename... Sig, typename... Args> 38*099543e4SBrad Bishop void makeCallback(const std::function<void(Sig...)>& callback, Args&&... args) 39*099543e4SBrad Bishop { 40*099543e4SBrad Bishop if (callback) 41*099543e4SBrad Bishop { 42*099543e4SBrad Bishop callback(std::forward<Args>(args)...); 43*099543e4SBrad Bishop } 44*099543e4SBrad Bishop } 45*099543e4SBrad Bishop 46*099543e4SBrad Bishop /** 47*099543e4SBrad Bishop * @brief Get file extensions for IBMCompatibleSystem 48*099543e4SBrad Bishop * 49*099543e4SBrad Bishop * IBM host firmware can be deployed as blobs (files) in a filesystem. Host 50*099543e4SBrad Bishop * firmware blobs for different values of 51*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem are packaged with 52*099543e4SBrad Bishop * different filename extensions. getExtensionsForIbmCompatibleSystem 53*099543e4SBrad Bishop * maintains the mapping from a given value of 54*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to an array of 55*099543e4SBrad Bishop * filename extensions. 56*099543e4SBrad Bishop * 57*099543e4SBrad Bishop * If a mapping is found getExtensionsForIbmCompatibleSystem returns true and 58*099543e4SBrad Bishop * the extensions parameter is reset with the map entry. If no mapping is 59*099543e4SBrad Bishop * found getExtensionsForIbmCompatibleSystem returns false and extensions is 60*099543e4SBrad Bishop * unmodified. 61*099543e4SBrad Bishop * 62*099543e4SBrad Bishop * @param[in] extensionMap a map of 63*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to host firmware blob 64*099543e4SBrad Bishop * file extensions. 65*099543e4SBrad Bishop * @param[in] ibmCompatibleSystem The names property of an instance of 66*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem 67*099543e4SBrad Bishop * @param[out] extentions the host firmware blob file extensions 68*099543e4SBrad Bishop * @return true if an entry was found, otherwise false 69*099543e4SBrad Bishop */ 70*099543e4SBrad Bishop bool getExtensionsForIbmCompatibleSystem( 71*099543e4SBrad Bishop const std::map<std::string, std::vector<std::string>>& extensionMap, 72*099543e4SBrad Bishop const std::vector<std::string>& ibmCompatibleSystem, 73*099543e4SBrad Bishop std::vector<std::string>& extensions) 74*099543e4SBrad Bishop { 75*099543e4SBrad Bishop for (const auto& system : ibmCompatibleSystem) 76*099543e4SBrad Bishop { 77*099543e4SBrad Bishop auto extensionMapIterator = extensionMap.find(system); 78*099543e4SBrad Bishop if (extensionMapIterator != extensionMap.end()) 79*099543e4SBrad Bishop { 80*099543e4SBrad Bishop extensions = extensionMapIterator->second; 81*099543e4SBrad Bishop return true; 82*099543e4SBrad Bishop } 83*099543e4SBrad Bishop } 84*099543e4SBrad Bishop 85*099543e4SBrad Bishop return false; 86*099543e4SBrad Bishop } 87*099543e4SBrad Bishop 88*099543e4SBrad Bishop /** 89*099543e4SBrad Bishop * @brief Write host firmware well-known name 90*099543e4SBrad Bishop * 91*099543e4SBrad Bishop * A wrapper around std::filesystem::create_symlink that avoids EEXIST by 92*099543e4SBrad Bishop * deleting any pre-existing file. 93*099543e4SBrad Bishop * 94*099543e4SBrad Bishop * @param[in] linkTarget The link target argument to 95*099543e4SBrad Bishop * std::filesystem::create_symlink 96*099543e4SBrad Bishop * @param[in] linkPath The link path argument to std::filesystem::create_symlink 97*099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 98*099543e4SBrad Bishop */ 99*099543e4SBrad Bishop void writeLink(const std::filesystem::path& linkTarget, 100*099543e4SBrad Bishop const std::filesystem::path& linkPath, 101*099543e4SBrad Bishop const ErrorCallbackType& errorCallback) 102*099543e4SBrad Bishop { 103*099543e4SBrad Bishop std::error_code ec; 104*099543e4SBrad Bishop 105*099543e4SBrad Bishop // remove files with the same name as the symlink to be created, 106*099543e4SBrad Bishop // otherwise symlink will fail with EEXIST. 107*099543e4SBrad Bishop if (!std::filesystem::remove(linkPath, ec)) 108*099543e4SBrad Bishop { 109*099543e4SBrad Bishop if (ec) 110*099543e4SBrad Bishop { 111*099543e4SBrad Bishop makeCallback(errorCallback, linkPath, ec); 112*099543e4SBrad Bishop return; 113*099543e4SBrad Bishop } 114*099543e4SBrad Bishop } 115*099543e4SBrad Bishop 116*099543e4SBrad Bishop std::filesystem::create_symlink(linkTarget, linkPath, ec); 117*099543e4SBrad Bishop if (ec) 118*099543e4SBrad Bishop { 119*099543e4SBrad Bishop makeCallback(errorCallback, linkPath, ec); 120*099543e4SBrad Bishop return; 121*099543e4SBrad Bishop } 122*099543e4SBrad Bishop } 123*099543e4SBrad Bishop 124*099543e4SBrad Bishop /** 125*099543e4SBrad Bishop * @brief Find host firmware blob files that need well-known names 126*099543e4SBrad Bishop * 127*099543e4SBrad Bishop * The IBM host firmware runtime looks for data and/or additional code while 128*099543e4SBrad Bishop * bootstraping in files with well-known names. findLinks uses the provided 129*099543e4SBrad Bishop * extensions argument to find host firmware blob files that require a 130*099543e4SBrad Bishop * well-known name. When a blob is found, issue the provided callback 131*099543e4SBrad Bishop * (typically a function that will write a symlink). 132*099543e4SBrad Bishop * 133*099543e4SBrad Bishop * @param[in] hostFirmwareDirectory The directory in which findLinks should 134*099543e4SBrad Bishop * look for host firmware blob files that need well-known names. 135*099543e4SBrad Bishop * @param[in] extentions The extensions of the firmware blob files denote a 136*099543e4SBrad Bishop * host firmware blob file requires a well-known name. 137*099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 138*099543e4SBrad Bishop * @param[in] linkCallback A callback made when host firmware blob files 139*099543e4SBrad Bishop * needing a well known name are found. 140*099543e4SBrad Bishop */ 141*099543e4SBrad Bishop void findLinks(const std::filesystem::path& hostFirmwareDirectory, 142*099543e4SBrad Bishop const std::vector<std::string>& extensions, 143*099543e4SBrad Bishop const ErrorCallbackType& errorCallback, 144*099543e4SBrad Bishop const LinkCallbackType& linkCallback) 145*099543e4SBrad Bishop { 146*099543e4SBrad Bishop std::error_code ec; 147*099543e4SBrad Bishop std::filesystem::directory_iterator directoryIterator(hostFirmwareDirectory, 148*099543e4SBrad Bishop ec); 149*099543e4SBrad Bishop if (ec) 150*099543e4SBrad Bishop { 151*099543e4SBrad Bishop makeCallback(errorCallback, hostFirmwareDirectory, ec); 152*099543e4SBrad Bishop return; 153*099543e4SBrad Bishop } 154*099543e4SBrad Bishop 155*099543e4SBrad Bishop for (; directoryIterator != std::filesystem::end(directoryIterator); 156*099543e4SBrad Bishop directoryIterator.increment(ec)) 157*099543e4SBrad Bishop { 158*099543e4SBrad Bishop const auto& file = directoryIterator->path(); 159*099543e4SBrad Bishop if (ec) 160*099543e4SBrad Bishop { 161*099543e4SBrad Bishop makeCallback(errorCallback, file, ec); 162*099543e4SBrad Bishop // quit here if the increment call failed otherwise the loop may 163*099543e4SBrad Bishop // never finish 164*099543e4SBrad Bishop break; 165*099543e4SBrad Bishop } 166*099543e4SBrad Bishop 167*099543e4SBrad Bishop if (std::find(extensions.begin(), extensions.end(), file.extension()) == 168*099543e4SBrad Bishop extensions.end()) 169*099543e4SBrad Bishop { 170*099543e4SBrad Bishop // this file doesn't have an extension or doesn't match any of the 171*099543e4SBrad Bishop // provided extensions. 172*099543e4SBrad Bishop continue; 173*099543e4SBrad Bishop } 174*099543e4SBrad Bishop 175*099543e4SBrad Bishop auto linkPath(file.parent_path().append( 176*099543e4SBrad Bishop static_cast<const std::string&>(file.stem()))); 177*099543e4SBrad Bishop 178*099543e4SBrad Bishop makeCallback(linkCallback, file.filename(), linkPath, errorCallback); 179*099543e4SBrad Bishop } 180*099543e4SBrad Bishop } 181*099543e4SBrad Bishop 182*099543e4SBrad Bishop /** 183*099543e4SBrad Bishop * @brief Make callbacks on 184*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem instances. 185*099543e4SBrad Bishop * 186*099543e4SBrad Bishop * Look for an instance of 187*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem in the provided 188*099543e4SBrad Bishop * argument and if found, issue the provided callback. 189*099543e4SBrad Bishop * 190*099543e4SBrad Bishop * @param[in] interfacesAndProperties the interfaces in which to look for an 191*099543e4SBrad Bishop * instance of xyz.openbmc_project.Configuration.IBMCompatibleSystem 192*099543e4SBrad Bishop * @param[in] callback the user callback to make if 193*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is found in 194*099543e4SBrad Bishop * interfacesAndProperties 195*099543e4SBrad Bishop * @return true if interfacesAndProperties contained an instance of 196*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem, false otherwise 197*099543e4SBrad Bishop */ 198*099543e4SBrad Bishop bool maybeCall(const std::map<std::string, 199*099543e4SBrad Bishop std::map<std::string, 200*099543e4SBrad Bishop std::variant<std::vector<std::string>>>>& 201*099543e4SBrad Bishop interfacesAndProperties, 202*099543e4SBrad Bishop const MaybeCallCallbackType& callback) 203*099543e4SBrad Bishop { 204*099543e4SBrad Bishop using namespace std::string_literals; 205*099543e4SBrad Bishop 206*099543e4SBrad Bishop static const auto interfaceName = 207*099543e4SBrad Bishop "xyz.openbmc_project.Configuration.IBMCompatibleSystem"s; 208*099543e4SBrad Bishop auto interfaceIterator = interfacesAndProperties.find(interfaceName); 209*099543e4SBrad Bishop if (interfaceIterator == interfacesAndProperties.cend()) 210*099543e4SBrad Bishop { 211*099543e4SBrad Bishop // IBMCompatibleSystem interface not found, so instruct the caller to 212*099543e4SBrad Bishop // keep waiting or try again later. 213*099543e4SBrad Bishop return false; 214*099543e4SBrad Bishop } 215*099543e4SBrad Bishop auto propertyIterator = interfaceIterator->second.find("Names"s); 216*099543e4SBrad Bishop if (propertyIterator == interfaceIterator->second.cend()) 217*099543e4SBrad Bishop { 218*099543e4SBrad Bishop // The interface exists but the property doesn't. This is a bug in the 219*099543e4SBrad Bishop // IBMCompatibleSystem implementation. The caller should not try 220*099543e4SBrad Bishop // again. 221*099543e4SBrad Bishop std::cerr << "Names property not implemented on " << interfaceName 222*099543e4SBrad Bishop << "\n"; 223*099543e4SBrad Bishop return true; 224*099543e4SBrad Bishop } 225*099543e4SBrad Bishop 226*099543e4SBrad Bishop const auto& ibmCompatibleSystem = 227*099543e4SBrad Bishop std::get<std::vector<std::string>>(propertyIterator->second); 228*099543e4SBrad Bishop if (callback) 229*099543e4SBrad Bishop { 230*099543e4SBrad Bishop callback(ibmCompatibleSystem); 231*099543e4SBrad Bishop } 232*099543e4SBrad Bishop 233*099543e4SBrad Bishop // IBMCompatibleSystem found and callback issued. 234*099543e4SBrad Bishop return true; 235*099543e4SBrad Bishop } 236*099543e4SBrad Bishop 237*099543e4SBrad Bishop /** 238*099543e4SBrad Bishop * @brief Make callbacks on 239*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem instances. 240*099543e4SBrad Bishop * 241*099543e4SBrad Bishop * Look for an instance of 242*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem in the provided 243*099543e4SBrad Bishop * argument and if found, issue the provided callback. 244*099543e4SBrad Bishop * 245*099543e4SBrad Bishop * @param[in] message the DBus message in which to look for an instance of 246*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem 247*099543e4SBrad Bishop * @param[in] callback the user callback to make if 248*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is found in 249*099543e4SBrad Bishop * message 250*099543e4SBrad Bishop * @return true if message contained an instance of 251*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem, false otherwise 252*099543e4SBrad Bishop */ 253*099543e4SBrad Bishop bool maybeCallMessage(sdbusplus::message::message& message, 254*099543e4SBrad Bishop const MaybeCallCallbackType& callback) 255*099543e4SBrad Bishop { 256*099543e4SBrad Bishop std::map<std::string, 257*099543e4SBrad Bishop std::map<std::string, std::variant<std::vector<std::string>>>> 258*099543e4SBrad Bishop interfacesAndProperties; 259*099543e4SBrad Bishop sdbusplus::message::object_path _; 260*099543e4SBrad Bishop message.read(_, interfacesAndProperties); 261*099543e4SBrad Bishop return maybeCall(interfacesAndProperties, callback); 262*099543e4SBrad Bishop } 263*099543e4SBrad Bishop 264*099543e4SBrad Bishop /** 265*099543e4SBrad Bishop * @brief Determine system support for host firmware well-known names. 266*099543e4SBrad Bishop * 267*099543e4SBrad Bishop * Using the provided extensionMap and 268*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem, determine if 269*099543e4SBrad Bishop * well-known names for host firmare blob files are necessary and if so, create 270*099543e4SBrad Bishop * them. 271*099543e4SBrad Bishop * 272*099543e4SBrad Bishop * @param[in] extensionMap a map of 273*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to host firmware blob 274*099543e4SBrad Bishop * file extensions. 275*099543e4SBrad Bishop * @param[in] hostFirmwareDirectory The directory in which findLinks should 276*099543e4SBrad Bishop * look for host firmware blob files that need well-known names. 277*099543e4SBrad Bishop * @param[in] ibmCompatibleSystem The names property of an instance of 278*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem 279*099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 280*099543e4SBrad Bishop */ 281*099543e4SBrad Bishop void maybeMakeLinks( 282*099543e4SBrad Bishop const std::map<std::string, std::vector<std::string>>& extensionMap, 283*099543e4SBrad Bishop const std::filesystem::path& hostFirmwareDirectory, 284*099543e4SBrad Bishop const std::vector<std::string>& ibmCompatibleSystem, 285*099543e4SBrad Bishop const ErrorCallbackType& errorCallback) 286*099543e4SBrad Bishop { 287*099543e4SBrad Bishop std::vector<std::string> extensions; 288*099543e4SBrad Bishop if (getExtensionsForIbmCompatibleSystem(extensionMap, ibmCompatibleSystem, 289*099543e4SBrad Bishop extensions)) 290*099543e4SBrad Bishop { 291*099543e4SBrad Bishop findLinks(hostFirmwareDirectory, extensions, errorCallback, writeLink); 292*099543e4SBrad Bishop } 293*099543e4SBrad Bishop } 294*099543e4SBrad Bishop 295*099543e4SBrad Bishop /** 296*099543e4SBrad Bishop * @brief process host firmware 297*099543e4SBrad Bishop * 298*099543e4SBrad Bishop * Allocate a callback context and register for DBus.ObjectManager Interfaces 299*099543e4SBrad Bishop * added signals from entity manager. 300*099543e4SBrad Bishop * 301*099543e4SBrad Bishop * Check the current entity manager object tree for a 302*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem instance (entity 303*099543e4SBrad Bishop * manager will be dbus activated if it is not running). If one is found, 304*099543e4SBrad Bishop * determine if symlinks need to be created and create them. Instruct the 305*099543e4SBrad Bishop * program event loop to exit. 306*099543e4SBrad Bishop * 307*099543e4SBrad Bishop * If no instance of xyz.openbmc_project.Configuration.IBMCompatibleSystem is 308*099543e4SBrad Bishop * found return the callback context to main, where the program will sleep 309*099543e4SBrad Bishop * until the callback is invoked one or more times and instructs the program 310*099543e4SBrad Bishop * event loop to exit when 311*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is added. 312*099543e4SBrad Bishop * 313*099543e4SBrad Bishop * @param[in] bus a DBus client connection 314*099543e4SBrad Bishop * @param[in] extensionMap a map of 315*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to host firmware blob 316*099543e4SBrad Bishop * file extensions. 317*099543e4SBrad Bishop * @param[in] hostFirmwareDirectory The directory in which processHostFirmware 318*099543e4SBrad Bishop * should look for blob files. 319*099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 320*099543e4SBrad Bishop * @param[in] loop a program event loop 321*099543e4SBrad Bishop * @return nullptr if an instance of 322*099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is found, otherwise a 323*099543e4SBrad Bishop * pointer to an sdbusplus match object. 324*099543e4SBrad Bishop */ 325*099543e4SBrad Bishop std::shared_ptr<void> processHostFirmware( 326*099543e4SBrad Bishop sdbusplus::bus::bus& bus, 327*099543e4SBrad Bishop std::map<std::string, std::vector<std::string>> extensionMap, 328*099543e4SBrad Bishop std::filesystem::path hostFirmwareDirectory, 329*099543e4SBrad Bishop ErrorCallbackType errorCallback, sdeventplus::Event& loop) 330*099543e4SBrad Bishop { 331*099543e4SBrad Bishop // ownership of extensionMap, hostFirmwareDirectory and errorCallback can't 332*099543e4SBrad Bishop // be transfered to the match callback because they are needed in the non 333*099543e4SBrad Bishop // async part of this function below, so they need to be moved to the heap. 334*099543e4SBrad Bishop auto pExtensionMap = 335*099543e4SBrad Bishop std::make_shared<decltype(extensionMap)>(std::move(extensionMap)); 336*099543e4SBrad Bishop auto pHostFirmwareDirectory = 337*099543e4SBrad Bishop std::make_shared<decltype(hostFirmwareDirectory)>( 338*099543e4SBrad Bishop std::move(hostFirmwareDirectory)); 339*099543e4SBrad Bishop auto pErrorCallback = 340*099543e4SBrad Bishop std::make_shared<decltype(errorCallback)>(std::move(errorCallback)); 341*099543e4SBrad Bishop 342*099543e4SBrad Bishop // register for a callback in case the IBMCompatibleSystem interface has 343*099543e4SBrad Bishop // not yet been published by entity manager. 344*099543e4SBrad Bishop auto interfacesAddedMatch = std::make_shared<sdbusplus::bus::match::match>( 345*099543e4SBrad Bishop bus, 346*099543e4SBrad Bishop sdbusplus::bus::match::rules::interfacesAdded() + 347*099543e4SBrad Bishop sdbusplus::bus::match::rules::sender( 348*099543e4SBrad Bishop "xyz.openbmc_project.EntityManager"), 349*099543e4SBrad Bishop [pExtensionMap, pHostFirmwareDirectory, pErrorCallback, 350*099543e4SBrad Bishop &loop](auto& message) { 351*099543e4SBrad Bishop // bind the extension map, host firmware directory, and error 352*099543e4SBrad Bishop // callback to the maybeMakeLinks function. 353*099543e4SBrad Bishop auto maybeMakeLinksWithArgsBound = 354*099543e4SBrad Bishop std::bind(maybeMakeLinks, std::cref(*pExtensionMap), 355*099543e4SBrad Bishop std::cref(*pHostFirmwareDirectory), 356*099543e4SBrad Bishop std::placeholders::_1, std::cref(*pErrorCallback)); 357*099543e4SBrad Bishop 358*099543e4SBrad Bishop // if the InterfacesAdded message contains an an instance of 359*099543e4SBrad Bishop // xyz.openbmc_project.Configuration.IBMCompatibleSystem, check to 360*099543e4SBrad Bishop // see if links are necessary on this system and if so, create 361*099543e4SBrad Bishop // them. 362*099543e4SBrad Bishop if (maybeCallMessage(message, maybeMakeLinksWithArgsBound)) 363*099543e4SBrad Bishop { 364*099543e4SBrad Bishop // The IBMCompatibleSystem interface was found and the links 365*099543e4SBrad Bishop // were created if applicable. Instruct the event loop / 366*099543e4SBrad Bishop // subcommand to exit. 367*099543e4SBrad Bishop loop.exit(0); 368*099543e4SBrad Bishop } 369*099543e4SBrad Bishop }); 370*099543e4SBrad Bishop 371*099543e4SBrad Bishop // now that we'll get a callback in the event of an InterfacesAdded signal 372*099543e4SBrad Bishop // (potentially containing 373*099543e4SBrad Bishop // xyz.openbmc_project.Configuration.IBMCompatibleSystem), activate entity 374*099543e4SBrad Bishop // manager if it isn't running and enumerate its objects 375*099543e4SBrad Bishop auto getManagedObjects = bus.new_method_call( 376*099543e4SBrad Bishop "xyz.openbmc_project.EntityManager", "/", 377*099543e4SBrad Bishop "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 378*099543e4SBrad Bishop auto reply = bus.call(getManagedObjects); 379*099543e4SBrad Bishop std::map<std::string, 380*099543e4SBrad Bishop std::map<std::string, std::variant<std::vector<std::string>>>> 381*099543e4SBrad Bishop interfacesAndProperties; 382*099543e4SBrad Bishop std::map<sdbusplus::message::object_path, decltype(interfacesAndProperties)> 383*099543e4SBrad Bishop objects; 384*099543e4SBrad Bishop reply.read(objects); 385*099543e4SBrad Bishop 386*099543e4SBrad Bishop // bind the extension map, host firmware directory, and error callback to 387*099543e4SBrad Bishop // the maybeMakeLinks function. 388*099543e4SBrad Bishop auto maybeMakeLinksWithArgsBound = 389*099543e4SBrad Bishop std::bind(maybeMakeLinks, std::cref(*pExtensionMap), 390*099543e4SBrad Bishop std::cref(*pHostFirmwareDirectory), std::placeholders::_1, 391*099543e4SBrad Bishop std::cref(*pErrorCallback)); 392*099543e4SBrad Bishop 393*099543e4SBrad Bishop for (const auto& pair : objects) 394*099543e4SBrad Bishop { 395*099543e4SBrad Bishop std::tie(std::ignore, interfacesAndProperties) = pair; 396*099543e4SBrad Bishop // if interfacesAndProperties contains an an instance of 397*099543e4SBrad Bishop // xyz.openbmc_project.Configuration.IBMCompatibleSystem, check to see 398*099543e4SBrad Bishop // if links are necessary on this system and if so, create them 399*099543e4SBrad Bishop if (maybeCall(interfacesAndProperties, maybeMakeLinksWithArgsBound)) 400*099543e4SBrad Bishop { 401*099543e4SBrad Bishop // The IBMCompatibleSystem interface is already on the bus and the 402*099543e4SBrad Bishop // links were created if applicable. Instruct the event loop to 403*099543e4SBrad Bishop // exit. 404*099543e4SBrad Bishop loop.exit(0); 405*099543e4SBrad Bishop // The match object isn't needed anymore, so destroy it on return. 406*099543e4SBrad Bishop return nullptr; 407*099543e4SBrad Bishop } 408*099543e4SBrad Bishop } 409*099543e4SBrad Bishop 410*099543e4SBrad Bishop // The IBMCompatibleSystem interface has not yet been published. Move 411*099543e4SBrad Bishop // ownership of the match callback to the caller. 412*099543e4SBrad Bishop return interfacesAddedMatch; 413*099543e4SBrad Bishop } 414*099543e4SBrad Bishop } // namespace process_hostfirmware 415*099543e4SBrad Bishop } // namespace functions 416