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 <sys/stat.h>
103840547dSJayanth Othayoth #include <sys/wait.h>
113840547dSJayanth Othayoth #include <unistd.h>
123840547dSJayanth Othayoth
133840547dSJayanth Othayoth #include <phosphor-logging/elog-errors.hpp>
1413c57ad8SJayanth Othayoth #include <phosphor-logging/elog.hpp>
1513c57ad8SJayanth Othayoth #include <sdbusplus/exception.hpp>
1613c57ad8SJayanth Othayoth
173840547dSJayanth Othayoth #include <filesystem>
18*e0dd7af4SJayanth Othayoth #include <format>
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
fwIntfAddedCallback(sdbusplus::message_t & msg)36aaea6867SPatrick Williams void Watch::fwIntfAddedCallback(sdbusplus::message_t& 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 }
46aaea6867SPatrick Williams catch (const sdbusplus::exception_t& e)
4713c57ad8SJayanth Othayoth {
48*e0dd7af4SJayanth Othayoth log<level::ERR>(std::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 }
941a9a5a6aSPatrick Williams catch (const fs::filesystem_error& e)
953840547dSJayanth Othayoth {
963840547dSJayanth Othayoth log<level::ERR>(
97*e0dd7af4SJayanth Othayoth std::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
exportDevtree()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>(
118*e0dd7af4SJayanth Othayoth std::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
14041e122fdSJayanth Othayoth // Update PDATA_INFODB value
14141e122fdSJayanth Othayoth openpower::phal::setPdataInfoDBEnv();
14241e122fdSJayanth Othayoth
1433840547dSJayanth Othayoth int status = 0;
1443840547dSJayanth Othayoth pid_t pid = fork();
1453840547dSJayanth Othayoth if (pid == 0)
1463840547dSJayanth Othayoth {
1473840547dSJayanth Othayoth std::string cmd("/usr/bin/attributes ");
1483840547dSJayanth Othayoth cmd += "export ";
1493840547dSJayanth Othayoth cmd += DEVTREE_EXPORT_FILTER_FILE;
1503840547dSJayanth Othayoth cmd += " > ";
1513840547dSJayanth Othayoth cmd += DEVTREE_EXP_FILE;
1523840547dSJayanth Othayoth execl("/bin/sh", "sh", "-c", cmd.c_str(), 0);
1533840547dSJayanth Othayoth
1543840547dSJayanth Othayoth auto error = errno;
155*e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("Error occurred during attributes function "
1563840547dSJayanth Othayoth "execution, errno({})",
1573840547dSJayanth Othayoth error)
1583840547dSJayanth Othayoth .c_str());
1593840547dSJayanth Othayoth // Creating PEL at one place.
1603840547dSJayanth Othayoth }
1613840547dSJayanth Othayoth else if (pid > 0)
1623840547dSJayanth Othayoth {
1633840547dSJayanth Othayoth waitpid(pid, &status, 0);
1643840547dSJayanth Othayoth if (WEXITSTATUS(status))
1653840547dSJayanth Othayoth {
1663840547dSJayanth Othayoth log<level::ERR>("Failed to collect attribute export data");
1673840547dSJayanth Othayoth openpower::pel::createPEL(ERROR_DEVTREE_BACKUP);
1683840547dSJayanth Othayoth }
1693840547dSJayanth Othayoth }
1703840547dSJayanth Othayoth else
1713840547dSJayanth Othayoth {
1723840547dSJayanth Othayoth log<level::ERR>("exportDevtree fork() failed");
1733840547dSJayanth Othayoth std::runtime_error("exportDevtree fork() failed");
1743840547dSJayanth Othayoth }
1753840547dSJayanth Othayoth }
17613c57ad8SJayanth Othayoth
17713c57ad8SJayanth Othayoth } // namespace fwupdate
17813c57ad8SJayanth Othayoth } // namespace phal
17913c57ad8SJayanth Othayoth } // namespace openpower
180