#include "config.h" #include "fw_update_watch.hpp" #include "common_utils.hpp" #include "create_pel.hpp" #include "pdbg_utils.hpp" #include #include #include #include #include #include #include #include namespace openpower { namespace phal { namespace fwupdate { using namespace phosphor::logging; namespace fs = std::filesystem; using Message = std::string; using Attributes = std::variant; using PropertyName = std::string; using PropertyMap = std::map; using InterfaceName = std::string; using InterfaceMap = std::map; void Watch::fwIntfAddedCallback(sdbusplus::message_t& msg) { // DBusInterfaceAdded interfaces; sdbusplus::message::object_path objectPath; InterfaceMap interfaceMap; try { msg.read(objectPath, interfaceMap); } catch (const sdbusplus::exception_t& e) { log(std::format("Failed to parse software add signal" "Exception [{}] REPLY_SIG [{}]", e.what(), msg.get_signature()) .c_str()); return; } auto iter = interfaceMap.find("xyz.openbmc_project.Software.Activation"); if (iter == interfaceMap.end()) { // Skip not related Software Activation return; } auto attr = iter->second.find("Activation"); if (attr == iter->second.end()) { // Skip not related to Activation property. return; } auto& imageProperty = std::get(attr->second); if (imageProperty.empty()) { // Skip, no image property return; } if (imageProperty == "xyz.openbmc_project.Software.Activation.Activations.Ready" && !isSoftwareUpdateInProgress()) { log("Software path interface add signal received"); // Set status to code update in progress. // Interface added signal triggered multiple times in code update path, // it's due to additional interfaces added by the software manager app // after the version interface is created. // Device tree data collection is required only for the first trigger setSoftwareUpdateProgress(true); try { // Colect device tree data openpower::phal::fwupdate::exportDevtree(); } catch (const fs::filesystem_error& e) { log( std::format("Filesystem error reported Error:({})", e.what()) .c_str()); throw std::runtime_error(e.what()); } log("Successfully exported devtree attribute data"); } return; } void exportDevtree() { constexpr auto ERROR_DEVTREE_BACKUP = "org.open_power.PHAL.Error.devtreeBackup"; // Check devtree export filter file is present auto path = fs::path(DEVTREE_EXPORT_FILTER_FILE); if (!fs::exists(path)) { log( std::format("devtree export filter file is not available: ({})", DEVTREE_EXPORT_FILTER_FILE) .c_str()); openpower::pel::createPEL(ERROR_DEVTREE_BACKUP); return; } // delete export data file if present auto expFile = fs::path(DEVTREE_EXP_FILE); if (fs::exists(expFile)) { fs::remove_all(expFile); } else { // create directory fs::create_directory(expFile.parent_path()); } // Update PDBG_DTB value openpower::phal::setDevtreeEnv(); // Update PDATA_INFODB value openpower::phal::setPdataInfoDBEnv(); int status = 0; pid_t pid = fork(); if (pid == 0) { std::string cmd("/usr/bin/attributes "); cmd += "export "; cmd += DEVTREE_EXPORT_FILTER_FILE; cmd += " > "; cmd += DEVTREE_EXP_FILE; execl("/bin/sh", "sh", "-c", cmd.c_str(), 0); auto error = errno; log(std::format("Error occurred during attributes function " "execution, errno({})", error) .c_str()); // Creating PEL at one place. } else if (pid > 0) { waitpid(pid, &status, 0); if (WEXITSTATUS(status)) { log("Failed to collect attribute export data"); openpower::pel::createPEL(ERROR_DEVTREE_BACKUP); } } else { log("exportDevtree fork() failed"); std::runtime_error("exportDevtree fork() failed"); } } } // namespace fwupdate } // namespace phal } // namespace openpower