blob: edaa7a63bdadde46e70cd19c1cc86d0ee273f580 [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
140 int status = 0;
141 pid_t pid = fork();
142 if (pid == 0)
143 {
144 std::string cmd("/usr/bin/attributes ");
145 cmd += "export ";
146 cmd += DEVTREE_EXPORT_FILTER_FILE;
147 cmd += " > ";
148 cmd += DEVTREE_EXP_FILE;
149 execl("/bin/sh", "sh", "-c", cmd.c_str(), 0);
150
151 auto error = errno;
152 log<level::ERR>(fmt::format("Error occurred during attributes function "
153 "execution, errno({})",
154 error)
155 .c_str());
156 // Creating PEL at one place.
157 }
158 else if (pid > 0)
159 {
160 waitpid(pid, &status, 0);
161 if (WEXITSTATUS(status))
162 {
163 log<level::ERR>("Failed to collect attribute export data");
164 openpower::pel::createPEL(ERROR_DEVTREE_BACKUP);
165 }
166 }
167 else
168 {
169 log<level::ERR>("exportDevtree fork() failed");
170 std::runtime_error("exportDevtree fork() failed");
171 }
172}
Jayanth Othayoth13c57ad2021-07-16 06:02:21 -0500173
174} // namespace fwupdate
175} // namespace phal
176} // namespace openpower