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