13840547dSJayanth Othayoth #include "config.h" 23840547dSJayanth Othayoth 313c57ad8SJayanth Othayoth #include "fw_update_watch.hpp" 413c57ad8SJayanth Othayoth 53840547dSJayanth Othayoth #include "common_utils.hpp" 63840547dSJayanth Othayoth #include "create_pel.hpp" 73840547dSJayanth Othayoth #include "pdbg_utils.hpp" 813c57ad8SJayanth Othayoth 93840547dSJayanth Othayoth #include <fmt/format.h> 103840547dSJayanth Othayoth #include <sys/stat.h> 113840547dSJayanth Othayoth #include <sys/wait.h> 123840547dSJayanth Othayoth #include <unistd.h> 133840547dSJayanth Othayoth 143840547dSJayanth Othayoth #include <phosphor-logging/elog-errors.hpp> 1513c57ad8SJayanth Othayoth #include <phosphor-logging/elog.hpp> 1613c57ad8SJayanth Othayoth #include <sdbusplus/exception.hpp> 1713c57ad8SJayanth Othayoth 183840547dSJayanth Othayoth #include <filesystem> 193840547dSJayanth Othayoth 2013c57ad8SJayanth Othayoth namespace openpower 2113c57ad8SJayanth Othayoth { 2213c57ad8SJayanth Othayoth namespace phal 2313c57ad8SJayanth Othayoth { 2413c57ad8SJayanth Othayoth namespace fwupdate 2513c57ad8SJayanth Othayoth { 2613c57ad8SJayanth Othayoth using namespace phosphor::logging; 273840547dSJayanth Othayoth namespace fs = std::filesystem; 283840547dSJayanth Othayoth 2913c57ad8SJayanth Othayoth using Message = std::string; 3013c57ad8SJayanth Othayoth using Attributes = std::variant<Message>; 3113c57ad8SJayanth Othayoth using PropertyName = std::string; 3213c57ad8SJayanth Othayoth using PropertyMap = std::map<PropertyName, Attributes>; 3313c57ad8SJayanth Othayoth using InterfaceName = std::string; 3413c57ad8SJayanth Othayoth using InterfaceMap = std::map<InterfaceName, PropertyMap>; 3513c57ad8SJayanth Othayoth 3613c57ad8SJayanth Othayoth void Watch::fwIntfAddedCallback(sdbusplus::message::message& msg) 3713c57ad8SJayanth Othayoth { 3813c57ad8SJayanth Othayoth // DBusInterfaceAdded interfaces; 3913c57ad8SJayanth Othayoth sdbusplus::message::object_path objectPath; 4013c57ad8SJayanth Othayoth InterfaceMap interfaceMap; 4113c57ad8SJayanth Othayoth 4213c57ad8SJayanth Othayoth try 4313c57ad8SJayanth Othayoth { 4413c57ad8SJayanth Othayoth msg.read(objectPath, interfaceMap); 4513c57ad8SJayanth Othayoth } 46*2246cca0SPatrick Williams catch (const sdbusplus::exception::exception& e) 4713c57ad8SJayanth Othayoth { 4813c57ad8SJayanth Othayoth log<level::ERR>(fmt::format("Failed to parse software add signal" 4913c57ad8SJayanth Othayoth "Exception [{}] REPLY_SIG [{}]", 5013c57ad8SJayanth Othayoth e.what(), msg.get_signature()) 5113c57ad8SJayanth Othayoth .c_str()); 5213c57ad8SJayanth Othayoth return; 5313c57ad8SJayanth Othayoth } 5413c57ad8SJayanth Othayoth 5513c57ad8SJayanth Othayoth auto iter = interfaceMap.find("xyz.openbmc_project.Software.Activation"); 5613c57ad8SJayanth Othayoth if (iter == interfaceMap.end()) 5713c57ad8SJayanth Othayoth { 5813c57ad8SJayanth Othayoth // Skip not related Software Activation 5913c57ad8SJayanth Othayoth return; 6013c57ad8SJayanth Othayoth } 6113c57ad8SJayanth Othayoth 6213c57ad8SJayanth Othayoth auto attr = iter->second.find("Activation"); 6313c57ad8SJayanth Othayoth if (attr == iter->second.end()) 6413c57ad8SJayanth Othayoth { 6513c57ad8SJayanth Othayoth // Skip not related to Activation property. 6613c57ad8SJayanth Othayoth return; 6713c57ad8SJayanth Othayoth } 6813c57ad8SJayanth Othayoth 6913c57ad8SJayanth Othayoth auto& imageProperty = std::get<InterfaceName>(attr->second); 7013c57ad8SJayanth Othayoth if (imageProperty.empty()) 7113c57ad8SJayanth Othayoth { 7213c57ad8SJayanth Othayoth // Skip, no image property 7313c57ad8SJayanth Othayoth return; 7413c57ad8SJayanth Othayoth } 7513c57ad8SJayanth Othayoth 7613c57ad8SJayanth Othayoth if (imageProperty == 7713c57ad8SJayanth Othayoth "xyz.openbmc_project.Software.Activation.Activations.Ready" && 7813c57ad8SJayanth Othayoth !isSoftwareUpdateInProgress()) 7913c57ad8SJayanth Othayoth { 8013c57ad8SJayanth Othayoth log<level::INFO>("Software path interface add signal received"); 8113c57ad8SJayanth Othayoth 8213c57ad8SJayanth Othayoth // Set status to code update in progress. 8313c57ad8SJayanth Othayoth // Interface added signal triggered multiple times in code update path, 8413c57ad8SJayanth Othayoth // it's due to additional interfaces added by the software manager app 8513c57ad8SJayanth Othayoth // after the version interface is created. 8613c57ad8SJayanth Othayoth // Device tree data collection is required only for the first trigger 8713c57ad8SJayanth Othayoth setSoftwareUpdateProgress(true); 8813c57ad8SJayanth Othayoth 893840547dSJayanth Othayoth try 903840547dSJayanth Othayoth { 9113c57ad8SJayanth Othayoth // Colect device tree data 9213c57ad8SJayanth Othayoth openpower::phal::fwupdate::exportDevtree(); 9313c57ad8SJayanth Othayoth } 943840547dSJayanth Othayoth catch (fs::filesystem_error& e) 953840547dSJayanth Othayoth { 963840547dSJayanth Othayoth log<level::ERR>( 973840547dSJayanth Othayoth fmt::format("Filesystem error reported Error:({})", e.what()) 983840547dSJayanth Othayoth .c_str()); 993840547dSJayanth Othayoth throw std::runtime_error(e.what()); 1003840547dSJayanth Othayoth } 1013840547dSJayanth Othayoth 1023840547dSJayanth Othayoth log<level::INFO>("Successfully exported devtree attribute data"); 1033840547dSJayanth Othayoth } 10413c57ad8SJayanth Othayoth 10513c57ad8SJayanth Othayoth return; 10613c57ad8SJayanth Othayoth } 10713c57ad8SJayanth Othayoth 10813c57ad8SJayanth Othayoth void exportDevtree() 1093840547dSJayanth Othayoth { 1103840547dSJayanth Othayoth constexpr auto ERROR_DEVTREE_BACKUP = 1113840547dSJayanth Othayoth "org.open_power.PHAL.Error.devtreeBackup"; 1123840547dSJayanth Othayoth 1133840547dSJayanth Othayoth // Check devtree export filter file is present 1143840547dSJayanth Othayoth auto path = fs::path(DEVTREE_EXPORT_FILTER_FILE); 1153840547dSJayanth Othayoth if (!fs::exists(path)) 1163840547dSJayanth Othayoth { 1173840547dSJayanth Othayoth log<level::ERR>( 1183840547dSJayanth Othayoth fmt::format("devtree export filter file is not available: ({})", 1193840547dSJayanth Othayoth DEVTREE_EXPORT_FILTER_FILE) 1203840547dSJayanth Othayoth .c_str()); 1213840547dSJayanth Othayoth openpower::pel::createPEL(ERROR_DEVTREE_BACKUP); 1223840547dSJayanth Othayoth return; 1233840547dSJayanth Othayoth } 1243840547dSJayanth Othayoth 1253840547dSJayanth Othayoth // delete export data file if present 1263840547dSJayanth Othayoth auto expFile = fs::path(DEVTREE_EXP_FILE); 1273840547dSJayanth Othayoth if (fs::exists(expFile)) 1283840547dSJayanth Othayoth { 1293840547dSJayanth Othayoth fs::remove_all(expFile); 1303840547dSJayanth Othayoth } 1313840547dSJayanth Othayoth else 1323840547dSJayanth Othayoth { 1333840547dSJayanth Othayoth // create directory 1343840547dSJayanth Othayoth fs::create_directory(expFile.parent_path()); 1353840547dSJayanth Othayoth } 1363840547dSJayanth Othayoth 1373840547dSJayanth Othayoth // Update PDBG_DTB value 1383840547dSJayanth Othayoth openpower::phal::setDevtreeEnv(); 1393840547dSJayanth Othayoth 1403840547dSJayanth Othayoth int status = 0; 1413840547dSJayanth Othayoth pid_t pid = fork(); 1423840547dSJayanth Othayoth if (pid == 0) 1433840547dSJayanth Othayoth { 1443840547dSJayanth Othayoth std::string cmd("/usr/bin/attributes "); 1453840547dSJayanth Othayoth cmd += "export "; 1463840547dSJayanth Othayoth cmd += DEVTREE_EXPORT_FILTER_FILE; 1473840547dSJayanth Othayoth cmd += " > "; 1483840547dSJayanth Othayoth cmd += DEVTREE_EXP_FILE; 1493840547dSJayanth Othayoth execl("/bin/sh", "sh", "-c", cmd.c_str(), 0); 1503840547dSJayanth Othayoth 1513840547dSJayanth Othayoth auto error = errno; 1523840547dSJayanth Othayoth log<level::ERR>(fmt::format("Error occurred during attributes function " 1533840547dSJayanth Othayoth "execution, errno({})", 1543840547dSJayanth Othayoth error) 1553840547dSJayanth Othayoth .c_str()); 1563840547dSJayanth Othayoth // Creating PEL at one place. 1573840547dSJayanth Othayoth } 1583840547dSJayanth Othayoth else if (pid > 0) 1593840547dSJayanth Othayoth { 1603840547dSJayanth Othayoth waitpid(pid, &status, 0); 1613840547dSJayanth Othayoth if (WEXITSTATUS(status)) 1623840547dSJayanth Othayoth { 1633840547dSJayanth Othayoth log<level::ERR>("Failed to collect attribute export data"); 1643840547dSJayanth Othayoth openpower::pel::createPEL(ERROR_DEVTREE_BACKUP); 1653840547dSJayanth Othayoth } 1663840547dSJayanth Othayoth } 1673840547dSJayanth Othayoth else 1683840547dSJayanth Othayoth { 1693840547dSJayanth Othayoth log<level::ERR>("exportDevtree fork() failed"); 1703840547dSJayanth Othayoth std::runtime_error("exportDevtree fork() failed"); 1713840547dSJayanth Othayoth } 1723840547dSJayanth Othayoth } 17313c57ad8SJayanth Othayoth 17413c57ad8SJayanth Othayoth } // namespace fwupdate 17513c57ad8SJayanth Othayoth } // namespace phal 17613c57ad8SJayanth Othayoth } // namespace openpower 177