blob: 2c6f813ee50c0749a4776ecad8a6f23a6f500ef1 [file] [log] [blame]
Jayanth Othayoth38405472021-07-26 06:16:44 -05001#include "config.h"
2
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -05003#include "fw_update_watch.hpp"
4
Jayanth Othayoth38405472021-07-26 06:16:44 -05005#include "common_utils.hpp"
6#include "create_pel.hpp"
7#include "pdbg_utils.hpp"
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -05008
Jayanth Othayoth38405472021-07-26 06:16:44 -05009#include <fmt/format.h>
10#include <sys/stat.h>
11#include <sys/wait.h>
12#include <unistd.h>
13
14#include <phosphor-logging/elog-errors.hpp>
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -050015#include <phosphor-logging/elog.hpp>
16#include <sdbusplus/exception.hpp>
17
Jayanth Othayoth38405472021-07-26 06:16:44 -050018#include <filesystem>
19
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -050020namespace openpower
21{
22namespace phal
23{
24namespace fwupdate
25{
26using namespace phosphor::logging;
Jayanth Othayoth38405472021-07-26 06:16:44 -050027namespace fs = std::filesystem;
28
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -050029using Message = std::string;
30using Attributes = std::variant<Message>;
31using PropertyName = std::string;
32using PropertyMap = std::map<PropertyName, Attributes>;
33using InterfaceName = std::string;
34using InterfaceMap = std::map<InterfaceName, PropertyMap>;
35
36void Watch::fwIntfAddedCallback(sdbusplus::message::message& msg)
37{
38 // DBusInterfaceAdded interfaces;
39 sdbusplus::message::object_path objectPath;
40 InterfaceMap interfaceMap;
41
42 try
43 {
44 msg.read(objectPath, interfaceMap);
45 }
Patrick Williams2246cca2021-09-02 09:32:52 -050046 catch (const sdbusplus::exception::exception& e)
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -050047 {
48 log<level::ERR>(fmt::format("Failed to parse software add signal"
49 "Exception [{}] REPLY_SIG [{}]",
50 e.what(), msg.get_signature())
51 .c_str());
52 return;
53 }
54
55 auto iter = interfaceMap.find("xyz.openbmc_project.Software.Activation");
56 if (iter == interfaceMap.end())
57 {
58 // Skip not related Software Activation
59 return;
60 }
61
62 auto attr = iter->second.find("Activation");
63 if (attr == iter->second.end())
64 {
65 // Skip not related to Activation property.
66 return;
67 }
68
69 auto& imageProperty = std::get<InterfaceName>(attr->second);
70 if (imageProperty.empty())
71 {
72 // Skip, no image property
73 return;
74 }
75
76 if (imageProperty ==
77 "xyz.openbmc_project.Software.Activation.Activations.Ready" &&
78 !isSoftwareUpdateInProgress())
79 {
80 log<level::INFO>("Software path interface add signal received");
81
82 // Set status to code update in progress.
83 // Interface added signal triggered multiple times in code update path,
84 // it's due to additional interfaces added by the software manager app
85 // after the version interface is created.
86 // Device tree data collection is required only for the first trigger
87 setSoftwareUpdateProgress(true);
88
Jayanth Othayoth38405472021-07-26 06:16:44 -050089 try
90 {
91 // Colect device tree data
92 openpower::phal::fwupdate::exportDevtree();
93 }
94 catch (fs::filesystem_error& e)
95 {
96 log<level::ERR>(
97 fmt::format("Filesystem error reported Error:({})", e.what())
98 .c_str());
99 throw std::runtime_error(e.what());
100 }
101
102 log<level::INFO>("Successfully exported devtree attribute data");
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -0500103 }
104
105 return;
106}
107
108void exportDevtree()
Jayanth Othayoth38405472021-07-26 06:16:44 -0500109{
110 constexpr auto ERROR_DEVTREE_BACKUP =
111 "org.open_power.PHAL.Error.devtreeBackup";
112
113 // Check devtree export filter file is present
114 auto path = fs::path(DEVTREE_EXPORT_FILTER_FILE);
115 if (!fs::exists(path))
116 {
117 log<level::ERR>(
118 fmt::format("devtree export filter file is not available: ({})",
119 DEVTREE_EXPORT_FILTER_FILE)
120 .c_str());
121 openpower::pel::createPEL(ERROR_DEVTREE_BACKUP);
122 return;
123 }
124
125 // delete export data file if present
126 auto expFile = fs::path(DEVTREE_EXP_FILE);
127 if (fs::exists(expFile))
128 {
129 fs::remove_all(expFile);
130 }
131 else
132 {
133 // create directory
134 fs::create_directory(expFile.parent_path());
135 }
136
137 // Update PDBG_DTB value
138 openpower::phal::setDevtreeEnv();
139
Jayanth Othayoth41e122f2021-09-10 09:25:19 -0500140 // Update PDATA_INFODB value
141 openpower::phal::setPdataInfoDBEnv();
142
Jayanth Othayoth38405472021-07-26 06:16:44 -0500143 int status = 0;
144 pid_t pid = fork();
145 if (pid == 0)
146 {
147 std::string cmd("/usr/bin/attributes ");
148 cmd += "export ";
149 cmd += DEVTREE_EXPORT_FILTER_FILE;
150 cmd += " > ";
151 cmd += DEVTREE_EXP_FILE;
152 execl("/bin/sh", "sh", "-c", cmd.c_str(), 0);
153
154 auto error = errno;
155 log<level::ERR>(fmt::format("Error occurred during attributes function "
156 "execution, errno({})",
157 error)
158 .c_str());
159 // Creating PEL at one place.
160 }
161 else if (pid > 0)
162 {
163 waitpid(pid, &status, 0);
164 if (WEXITSTATUS(status))
165 {
166 log<level::ERR>("Failed to collect attribute export data");
167 openpower::pel::createPEL(ERROR_DEVTREE_BACKUP);
168 }
169 }
170 else
171 {
172 log<level::ERR>("exportDevtree fork() failed");
173 std::runtime_error("exportDevtree fork() failed");
174 }
175}
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -0500176
177} // namespace fwupdate
178} // namespace phal
179} // namespace openpower