1 #include "activation_static.hpp"
2 
3 #include "item_updater.hpp"
4 
5 #include <phosphor-logging/log.hpp>
6 
7 namespace openpower
8 {
9 namespace software
10 {
11 namespace updater
12 {
13 namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
14 
15 using namespace phosphor::logging;
16 
17 auto ActivationStatic::activation(Activations value) -> Activations
18 {
19 
20     auto ret = value;
21     if (value != softwareServer::Activation::Activations::Active)
22     {
23         redundancyPriority.reset(nullptr);
24     }
25 
26     if (value == softwareServer::Activation::Activations::Activating)
27     {
28         fs::path imagePath(IMG_DIR);
29         imagePath /= versionId;
30 
31         for (const auto& entry : fs::directory_iterator(imagePath))
32         {
33             if (entry.path().extension() == ".pnor")
34             {
35                 pnorFilePath = entry;
36                 break;
37             }
38         }
39         if (pnorFilePath.empty())
40         {
41             log<level::ERR>("Unable to find pnor file",
42                             entry("DIR=%s", imagePath.c_str()));
43             ret = softwareServer::Activation::Activations::Failed;
44             goto out;
45         }
46 #ifdef WANT_SIGNATURE_VERIFY
47         // Validate the signed image.
48         if (!validateSignature(pnorFilePath.filename()))
49         {
50             // Cleanup
51             activationBlocksTransition.reset(nullptr);
52             activationProgress.reset(nullptr);
53 
54             ret = softwareServer::Activation::Activations::Failed;
55             goto out;
56         }
57 #endif
58         if (parent.freeSpace())
59         {
60             startActivation();
61         }
62         else
63         {
64             ret = softwareServer::Activation::Activations::Failed;
65         }
66     }
67     else
68     {
69         activationBlocksTransition.reset(nullptr);
70         activationProgress.reset(nullptr);
71     }
72 
73 out:
74     return softwareServer::Activation::activation(ret);
75 }
76 
77 void ActivationStatic::startActivation()
78 {
79     if (!activationProgress)
80     {
81         activationProgress = std::make_unique<ActivationProgress>(bus, path);
82     }
83 
84     if (!activationBlocksTransition)
85     {
86         activationBlocksTransition =
87             std::make_unique<ActivationBlocksTransition>(bus, path);
88     }
89 
90     // TODO: check why the signal is still received without calling this
91     // function?
92     subscribeToSystemdSignals();
93 
94     log<level::INFO>("Start programming...",
95                      entry("PNOR=%s", pnorFilePath.c_str()));
96 
97     std::string pnorFileEscaped = pnorFilePath.string();
98     // Escape all '/' to '-'
99     std::replace(pnorFileEscaped.begin(), pnorFileEscaped.end(), '/', '-');
100 
101     constexpr auto updatePNORService = "openpower-pnor-update@";
102     pnorUpdateUnit =
103         std::string(updatePNORService) + pnorFileEscaped + ".service";
104     auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
105                                       SYSTEMD_INTERFACE, "StartUnit");
106     method.append(pnorUpdateUnit, "replace");
107     bus.call_noreply(method);
108 
109     activationProgress->progress(10);
110 }
111 
112 void ActivationStatic::unitStateChange(sdbusplus::message::message& msg)
113 {
114     uint32_t newStateID{};
115     sdbusplus::message::object_path newStateObjPath;
116     std::string newStateUnit{};
117     std::string newStateResult{};
118 
119     // Read the msg and populate each variable
120     msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
121 
122     if (newStateUnit == pnorUpdateUnit)
123     {
124         if (newStateResult == "done")
125         {
126             finishActivation();
127         }
128         if (newStateResult == "failed" || newStateResult == "dependency")
129         {
130             Activation::activation(
131                 softwareServer::Activation::Activations::Failed);
132         }
133     }
134 }
135 
136 void ActivationStatic::finishActivation()
137 {
138     activationProgress->progress(90);
139 
140     // Set Redundancy Priority before setting to Active
141     if (!redundancyPriority)
142     {
143         redundancyPriority =
144             std::make_unique<RedundancyPriority>(bus, path, *this, 0);
145     }
146 
147     activationProgress->progress(100);
148 
149     activationBlocksTransition.reset();
150     activationProgress.reset();
151 
152     unsubscribeFromSystemdSignals();
153     // Remove version object from image manager
154     deleteImageManagerObject();
155     // Create active association
156     parent.createActiveAssociation(path);
157     // Create updateable association as this
158     // can be re-programmed.
159     parent.createUpdateableAssociation(path);
160     // Create functional assocaition
161     parent.updateFunctionalAssociation(versionId);
162 
163     Activation::activation(Activation::Activations::Active);
164 }
165 
166 } // namespace updater
167 } // namespace software
168 } // namespace openpower
169