1 #include "activation_ubi.hpp"
2
3 #include "item_updater.hpp"
4 #include "serialize.hpp"
5
6 #include <phosphor-logging/log.hpp>
7
8 #include <filesystem>
9
10 namespace openpower
11 {
12 namespace software
13 {
14 namespace updater
15 {
16 namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
17 using namespace phosphor::logging;
18
priority(uint8_t value)19 uint8_t RedundancyPriorityUbi::priority(uint8_t value)
20 {
21 storeToFile(parent.versionId, value);
22 return RedundancyPriority::priority(value);
23 }
24
activation(Activations value)25 auto ActivationUbi::activation(Activations value) -> Activations
26 {
27 if (value != softwareServer::Activation::Activations::Active)
28 {
29 redundancyPriority.reset(nullptr);
30 }
31
32 if (value == softwareServer::Activation::Activations::Activating)
33 {
34 parent.freeSpace();
35 softwareServer::Activation::activation(value);
36
37 if (ubiVolumesCreated == false)
38 {
39 // Enable systemd signals
40 subscribeToSystemdSignals();
41
42 #ifdef WANT_SIGNATURE_VERIFY
43 // Validate the signed image.
44 if (!validateSignature(squashFSImage))
45 {
46 // Cleanup
47 activationBlocksTransition.reset(nullptr);
48 activationProgress.reset(nullptr);
49
50 return softwareServer::Activation::activation(
51 softwareServer::Activation::Activations::Failed);
52 }
53 #endif
54 startActivation();
55 return softwareServer::Activation::activation(value);
56 }
57 else if (ubiVolumesCreated == true)
58 {
59 // Only when the squashfs image is finished loading AND the RW
60 // volumes have been created do we proceed with activation. To
61 // verify that this happened, we check for the mount dirs PNOR_PRSV
62 // and PNOR_RW_PREFIX_<versionid>, as well as the image dir R0.
63
64 if ((std::filesystem::is_directory(PNOR_PRSV)) &&
65 (std::filesystem::is_directory(PNOR_RW_PREFIX + versionId)) &&
66 (std::filesystem::is_directory(PNOR_RO_PREFIX + versionId)))
67 {
68 finishActivation();
69 if (Activation::checkApplyTimeImmediate())
70 {
71 log<level::INFO>("Image Active. ApplyTime is immediate, "
72 "rebooting Host.");
73 Activation::rebootHost();
74 }
75 return softwareServer::Activation::activation(
76 softwareServer::Activation::Activations::Active);
77 }
78 else
79 {
80 activationBlocksTransition.reset(nullptr);
81 activationProgress.reset(nullptr);
82 return softwareServer::Activation::activation(
83 softwareServer::Activation::Activations::Failed);
84 }
85 }
86 }
87 else
88 {
89 activationBlocksTransition.reset(nullptr);
90 activationProgress.reset(nullptr);
91 }
92
93 return softwareServer::Activation::activation(value);
94 }
95
requestedActivation(RequestedActivations value)96 auto ActivationUbi::requestedActivation(RequestedActivations value)
97 -> RequestedActivations
98 {
99 ubiVolumesCreated = false;
100 return Activation::requestedActivation(value);
101 }
102
startActivation()103 void ActivationUbi::startActivation()
104 {
105 // Since the squashfs image has not yet been loaded to pnor and the
106 // RW volumes have not yet been created, we need to start the
107 // service files for each of those actions.
108
109 if (!activationProgress)
110 {
111 activationProgress = std::make_unique<ActivationProgress>(bus, path);
112 }
113
114 if (!activationBlocksTransition)
115 {
116 activationBlocksTransition =
117 std::make_unique<ActivationBlocksTransition>(bus, path);
118 }
119
120 constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
121 auto ubimountServiceFile =
122 std::string(ubimountService) + versionId + ".service";
123 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
124 SYSTEMD_INTERFACE, "StartUnit");
125 method.append(ubimountServiceFile, "replace");
126 bus.call_noreply(method);
127
128 activationProgress->progress(10);
129 }
130
unitStateChange(sdbusplus::message_t & msg)131 void ActivationUbi::unitStateChange(sdbusplus::message_t& msg)
132 {
133 uint32_t newStateID{};
134 sdbusplus::message::object_path newStateObjPath;
135 std::string newStateUnit{};
136 std::string newStateResult{};
137
138 // Read the msg and populate each variable
139 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
140
141 auto ubimountServiceFile =
142 "obmc-flash-bios-ubimount@" + versionId + ".service";
143
144 if (newStateUnit == ubimountServiceFile && newStateResult == "done")
145 {
146 ubiVolumesCreated = true;
147 activationProgress->progress(activationProgress->progress() + 50);
148 }
149
150 if (ubiVolumesCreated)
151 {
152 activation(softwareServer::Activation::Activations::Activating);
153 }
154
155 if ((newStateUnit == ubimountServiceFile) &&
156 (newStateResult == "failed" || newStateResult == "dependency"))
157 {
158 activation(softwareServer::Activation::Activations::Failed);
159 }
160
161 return;
162 }
163
finishActivation()164 void ActivationUbi::finishActivation()
165 {
166 activationProgress->progress(90);
167
168 // Set Redundancy Priority before setting to Active
169 if (!redundancyPriority)
170 {
171 redundancyPriority =
172 std::make_unique<RedundancyPriorityUbi>(bus, path, *this, 0);
173 }
174
175 activationProgress->progress(100);
176
177 activationBlocksTransition.reset(nullptr);
178 activationProgress.reset(nullptr);
179
180 ubiVolumesCreated = false;
181 unsubscribeFromSystemdSignals();
182 // Remove version object from image manager
183 deleteImageManagerObject();
184 // Create active association
185 parent.createActiveAssociation(path);
186 // Create updateable association as this
187 // can be re-programmed.
188 parent.createUpdateableAssociation(path);
189 }
190
191 } // namespace updater
192 } // namespace software
193 } // namespace openpower
194