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 = std::string(ubimountService) + versionId +
122                                ".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 = "obmc-flash-bios-ubimount@" + versionId +
142                                ".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 = std::make_unique<RedundancyPriorityUbi>(bus, path,
172                                                                      *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