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