1099543e4SBrad Bishop // SPDX-License-Identifier: Apache-2.0 2099543e4SBrad Bishop 3099543e4SBrad Bishop /**@file functions.cpp*/ 4099543e4SBrad Bishop 556f538caSAdriana Kobylak #include "config.h" 656f538caSAdriana Kobylak 7099543e4SBrad Bishop #include "functions.hpp" 8099543e4SBrad Bishop 9ae0998f1SAdriana Kobylak #include <nlohmann/json.hpp> 1056f538caSAdriana Kobylak #include <phosphor-logging/log.hpp> 11099543e4SBrad Bishop #include <sdbusplus/bus.hpp> 12099543e4SBrad Bishop #include <sdbusplus/bus/match.hpp> 13c79fa915SAdriana Kobylak #include <sdbusplus/exception.hpp> 14099543e4SBrad Bishop #include <sdbusplus/message.hpp> 15099543e4SBrad Bishop #include <sdeventplus/event.hpp> 16099543e4SBrad Bishop 17099543e4SBrad Bishop #include <filesystem> 18ae0998f1SAdriana Kobylak #include <fstream> 19099543e4SBrad Bishop #include <functional> 20099543e4SBrad Bishop #include <iostream> 21099543e4SBrad Bishop #include <map> 22099543e4SBrad Bishop #include <memory> 23099543e4SBrad Bishop #include <string> 24099543e4SBrad Bishop #include <variant> 25099543e4SBrad Bishop #include <vector> 26099543e4SBrad Bishop 27099543e4SBrad Bishop namespace functions 28099543e4SBrad Bishop { 29099543e4SBrad Bishop namespace process_hostfirmware 30099543e4SBrad Bishop { 31099543e4SBrad Bishop 3256f538caSAdriana Kobylak using namespace phosphor::logging; 33ebf67bf7SAdriana Kobylak using InterfacesPropertiesMap = 34ebf67bf7SAdriana Kobylak std::map<std::string, 35ebf67bf7SAdriana Kobylak std::map<std::string, std::variant<std::vector<std::string>>>>; 36ebf67bf7SAdriana Kobylak using ManagedObjectType = 37ebf67bf7SAdriana Kobylak std::map<sdbusplus::message::object_path, InterfacesPropertiesMap>; 3856f538caSAdriana Kobylak 39099543e4SBrad Bishop /** 40fd4a6088SAdriana Kobylak * @brief GetObject function to find the service given an object path. 41fd4a6088SAdriana Kobylak * It is used to determine if a service is running, so there is no need 42fd4a6088SAdriana Kobylak * to specify interfaces as a parameter to constrain the search. 43fd4a6088SAdriana Kobylak */ 44fd4a6088SAdriana Kobylak std::string getObject(sdbusplus::bus::bus& bus, const std::string& path) 45fd4a6088SAdriana Kobylak { 46fd4a6088SAdriana Kobylak auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, 47fd4a6088SAdriana Kobylak MAPPER_BUSNAME, "GetObject"); 48fd4a6088SAdriana Kobylak method.append(path); 49fd4a6088SAdriana Kobylak std::vector<std::string> interfaces; 50fd4a6088SAdriana Kobylak method.append(interfaces); 51fd4a6088SAdriana Kobylak 52fd4a6088SAdriana Kobylak std::vector<std::pair<std::string, std::vector<std::string>>> response; 53fd4a6088SAdriana Kobylak 54fd4a6088SAdriana Kobylak try 55fd4a6088SAdriana Kobylak { 56fd4a6088SAdriana Kobylak auto reply = bus.call(method); 57fd4a6088SAdriana Kobylak reply.read(response); 58fd4a6088SAdriana Kobylak if (response.empty()) 59fd4a6088SAdriana Kobylak { 60fd4a6088SAdriana Kobylak return std::string{}; 61fd4a6088SAdriana Kobylak } 62fd4a6088SAdriana Kobylak } 63fd4a6088SAdriana Kobylak catch (const sdbusplus::exception::SdBusError& e) 64fd4a6088SAdriana Kobylak { 65fd4a6088SAdriana Kobylak return std::string{}; 66fd4a6088SAdriana Kobylak } 67fd4a6088SAdriana Kobylak return response[0].first; 68fd4a6088SAdriana Kobylak } 69fd4a6088SAdriana Kobylak 70fd4a6088SAdriana Kobylak /** 71ebf67bf7SAdriana Kobylak * @brief Returns the managed objects for a given service 72ebf67bf7SAdriana Kobylak */ 73ebf67bf7SAdriana Kobylak ManagedObjectType getManagedObjects(sdbusplus::bus::bus& bus, 74ebf67bf7SAdriana Kobylak const std::string& service) 75ebf67bf7SAdriana Kobylak { 76ebf67bf7SAdriana Kobylak auto method = bus.new_method_call(service.c_str(), "/", 77ebf67bf7SAdriana Kobylak "org.freedesktop.DBus.ObjectManager", 78ebf67bf7SAdriana Kobylak "GetManagedObjects"); 79ebf67bf7SAdriana Kobylak 80ebf67bf7SAdriana Kobylak ManagedObjectType objects; 81ebf67bf7SAdriana Kobylak 82ebf67bf7SAdriana Kobylak try 83ebf67bf7SAdriana Kobylak { 84ebf67bf7SAdriana Kobylak auto reply = bus.call(method); 85ebf67bf7SAdriana Kobylak reply.read(objects); 86ebf67bf7SAdriana Kobylak } 87ebf67bf7SAdriana Kobylak catch (const sdbusplus::exception::SdBusError& e) 88ebf67bf7SAdriana Kobylak { 89ebf67bf7SAdriana Kobylak return ManagedObjectType{}; 90ebf67bf7SAdriana Kobylak } 91ebf67bf7SAdriana Kobylak return objects; 92ebf67bf7SAdriana Kobylak } 93ebf67bf7SAdriana Kobylak 94ebf67bf7SAdriana Kobylak /** 95099543e4SBrad Bishop * @brief Issue callbacks safely 96099543e4SBrad Bishop * 97099543e4SBrad Bishop * std::function can be empty, so this wrapper method checks for that prior to 98099543e4SBrad Bishop * calling it to avoid std::bad_function_call 99099543e4SBrad Bishop * 100099543e4SBrad Bishop * @tparam Sig the types of the std::function arguments 101099543e4SBrad Bishop * @tparam Args the deduced argument types 102099543e4SBrad Bishop * @param[in] callback the callback being wrapped 103099543e4SBrad Bishop * @param[in] args the callback arguments 104099543e4SBrad Bishop */ 105099543e4SBrad Bishop template <typename... Sig, typename... Args> 106099543e4SBrad Bishop void makeCallback(const std::function<void(Sig...)>& callback, Args&&... args) 107099543e4SBrad Bishop { 108099543e4SBrad Bishop if (callback) 109099543e4SBrad Bishop { 110099543e4SBrad Bishop callback(std::forward<Args>(args)...); 111099543e4SBrad Bishop } 112099543e4SBrad Bishop } 113099543e4SBrad Bishop 114099543e4SBrad Bishop /** 115099543e4SBrad Bishop * @brief Get file extensions for IBMCompatibleSystem 116099543e4SBrad Bishop * 117099543e4SBrad Bishop * IBM host firmware can be deployed as blobs (files) in a filesystem. Host 118099543e4SBrad Bishop * firmware blobs for different values of 119099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem are packaged with 120099543e4SBrad Bishop * different filename extensions. getExtensionsForIbmCompatibleSystem 121099543e4SBrad Bishop * maintains the mapping from a given value of 122099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to an array of 123099543e4SBrad Bishop * filename extensions. 124099543e4SBrad Bishop * 125099543e4SBrad Bishop * If a mapping is found getExtensionsForIbmCompatibleSystem returns true and 126099543e4SBrad Bishop * the extensions parameter is reset with the map entry. If no mapping is 127099543e4SBrad Bishop * found getExtensionsForIbmCompatibleSystem returns false and extensions is 128099543e4SBrad Bishop * unmodified. 129099543e4SBrad Bishop * 130099543e4SBrad Bishop * @param[in] extensionMap a map of 131099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to host firmware blob 132099543e4SBrad Bishop * file extensions. 133099543e4SBrad Bishop * @param[in] ibmCompatibleSystem The names property of an instance of 134099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem 135099543e4SBrad Bishop * @param[out] extentions the host firmware blob file extensions 136099543e4SBrad Bishop * @return true if an entry was found, otherwise false 137099543e4SBrad Bishop */ 138099543e4SBrad Bishop bool getExtensionsForIbmCompatibleSystem( 139099543e4SBrad Bishop const std::map<std::string, std::vector<std::string>>& extensionMap, 140099543e4SBrad Bishop const std::vector<std::string>& ibmCompatibleSystem, 141099543e4SBrad Bishop std::vector<std::string>& extensions) 142099543e4SBrad Bishop { 143099543e4SBrad Bishop for (const auto& system : ibmCompatibleSystem) 144099543e4SBrad Bishop { 145099543e4SBrad Bishop auto extensionMapIterator = extensionMap.find(system); 146099543e4SBrad Bishop if (extensionMapIterator != extensionMap.end()) 147099543e4SBrad Bishop { 148099543e4SBrad Bishop extensions = extensionMapIterator->second; 149099543e4SBrad Bishop return true; 150099543e4SBrad Bishop } 151099543e4SBrad Bishop } 152099543e4SBrad Bishop 153099543e4SBrad Bishop return false; 154099543e4SBrad Bishop } 155099543e4SBrad Bishop 156099543e4SBrad Bishop /** 157099543e4SBrad Bishop * @brief Write host firmware well-known name 158099543e4SBrad Bishop * 159099543e4SBrad Bishop * A wrapper around std::filesystem::create_symlink that avoids EEXIST by 160099543e4SBrad Bishop * deleting any pre-existing file. 161099543e4SBrad Bishop * 162099543e4SBrad Bishop * @param[in] linkTarget The link target argument to 163099543e4SBrad Bishop * std::filesystem::create_symlink 164099543e4SBrad Bishop * @param[in] linkPath The link path argument to std::filesystem::create_symlink 165099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 166099543e4SBrad Bishop */ 167099543e4SBrad Bishop void writeLink(const std::filesystem::path& linkTarget, 168099543e4SBrad Bishop const std::filesystem::path& linkPath, 169099543e4SBrad Bishop const ErrorCallbackType& errorCallback) 170099543e4SBrad Bishop { 171099543e4SBrad Bishop std::error_code ec; 172099543e4SBrad Bishop 173099543e4SBrad Bishop // remove files with the same name as the symlink to be created, 174099543e4SBrad Bishop // otherwise symlink will fail with EEXIST. 175099543e4SBrad Bishop if (!std::filesystem::remove(linkPath, ec)) 176099543e4SBrad Bishop { 177099543e4SBrad Bishop if (ec) 178099543e4SBrad Bishop { 179099543e4SBrad Bishop makeCallback(errorCallback, linkPath, ec); 180099543e4SBrad Bishop return; 181099543e4SBrad Bishop } 182099543e4SBrad Bishop } 183099543e4SBrad Bishop 184099543e4SBrad Bishop std::filesystem::create_symlink(linkTarget, linkPath, ec); 185099543e4SBrad Bishop if (ec) 186099543e4SBrad Bishop { 187099543e4SBrad Bishop makeCallback(errorCallback, linkPath, ec); 188099543e4SBrad Bishop return; 189099543e4SBrad Bishop } 190099543e4SBrad Bishop } 191099543e4SBrad Bishop 192099543e4SBrad Bishop /** 193099543e4SBrad Bishop * @brief Find host firmware blob files that need well-known names 194099543e4SBrad Bishop * 195099543e4SBrad Bishop * The IBM host firmware runtime looks for data and/or additional code while 196099543e4SBrad Bishop * bootstraping in files with well-known names. findLinks uses the provided 197099543e4SBrad Bishop * extensions argument to find host firmware blob files that require a 198099543e4SBrad Bishop * well-known name. When a blob is found, issue the provided callback 199099543e4SBrad Bishop * (typically a function that will write a symlink). 200099543e4SBrad Bishop * 201099543e4SBrad Bishop * @param[in] hostFirmwareDirectory The directory in which findLinks should 202099543e4SBrad Bishop * look for host firmware blob files that need well-known names. 203099543e4SBrad Bishop * @param[in] extentions The extensions of the firmware blob files denote a 204099543e4SBrad Bishop * host firmware blob file requires a well-known name. 205099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 206099543e4SBrad Bishop * @param[in] linkCallback A callback made when host firmware blob files 207099543e4SBrad Bishop * needing a well known name are found. 208099543e4SBrad Bishop */ 209099543e4SBrad Bishop void findLinks(const std::filesystem::path& hostFirmwareDirectory, 210099543e4SBrad Bishop const std::vector<std::string>& extensions, 211099543e4SBrad Bishop const ErrorCallbackType& errorCallback, 212099543e4SBrad Bishop const LinkCallbackType& linkCallback) 213099543e4SBrad Bishop { 214099543e4SBrad Bishop std::error_code ec; 215099543e4SBrad Bishop std::filesystem::directory_iterator directoryIterator(hostFirmwareDirectory, 216099543e4SBrad Bishop ec); 217099543e4SBrad Bishop if (ec) 218099543e4SBrad Bishop { 219099543e4SBrad Bishop makeCallback(errorCallback, hostFirmwareDirectory, ec); 220099543e4SBrad Bishop return; 221099543e4SBrad Bishop } 222099543e4SBrad Bishop 223099543e4SBrad Bishop for (; directoryIterator != std::filesystem::end(directoryIterator); 224099543e4SBrad Bishop directoryIterator.increment(ec)) 225099543e4SBrad Bishop { 226099543e4SBrad Bishop const auto& file = directoryIterator->path(); 227099543e4SBrad Bishop if (ec) 228099543e4SBrad Bishop { 229099543e4SBrad Bishop makeCallback(errorCallback, file, ec); 230099543e4SBrad Bishop // quit here if the increment call failed otherwise the loop may 231099543e4SBrad Bishop // never finish 232099543e4SBrad Bishop break; 233099543e4SBrad Bishop } 234099543e4SBrad Bishop 235099543e4SBrad Bishop if (std::find(extensions.begin(), extensions.end(), file.extension()) == 236099543e4SBrad Bishop extensions.end()) 237099543e4SBrad Bishop { 238099543e4SBrad Bishop // this file doesn't have an extension or doesn't match any of the 239099543e4SBrad Bishop // provided extensions. 240099543e4SBrad Bishop continue; 241099543e4SBrad Bishop } 242099543e4SBrad Bishop 243099543e4SBrad Bishop auto linkPath(file.parent_path().append( 244099543e4SBrad Bishop static_cast<const std::string&>(file.stem()))); 245099543e4SBrad Bishop 246099543e4SBrad Bishop makeCallback(linkCallback, file.filename(), linkPath, errorCallback); 247099543e4SBrad Bishop } 248099543e4SBrad Bishop } 249099543e4SBrad Bishop 250099543e4SBrad Bishop /** 251ae0998f1SAdriana Kobylak * @brief Parse the elements json file and construct a string with the data to 252ae0998f1SAdriana Kobylak * be used to update the bios attribute table. 253ae0998f1SAdriana Kobylak * 254ae0998f1SAdriana Kobylak * @param[in] elementsJsonFilePath - The path to the host firmware json file. 255ae0998f1SAdriana Kobylak * @param[in] extensions - The extensions of the firmware blob files. 25653a27395SAdriana Kobylak */ 257ae0998f1SAdriana Kobylak std::string getBiosAttrStr(const std::filesystem::path& elementsJsonFilePath, 258ae0998f1SAdriana Kobylak const std::vector<std::string>& extensions) 25956f538caSAdriana Kobylak { 26056f538caSAdriana Kobylak std::string biosAttrStr{}; 26156f538caSAdriana Kobylak 262ae0998f1SAdriana Kobylak std::ifstream jsonFile(elementsJsonFilePath.c_str()); 263ae0998f1SAdriana Kobylak if (!jsonFile) 264ae0998f1SAdriana Kobylak { 265ae0998f1SAdriana Kobylak return {}; 266ae0998f1SAdriana Kobylak } 267ae0998f1SAdriana Kobylak 268ae0998f1SAdriana Kobylak std::map<std::string, std::string> attr; 269ae0998f1SAdriana Kobylak auto data = nlohmann::json::parse(jsonFile, nullptr, false); 270ae0998f1SAdriana Kobylak if (data.is_discarded()) 271ae0998f1SAdriana Kobylak { 272ae0998f1SAdriana Kobylak log<level::ERR>("Error parsing JSON file", 273ae0998f1SAdriana Kobylak entry("FILE=%s", elementsJsonFilePath.c_str())); 274ae0998f1SAdriana Kobylak return {}; 275ae0998f1SAdriana Kobylak } 276ae0998f1SAdriana Kobylak 277ae0998f1SAdriana Kobylak // .get requires a non-const iterator 278ae0998f1SAdriana Kobylak for (auto& iter : data["lids"]) 279ae0998f1SAdriana Kobylak { 280ae0998f1SAdriana Kobylak std::string name{}; 281ae0998f1SAdriana Kobylak std::string lid{}; 282ae0998f1SAdriana Kobylak 283ae0998f1SAdriana Kobylak try 284ae0998f1SAdriana Kobylak { 285ae0998f1SAdriana Kobylak name = iter["element_name"].get<std::string>(); 286ae0998f1SAdriana Kobylak lid = iter["short_lid_name"].get<std::string>(); 287ae0998f1SAdriana Kobylak } 288ae0998f1SAdriana Kobylak catch (std::exception& e) 289ae0998f1SAdriana Kobylak { 290ae0998f1SAdriana Kobylak // Possibly the element or lid name field was not found 291ae0998f1SAdriana Kobylak log<level::ERR>("Error reading JSON field", 292ae0998f1SAdriana Kobylak entry("FILE=%s", elementsJsonFilePath.c_str()), 293ae0998f1SAdriana Kobylak entry("ERROR=%s", e.what())); 294ae0998f1SAdriana Kobylak continue; 295ae0998f1SAdriana Kobylak } 296ae0998f1SAdriana Kobylak 297ae0998f1SAdriana Kobylak // The elements with the ipl extension have higher priority. Therefore 298ae0998f1SAdriana Kobylak // Use operator[] to overwrite value if an entry for it already exists. 299ae0998f1SAdriana Kobylak // Ex: if the JSON contains an entry A.P10 followed by A.P10.iplTime, 300ae0998f1SAdriana Kobylak // the lid value for the latter one will be overwrite the value of the 301ae0998f1SAdriana Kobylak // first one. 302ae0998f1SAdriana Kobylak constexpr auto iplExtension = ".iplTime"; 303ae0998f1SAdriana Kobylak std::filesystem::path path(name); 304ae0998f1SAdriana Kobylak if (path.extension() == iplExtension) 305ae0998f1SAdriana Kobylak { 306ae0998f1SAdriana Kobylak // Some elements have an additional extension, ex: .P10.iplTime 307ae0998f1SAdriana Kobylak // Strip off the ipl extension with stem(), then check if there is 308ae0998f1SAdriana Kobylak // an additional extension with extension(). 309ae0998f1SAdriana Kobylak if (!path.stem().extension().empty()) 310ae0998f1SAdriana Kobylak { 311ae0998f1SAdriana Kobylak // Check if the extension matches the extensions for this system 312ae0998f1SAdriana Kobylak if (std::find(extensions.begin(), extensions.end(), 313ae0998f1SAdriana Kobylak path.stem().extension()) == extensions.end()) 314ae0998f1SAdriana Kobylak { 315ae0998f1SAdriana Kobylak continue; 316ae0998f1SAdriana Kobylak } 317ae0998f1SAdriana Kobylak } 318ae0998f1SAdriana Kobylak // Get the element name without extensions by calling stem() twice 319ae0998f1SAdriana Kobylak // since stem() returns the base name if no periods are found. 320ae0998f1SAdriana Kobylak // Therefore both "element.P10" and "element.P10.iplTime" would 321ae0998f1SAdriana Kobylak // become "element". 322ae0998f1SAdriana Kobylak attr[path.stem().stem()] = lid; 323ae0998f1SAdriana Kobylak continue; 324ae0998f1SAdriana Kobylak } 325ae0998f1SAdriana Kobylak 326ae0998f1SAdriana Kobylak // Process all other extensions. The extension should match the list of 327ae0998f1SAdriana Kobylak // supported extensions for this system. Use .insert() to only add 328ae0998f1SAdriana Kobylak // entries that do not exist, so to not overwrite the values that may 329ae0998f1SAdriana Kobylak // had been added that had the ipl extension. 330ae0998f1SAdriana Kobylak if (std::find(extensions.begin(), extensions.end(), path.extension()) != 331ae0998f1SAdriana Kobylak extensions.end()) 332ae0998f1SAdriana Kobylak { 333ae0998f1SAdriana Kobylak attr.insert({path.stem(), lid}); 334ae0998f1SAdriana Kobylak } 335ae0998f1SAdriana Kobylak } 336ae0998f1SAdriana Kobylak for (const auto& a : attr) 337ae0998f1SAdriana Kobylak { 338ae0998f1SAdriana Kobylak // Build the bios attribute string with format: 339ae0998f1SAdriana Kobylak // "element1=lid1,element2=lid2,elementN=lidN," 340ae0998f1SAdriana Kobylak biosAttrStr += a.first + "=" + a.second + ","; 341*5dc5d6ccSAdriana Kobylak 342*5dc5d6ccSAdriana Kobylak // Create symlinks from the hostfw elements to their corresponding 343*5dc5d6ccSAdriana Kobylak // lid files if they don't exist 344*5dc5d6ccSAdriana Kobylak auto elementFilePath = 345*5dc5d6ccSAdriana Kobylak std::filesystem::path("/media/hostfw/running") / a.first; 346*5dc5d6ccSAdriana Kobylak if (!std::filesystem::exists(elementFilePath)) 347*5dc5d6ccSAdriana Kobylak { 348*5dc5d6ccSAdriana Kobylak std::error_code ec; 349*5dc5d6ccSAdriana Kobylak auto lidName = a.second + ".lid"; 350*5dc5d6ccSAdriana Kobylak std::filesystem::create_symlink(lidName, elementFilePath, ec); 351*5dc5d6ccSAdriana Kobylak if (ec) 352*5dc5d6ccSAdriana Kobylak { 353*5dc5d6ccSAdriana Kobylak log<level::ERR>("Error creating symlink", 354*5dc5d6ccSAdriana Kobylak entry("TARGET=%s", lidName.c_str()), 355*5dc5d6ccSAdriana Kobylak entry("LINK=%s", elementFilePath.c_str())); 356*5dc5d6ccSAdriana Kobylak } 357*5dc5d6ccSAdriana Kobylak } 358ae0998f1SAdriana Kobylak } 359ae0998f1SAdriana Kobylak 360ae0998f1SAdriana Kobylak return biosAttrStr; 361ae0998f1SAdriana Kobylak } 362ae0998f1SAdriana Kobylak 363ae0998f1SAdriana Kobylak /** 364ae0998f1SAdriana Kobylak * @brief Set the bios attribute table with details of the host firmware data 365ae0998f1SAdriana Kobylak * for this system. 366ae0998f1SAdriana Kobylak * 367ae0998f1SAdriana Kobylak * @param[in] elementsJsonFilePath - The path to the host firmware json file. 368ae0998f1SAdriana Kobylak * @param[in] extentions - The extensions of the firmware blob files. 369ae0998f1SAdriana Kobylak */ 370ae0998f1SAdriana Kobylak void setBiosAttr(const std::filesystem::path& elementsJsonFilePath, 371ae0998f1SAdriana Kobylak const std::vector<std::string>& extensions) 372ae0998f1SAdriana Kobylak { 373ae0998f1SAdriana Kobylak auto biosAttrStr = getBiosAttrStr(elementsJsonFilePath, extensions); 374ae0998f1SAdriana Kobylak 37556f538caSAdriana Kobylak constexpr auto biosConfigPath = "/xyz/openbmc_project/bios_config/manager"; 37656f538caSAdriana Kobylak constexpr auto biosConfigIntf = "xyz.openbmc_project.BIOSConfig.Manager"; 37756f538caSAdriana Kobylak constexpr auto dbusAttrName = "hb_lid_ids"; 37856f538caSAdriana Kobylak constexpr auto dbusAttrType = 37956f538caSAdriana Kobylak "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String"; 38056f538caSAdriana Kobylak 38156f538caSAdriana Kobylak using PendingAttributesType = std::vector<std::pair< 38256f538caSAdriana Kobylak std::string, std::tuple<std::string, std::variant<std::string>>>>; 38356f538caSAdriana Kobylak PendingAttributesType pendingAttributes; 38456f538caSAdriana Kobylak pendingAttributes.emplace_back(std::make_pair( 38556f538caSAdriana Kobylak dbusAttrName, std::make_tuple(dbusAttrType, biosAttrStr))); 38656f538caSAdriana Kobylak 38756f538caSAdriana Kobylak auto bus = sdbusplus::bus::new_default(); 38856f538caSAdriana Kobylak auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, 38956f538caSAdriana Kobylak MAPPER_INTERFACE, "GetObject"); 39056f538caSAdriana Kobylak method.append(biosConfigPath, std::vector<std::string>({biosConfigIntf})); 39156f538caSAdriana Kobylak std::vector<std::pair<std::string, std::vector<std::string>>> response; 39256f538caSAdriana Kobylak try 39356f538caSAdriana Kobylak { 39456f538caSAdriana Kobylak auto reply = bus.call(method); 39556f538caSAdriana Kobylak reply.read(response); 39656f538caSAdriana Kobylak if (response.empty()) 39756f538caSAdriana Kobylak { 39856f538caSAdriana Kobylak log<level::ERR>("Error reading mapper response", 39956f538caSAdriana Kobylak entry("PATH=%s", biosConfigPath), 40056f538caSAdriana Kobylak entry("INTERFACE=%s", biosConfigIntf)); 40156f538caSAdriana Kobylak return; 40256f538caSAdriana Kobylak } 40356f538caSAdriana Kobylak auto method = bus.new_method_call((response.begin()->first).c_str(), 40456f538caSAdriana Kobylak biosConfigPath, 40556f538caSAdriana Kobylak SYSTEMD_PROPERTY_INTERFACE, "Set"); 40656f538caSAdriana Kobylak method.append(biosConfigIntf, "PendingAttributes", 40756f538caSAdriana Kobylak std::variant<PendingAttributesType>(pendingAttributes)); 40856f538caSAdriana Kobylak bus.call(method); 40956f538caSAdriana Kobylak } 41056f538caSAdriana Kobylak catch (const sdbusplus::exception::SdBusError& e) 41156f538caSAdriana Kobylak { 41256f538caSAdriana Kobylak log<level::ERR>("Error setting the bios attribute", 41356f538caSAdriana Kobylak entry("ERROR=%s", e.what()), 41456f538caSAdriana Kobylak entry("ATTRIBUTE=%s", dbusAttrName)); 41556f538caSAdriana Kobylak return; 41656f538caSAdriana Kobylak } 41756f538caSAdriana Kobylak } 41853a27395SAdriana Kobylak 41953a27395SAdriana Kobylak /** 420099543e4SBrad Bishop * @brief Make callbacks on 421099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem instances. 422099543e4SBrad Bishop * 423099543e4SBrad Bishop * Look for an instance of 424099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem in the provided 425099543e4SBrad Bishop * argument and if found, issue the provided callback. 426099543e4SBrad Bishop * 427099543e4SBrad Bishop * @param[in] interfacesAndProperties the interfaces in which to look for an 428099543e4SBrad Bishop * instance of xyz.openbmc_project.Configuration.IBMCompatibleSystem 429099543e4SBrad Bishop * @param[in] callback the user callback to make if 430099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is found in 431099543e4SBrad Bishop * interfacesAndProperties 432099543e4SBrad Bishop * @return true if interfacesAndProperties contained an instance of 433099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem, false otherwise 434099543e4SBrad Bishop */ 435099543e4SBrad Bishop bool maybeCall(const std::map<std::string, 436099543e4SBrad Bishop std::map<std::string, 437099543e4SBrad Bishop std::variant<std::vector<std::string>>>>& 438099543e4SBrad Bishop interfacesAndProperties, 439099543e4SBrad Bishop const MaybeCallCallbackType& callback) 440099543e4SBrad Bishop { 441099543e4SBrad Bishop using namespace std::string_literals; 442099543e4SBrad Bishop 443099543e4SBrad Bishop static const auto interfaceName = 444099543e4SBrad Bishop "xyz.openbmc_project.Configuration.IBMCompatibleSystem"s; 445099543e4SBrad Bishop auto interfaceIterator = interfacesAndProperties.find(interfaceName); 446099543e4SBrad Bishop if (interfaceIterator == interfacesAndProperties.cend()) 447099543e4SBrad Bishop { 448099543e4SBrad Bishop // IBMCompatibleSystem interface not found, so instruct the caller to 449099543e4SBrad Bishop // keep waiting or try again later. 450099543e4SBrad Bishop return false; 451099543e4SBrad Bishop } 452099543e4SBrad Bishop auto propertyIterator = interfaceIterator->second.find("Names"s); 453099543e4SBrad Bishop if (propertyIterator == interfaceIterator->second.cend()) 454099543e4SBrad Bishop { 455099543e4SBrad Bishop // The interface exists but the property doesn't. This is a bug in the 456099543e4SBrad Bishop // IBMCompatibleSystem implementation. The caller should not try 457099543e4SBrad Bishop // again. 458099543e4SBrad Bishop std::cerr << "Names property not implemented on " << interfaceName 459099543e4SBrad Bishop << "\n"; 460099543e4SBrad Bishop return true; 461099543e4SBrad Bishop } 462099543e4SBrad Bishop 463099543e4SBrad Bishop const auto& ibmCompatibleSystem = 464099543e4SBrad Bishop std::get<std::vector<std::string>>(propertyIterator->second); 465099543e4SBrad Bishop if (callback) 466099543e4SBrad Bishop { 467099543e4SBrad Bishop callback(ibmCompatibleSystem); 468099543e4SBrad Bishop } 469099543e4SBrad Bishop 470099543e4SBrad Bishop // IBMCompatibleSystem found and callback issued. 471099543e4SBrad Bishop return true; 472099543e4SBrad Bishop } 473099543e4SBrad Bishop 474099543e4SBrad Bishop /** 475099543e4SBrad Bishop * @brief Make callbacks on 476099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem instances. 477099543e4SBrad Bishop * 478099543e4SBrad Bishop * Look for an instance of 479099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem in the provided 480099543e4SBrad Bishop * argument and if found, issue the provided callback. 481099543e4SBrad Bishop * 482099543e4SBrad Bishop * @param[in] message the DBus message in which to look for an instance of 483099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem 484099543e4SBrad Bishop * @param[in] callback the user callback to make if 485099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is found in 486099543e4SBrad Bishop * message 487099543e4SBrad Bishop * @return true if message contained an instance of 488099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem, false otherwise 489099543e4SBrad Bishop */ 490099543e4SBrad Bishop bool maybeCallMessage(sdbusplus::message::message& message, 491099543e4SBrad Bishop const MaybeCallCallbackType& callback) 492099543e4SBrad Bishop { 493099543e4SBrad Bishop std::map<std::string, 494099543e4SBrad Bishop std::map<std::string, std::variant<std::vector<std::string>>>> 495099543e4SBrad Bishop interfacesAndProperties; 496099543e4SBrad Bishop sdbusplus::message::object_path _; 497099543e4SBrad Bishop message.read(_, interfacesAndProperties); 498099543e4SBrad Bishop return maybeCall(interfacesAndProperties, callback); 499099543e4SBrad Bishop } 500099543e4SBrad Bishop 501099543e4SBrad Bishop /** 502099543e4SBrad Bishop * @brief Determine system support for host firmware well-known names. 503099543e4SBrad Bishop * 504099543e4SBrad Bishop * Using the provided extensionMap and 505099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem, determine if 506099543e4SBrad Bishop * well-known names for host firmare blob files are necessary and if so, create 507099543e4SBrad Bishop * them. 508099543e4SBrad Bishop * 509099543e4SBrad Bishop * @param[in] extensionMap a map of 510099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to host firmware blob 511099543e4SBrad Bishop * file extensions. 512099543e4SBrad Bishop * @param[in] hostFirmwareDirectory The directory in which findLinks should 513099543e4SBrad Bishop * look for host firmware blob files that need well-known names. 514099543e4SBrad Bishop * @param[in] ibmCompatibleSystem The names property of an instance of 515099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem 516099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 517099543e4SBrad Bishop */ 518099543e4SBrad Bishop void maybeMakeLinks( 519099543e4SBrad Bishop const std::map<std::string, std::vector<std::string>>& extensionMap, 520099543e4SBrad Bishop const std::filesystem::path& hostFirmwareDirectory, 521099543e4SBrad Bishop const std::vector<std::string>& ibmCompatibleSystem, 522099543e4SBrad Bishop const ErrorCallbackType& errorCallback) 523099543e4SBrad Bishop { 524099543e4SBrad Bishop std::vector<std::string> extensions; 525099543e4SBrad Bishop if (getExtensionsForIbmCompatibleSystem(extensionMap, ibmCompatibleSystem, 526099543e4SBrad Bishop extensions)) 527099543e4SBrad Bishop { 528099543e4SBrad Bishop findLinks(hostFirmwareDirectory, extensions, errorCallback, writeLink); 529099543e4SBrad Bishop } 530099543e4SBrad Bishop } 531099543e4SBrad Bishop 532099543e4SBrad Bishop /** 53353a27395SAdriana Kobylak * @brief Determine system support for updating the bios attribute table. 53453a27395SAdriana Kobylak * 53553a27395SAdriana Kobylak * Using the provided extensionMap and 53653a27395SAdriana Kobylak * xyz.openbmc_project.Configuration.IBMCompatibleSystem, determine if the bios 53753a27395SAdriana Kobylak * attribute table needs to be updated. 53853a27395SAdriana Kobylak * 53953a27395SAdriana Kobylak * @param[in] extensionMap a map of 54053a27395SAdriana Kobylak * xyz.openbmc_project.Configuration.IBMCompatibleSystem to host firmware blob 54153a27395SAdriana Kobylak * file extensions. 542ae0998f1SAdriana Kobylak * @param[in] elementsJsonFilePath The file path to the json file 54353a27395SAdriana Kobylak * @param[in] ibmCompatibleSystem The names property of an instance of 54453a27395SAdriana Kobylak * xyz.openbmc_project.Configuration.IBMCompatibleSystem 54553a27395SAdriana Kobylak */ 54653a27395SAdriana Kobylak void maybeSetBiosAttr( 54753a27395SAdriana Kobylak const std::map<std::string, std::vector<std::string>>& extensionMap, 548ae0998f1SAdriana Kobylak const std::filesystem::path& elementsJsonFilePath, 54953a27395SAdriana Kobylak const std::vector<std::string>& ibmCompatibleSystem) 55053a27395SAdriana Kobylak { 55153a27395SAdriana Kobylak std::vector<std::string> extensions; 55253a27395SAdriana Kobylak if (getExtensionsForIbmCompatibleSystem(extensionMap, ibmCompatibleSystem, 55353a27395SAdriana Kobylak extensions)) 55453a27395SAdriana Kobylak { 555ae0998f1SAdriana Kobylak setBiosAttr(elementsJsonFilePath, extensions); 55653a27395SAdriana Kobylak } 55753a27395SAdriana Kobylak } 55853a27395SAdriana Kobylak 55953a27395SAdriana Kobylak /** 560099543e4SBrad Bishop * @brief process host firmware 561099543e4SBrad Bishop * 562099543e4SBrad Bishop * Allocate a callback context and register for DBus.ObjectManager Interfaces 563099543e4SBrad Bishop * added signals from entity manager. 564099543e4SBrad Bishop * 565099543e4SBrad Bishop * Check the current entity manager object tree for a 566099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem instance (entity 567099543e4SBrad Bishop * manager will be dbus activated if it is not running). If one is found, 568099543e4SBrad Bishop * determine if symlinks need to be created and create them. Instruct the 569099543e4SBrad Bishop * program event loop to exit. 570099543e4SBrad Bishop * 571099543e4SBrad Bishop * If no instance of xyz.openbmc_project.Configuration.IBMCompatibleSystem is 572099543e4SBrad Bishop * found return the callback context to main, where the program will sleep 573099543e4SBrad Bishop * until the callback is invoked one or more times and instructs the program 574099543e4SBrad Bishop * event loop to exit when 575099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is added. 576099543e4SBrad Bishop * 577099543e4SBrad Bishop * @param[in] bus a DBus client connection 578099543e4SBrad Bishop * @param[in] extensionMap a map of 579099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem to host firmware blob 580099543e4SBrad Bishop * file extensions. 581099543e4SBrad Bishop * @param[in] hostFirmwareDirectory The directory in which processHostFirmware 582099543e4SBrad Bishop * should look for blob files. 583099543e4SBrad Bishop * @param[in] errorCallback A callback made in the event of filesystem errors. 584099543e4SBrad Bishop * @param[in] loop a program event loop 585099543e4SBrad Bishop * @return nullptr if an instance of 586099543e4SBrad Bishop * xyz.openbmc_project.Configuration.IBMCompatibleSystem is found, otherwise a 587099543e4SBrad Bishop * pointer to an sdbusplus match object. 588099543e4SBrad Bishop */ 589099543e4SBrad Bishop std::shared_ptr<void> processHostFirmware( 590099543e4SBrad Bishop sdbusplus::bus::bus& bus, 591099543e4SBrad Bishop std::map<std::string, std::vector<std::string>> extensionMap, 592099543e4SBrad Bishop std::filesystem::path hostFirmwareDirectory, 593099543e4SBrad Bishop ErrorCallbackType errorCallback, sdeventplus::Event& loop) 594099543e4SBrad Bishop { 595099543e4SBrad Bishop // ownership of extensionMap, hostFirmwareDirectory and errorCallback can't 596099543e4SBrad Bishop // be transfered to the match callback because they are needed in the non 597099543e4SBrad Bishop // async part of this function below, so they need to be moved to the heap. 598099543e4SBrad Bishop auto pExtensionMap = 599099543e4SBrad Bishop std::make_shared<decltype(extensionMap)>(std::move(extensionMap)); 600099543e4SBrad Bishop auto pHostFirmwareDirectory = 601099543e4SBrad Bishop std::make_shared<decltype(hostFirmwareDirectory)>( 602099543e4SBrad Bishop std::move(hostFirmwareDirectory)); 603099543e4SBrad Bishop auto pErrorCallback = 604099543e4SBrad Bishop std::make_shared<decltype(errorCallback)>(std::move(errorCallback)); 605099543e4SBrad Bishop 606099543e4SBrad Bishop // register for a callback in case the IBMCompatibleSystem interface has 607099543e4SBrad Bishop // not yet been published by entity manager. 608099543e4SBrad Bishop auto interfacesAddedMatch = std::make_shared<sdbusplus::bus::match::match>( 609099543e4SBrad Bishop bus, 610099543e4SBrad Bishop sdbusplus::bus::match::rules::interfacesAdded() + 611099543e4SBrad Bishop sdbusplus::bus::match::rules::sender( 612099543e4SBrad Bishop "xyz.openbmc_project.EntityManager"), 613099543e4SBrad Bishop [pExtensionMap, pHostFirmwareDirectory, pErrorCallback, 614099543e4SBrad Bishop &loop](auto& message) { 615099543e4SBrad Bishop // bind the extension map, host firmware directory, and error 616099543e4SBrad Bishop // callback to the maybeMakeLinks function. 617099543e4SBrad Bishop auto maybeMakeLinksWithArgsBound = 618099543e4SBrad Bishop std::bind(maybeMakeLinks, std::cref(*pExtensionMap), 619099543e4SBrad Bishop std::cref(*pHostFirmwareDirectory), 620099543e4SBrad Bishop std::placeholders::_1, std::cref(*pErrorCallback)); 621099543e4SBrad Bishop 622099543e4SBrad Bishop // if the InterfacesAdded message contains an an instance of 623099543e4SBrad Bishop // xyz.openbmc_project.Configuration.IBMCompatibleSystem, check to 624099543e4SBrad Bishop // see if links are necessary on this system and if so, create 625099543e4SBrad Bishop // them. 626099543e4SBrad Bishop if (maybeCallMessage(message, maybeMakeLinksWithArgsBound)) 627099543e4SBrad Bishop { 628099543e4SBrad Bishop // The IBMCompatibleSystem interface was found and the links 629099543e4SBrad Bishop // were created if applicable. Instruct the event loop / 630099543e4SBrad Bishop // subcommand to exit. 631099543e4SBrad Bishop loop.exit(0); 632099543e4SBrad Bishop } 633099543e4SBrad Bishop }); 634099543e4SBrad Bishop 635099543e4SBrad Bishop // now that we'll get a callback in the event of an InterfacesAdded signal 636099543e4SBrad Bishop // (potentially containing 637099543e4SBrad Bishop // xyz.openbmc_project.Configuration.IBMCompatibleSystem), activate entity 638099543e4SBrad Bishop // manager if it isn't running and enumerate its objects 639099543e4SBrad Bishop auto getManagedObjects = bus.new_method_call( 640099543e4SBrad Bishop "xyz.openbmc_project.EntityManager", "/", 641099543e4SBrad Bishop "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 642099543e4SBrad Bishop std::map<std::string, 643099543e4SBrad Bishop std::map<std::string, std::variant<std::vector<std::string>>>> 644099543e4SBrad Bishop interfacesAndProperties; 645099543e4SBrad Bishop std::map<sdbusplus::message::object_path, decltype(interfacesAndProperties)> 646099543e4SBrad Bishop objects; 647c79fa915SAdriana Kobylak try 648c79fa915SAdriana Kobylak { 649c79fa915SAdriana Kobylak auto reply = bus.call(getManagedObjects); 650099543e4SBrad Bishop reply.read(objects); 651c79fa915SAdriana Kobylak } 652c79fa915SAdriana Kobylak catch (const sdbusplus::exception::SdBusError& e) 653c79fa915SAdriana Kobylak { 654c79fa915SAdriana Kobylak // Error querying the EntityManager interface. Return the match to have 655c79fa915SAdriana Kobylak // the callback run if/when the interface appears in D-Bus. 656c79fa915SAdriana Kobylak return interfacesAddedMatch; 657c79fa915SAdriana Kobylak } 658099543e4SBrad Bishop 659099543e4SBrad Bishop // bind the extension map, host firmware directory, and error callback to 660099543e4SBrad Bishop // the maybeMakeLinks function. 661099543e4SBrad Bishop auto maybeMakeLinksWithArgsBound = 662099543e4SBrad Bishop std::bind(maybeMakeLinks, std::cref(*pExtensionMap), 663099543e4SBrad Bishop std::cref(*pHostFirmwareDirectory), std::placeholders::_1, 664099543e4SBrad Bishop std::cref(*pErrorCallback)); 665099543e4SBrad Bishop 666099543e4SBrad Bishop for (const auto& pair : objects) 667099543e4SBrad Bishop { 668099543e4SBrad Bishop std::tie(std::ignore, interfacesAndProperties) = pair; 669099543e4SBrad Bishop // if interfacesAndProperties contains an an instance of 670099543e4SBrad Bishop // xyz.openbmc_project.Configuration.IBMCompatibleSystem, check to see 671099543e4SBrad Bishop // if links are necessary on this system and if so, create them 672099543e4SBrad Bishop if (maybeCall(interfacesAndProperties, maybeMakeLinksWithArgsBound)) 673099543e4SBrad Bishop { 674099543e4SBrad Bishop // The IBMCompatibleSystem interface is already on the bus and the 675099543e4SBrad Bishop // links were created if applicable. Instruct the event loop to 676099543e4SBrad Bishop // exit. 677099543e4SBrad Bishop loop.exit(0); 678099543e4SBrad Bishop // The match object isn't needed anymore, so destroy it on return. 679099543e4SBrad Bishop return nullptr; 680099543e4SBrad Bishop } 681099543e4SBrad Bishop } 682099543e4SBrad Bishop 683099543e4SBrad Bishop // The IBMCompatibleSystem interface has not yet been published. Move 684099543e4SBrad Bishop // ownership of the match callback to the caller. 685099543e4SBrad Bishop return interfacesAddedMatch; 686099543e4SBrad Bishop } 68753a27395SAdriana Kobylak 68853a27395SAdriana Kobylak /** 68953a27395SAdriana Kobylak * @brief Update the Bios Attribute Table 69053a27395SAdriana Kobylak * 69153a27395SAdriana Kobylak * If an instance of xyz.openbmc_project.Configuration.IBMCompatibleSystem is 69253a27395SAdriana Kobylak * found, update the Bios Attribute Table with the appropriate host firmware 69353a27395SAdriana Kobylak * data. 69453a27395SAdriana Kobylak * 69553a27395SAdriana Kobylak * @param[in] bus - D-Bus client connection. 69653a27395SAdriana Kobylak * @param[in] extensionMap - Map of IBMCompatibleSystem names and host firmware 69753a27395SAdriana Kobylak * file extensions. 698ae0998f1SAdriana Kobylak * @param[in] elementsJsonFilePath - The Path to the json file 69953a27395SAdriana Kobylak * @param[in] loop - Program event loop. 70053a27395SAdriana Kobylak * @return nullptr 70153a27395SAdriana Kobylak */ 702ebf67bf7SAdriana Kobylak std::vector<std::shared_ptr<void>> updateBiosAttrTable( 70353a27395SAdriana Kobylak sdbusplus::bus::bus& bus, 70453a27395SAdriana Kobylak std::map<std::string, std::vector<std::string>> extensionMap, 705ae0998f1SAdriana Kobylak std::filesystem::path elementsJsonFilePath, sdeventplus::Event& loop) 70653a27395SAdriana Kobylak { 707d0379ea5SAdriana Kobylak constexpr auto pldmPath = "/xyz/openbmc_project/pldm"; 708ebf67bf7SAdriana Kobylak constexpr auto entityManagerServiceName = 709ebf67bf7SAdriana Kobylak "xyz.openbmc_project.EntityManager"; 710d0379ea5SAdriana Kobylak 71153a27395SAdriana Kobylak auto pExtensionMap = 71253a27395SAdriana Kobylak std::make_shared<decltype(extensionMap)>(std::move(extensionMap)); 713ae0998f1SAdriana Kobylak auto pElementsJsonFilePath = 714ae0998f1SAdriana Kobylak std::make_shared<decltype(elementsJsonFilePath)>( 715ae0998f1SAdriana Kobylak std::move(elementsJsonFilePath)); 71653a27395SAdriana Kobylak 717d0379ea5SAdriana Kobylak // Entity Manager is needed to get the list of supported extensions. Add a 718d0379ea5SAdriana Kobylak // match to monitor interfaces added in case it's not running yet. 719d0379ea5SAdriana Kobylak auto maybeSetAttrWithArgsBound = 720d0379ea5SAdriana Kobylak std::bind(maybeSetBiosAttr, std::cref(*pExtensionMap), 721d0379ea5SAdriana Kobylak std::cref(*pElementsJsonFilePath), std::placeholders::_1); 722d0379ea5SAdriana Kobylak 723ebf67bf7SAdriana Kobylak std::vector<std::shared_ptr<void>> matches; 724ebf67bf7SAdriana Kobylak matches.emplace_back(std::make_shared<sdbusplus::bus::match::match>( 725d0379ea5SAdriana Kobylak bus, 726d0379ea5SAdriana Kobylak sdbusplus::bus::match::rules::interfacesAdded() + 727d0379ea5SAdriana Kobylak sdbusplus::bus::match::rules::sender( 728d0379ea5SAdriana Kobylak "xyz.openbmc_project.EntityManager"), 729d0379ea5SAdriana Kobylak [pldmPath, pExtensionMap, pElementsJsonFilePath, 730d0379ea5SAdriana Kobylak maybeSetAttrWithArgsBound, &loop](auto& message) { 731d0379ea5SAdriana Kobylak auto bus = sdbusplus::bus::new_default(); 732fd4a6088SAdriana Kobylak auto pldmObject = getObject(bus, pldmPath); 733fd4a6088SAdriana Kobylak if (pldmObject.empty()) 734fd4a6088SAdriana Kobylak { 735d0379ea5SAdriana Kobylak return; 736d0379ea5SAdriana Kobylak } 737d0379ea5SAdriana Kobylak if (maybeCallMessage(message, maybeSetAttrWithArgsBound)) 738d0379ea5SAdriana Kobylak { 739fd4a6088SAdriana Kobylak loop.exit(0); 740d0379ea5SAdriana Kobylak } 741ebf67bf7SAdriana Kobylak })); 742ebf67bf7SAdriana Kobylak matches.emplace_back(std::make_shared<sdbusplus::bus::match::match>( 743ebf67bf7SAdriana Kobylak bus, 744ebf67bf7SAdriana Kobylak sdbusplus::bus::match::rules::nameOwnerChanged() + 745ebf67bf7SAdriana Kobylak sdbusplus::bus::match::rules::arg0namespace( 746ebf67bf7SAdriana Kobylak "xyz.openbmc_project.PLDM"), 747ebf67bf7SAdriana Kobylak [pExtensionMap, pElementsJsonFilePath, maybeSetAttrWithArgsBound, 748ebf67bf7SAdriana Kobylak &loop](auto& message) { 749ebf67bf7SAdriana Kobylak std::string name; 750ebf67bf7SAdriana Kobylak std::string oldOwner; 751ebf67bf7SAdriana Kobylak std::string newOwner; 752ebf67bf7SAdriana Kobylak message.read(name, oldOwner, newOwner); 753ebf67bf7SAdriana Kobylak 754ebf67bf7SAdriana Kobylak if (newOwner.empty()) 755ebf67bf7SAdriana Kobylak { 756ebf67bf7SAdriana Kobylak return; 757ebf67bf7SAdriana Kobylak } 758ebf67bf7SAdriana Kobylak 759ebf67bf7SAdriana Kobylak auto bus = sdbusplus::bus::new_default(); 760ebf67bf7SAdriana Kobylak InterfacesPropertiesMap interfacesAndProperties; 761ebf67bf7SAdriana Kobylak auto objects = getManagedObjects(bus, entityManagerServiceName); 762ebf67bf7SAdriana Kobylak for (const auto& pair : objects) 763ebf67bf7SAdriana Kobylak { 764ebf67bf7SAdriana Kobylak std::tie(std::ignore, interfacesAndProperties) = pair; 765ebf67bf7SAdriana Kobylak if (maybeCall(interfacesAndProperties, 766ebf67bf7SAdriana Kobylak maybeSetAttrWithArgsBound)) 767ebf67bf7SAdriana Kobylak { 768ebf67bf7SAdriana Kobylak loop.exit(0); 769ebf67bf7SAdriana Kobylak } 770ebf67bf7SAdriana Kobylak } 771ebf67bf7SAdriana Kobylak })); 772d0379ea5SAdriana Kobylak 773d0379ea5SAdriana Kobylak // The BIOS attribute table can only be updated if PLDM is running because 774d0379ea5SAdriana Kobylak // PLDM is the one that exposes this property. Return if it's not running. 775d0379ea5SAdriana Kobylak auto pldmObject = getObject(bus, pldmPath); 776d0379ea5SAdriana Kobylak if (pldmObject.empty()) 777d0379ea5SAdriana Kobylak { 778ebf67bf7SAdriana Kobylak return matches; 779fd4a6088SAdriana Kobylak } 780fd4a6088SAdriana Kobylak 781ebf67bf7SAdriana Kobylak InterfacesPropertiesMap interfacesAndProperties; 782ebf67bf7SAdriana Kobylak auto objects = getManagedObjects(bus, entityManagerServiceName); 78353a27395SAdriana Kobylak for (const auto& pair : objects) 78453a27395SAdriana Kobylak { 78553a27395SAdriana Kobylak std::tie(std::ignore, interfacesAndProperties) = pair; 78653a27395SAdriana Kobylak if (maybeCall(interfacesAndProperties, maybeSetAttrWithArgsBound)) 78753a27395SAdriana Kobylak { 788d0379ea5SAdriana Kobylak loop.exit(0); 789ebf67bf7SAdriana Kobylak return {}; 79053a27395SAdriana Kobylak } 79153a27395SAdriana Kobylak } 79253a27395SAdriana Kobylak 793ebf67bf7SAdriana Kobylak return matches; 79453a27395SAdriana Kobylak } 79553a27395SAdriana Kobylak 796099543e4SBrad Bishop } // namespace process_hostfirmware 797099543e4SBrad Bishop } // namespace functions 798