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