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