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