blob: 5fb8a8a8e61928fe2a1db832c560dd2dbea1ac72 [file] [log] [blame]
Alexander Hansencc372352025-01-14 14:15:39 +01001#include "software.hpp"
2
3#include "device.hpp"
4#include "software_update.hpp"
5
6#include <phosphor-logging/lg2.hpp>
7#include <sdbusplus/async/context.hpp>
8#include <xyz/openbmc_project/Association/Definitions/server.hpp>
9#include <xyz/openbmc_project/Software/Activation/aserver.hpp>
10#include <xyz/openbmc_project/Software/Update/aserver.hpp>
11#include <xyz/openbmc_project/State/Host/client.hpp>
12
13PHOSPHOR_LOG2_USING;
14
15using namespace phosphor::software;
16using namespace phosphor::software::device;
17using namespace phosphor::software::config;
18using namespace phosphor::software::update;
19
20const static std::string baseObjPathSoftware = "/xyz/openbmc_project/software/";
21
22SoftwareActivationProgress::SoftwareActivationProgress(
23 sdbusplus::async::context& ctx, const char* objPath) :
24 ActivationProgress(ctx, objPath)
25{
26 // This prevents "Conditional jump or move depends on uninitialised
27 // value(s)"
28 // when properties are updated for the first time
29 progress_ = 0;
30}
31
32void SoftwareActivationProgress::setProgress(int progressArg)
33{
34 progress(progressArg);
35}
36
37Software::Software(sdbusplus::async::context& ctx, Device& parent) :
38 Software(ctx, parent, getRandomSoftwareId(parent))
39{}
40
41Software::Software(sdbusplus::async::context& ctx, Device& parent,
42 const std::string& swid) :
43 SoftwareActivation(ctx, (baseObjPathSoftware + swid).c_str()),
44 objectPath(baseObjPathSoftware + swid), parentDevice(parent), swid(swid),
45 ctx(ctx)
46{
47 // initialize the members of our base class to prevent
48 // "Conditional jump or move depends on uninitialised value(s)"
49 activation_ = Activations::NotReady;
50 requested_activation_ = RequestedActivations::None;
51
52 std::string objPath = baseObjPathSoftware + swid;
53
54 debug("{SWID}: created dbus interfaces on path {OBJPATH}", "SWID", swid,
55 "OBJPATH", objPath);
56};
57
Alexander Hansenf2c95a02024-11-26 11:16:44 +010058long int Software::getRandomId()
Alexander Hansencc372352025-01-14 14:15:39 +010059{
60 struct timespec ts;
61 clock_gettime(CLOCK_REALTIME, &ts);
62 unsigned int seed = ts.tv_nsec ^ getpid();
63 srandom(seed);
64 return random() % 10000;
65}
66
67std::string Software::getRandomSoftwareId(Device& parent)
68{
69 return std::format("{}_{}", parent.config.configName, getRandomId());
70}
71
Alexander Hansencc372352025-01-14 14:15:39 +010072sdbusplus::async::task<> Software::createInventoryAssociations(bool isRunning)
Alexander Hansencc372352025-01-14 14:15:39 +010073{
74 debug("{SWID}: setting association definitions", "SWID", swid);
75
76 std::string endpoint = "";
77
78 try
79 {
80 endpoint = co_await parentDevice.config.getInventoryItemObjectPath(ctx);
81 }
82 catch (std::exception& e)
83 {
84 error(e.what());
85 }
86
87 if (!associationDefinitions)
88 {
89 std::string path = objectPath;
90 associationDefinitions =
91 std::make_unique<SoftwareAssociationDefinitions>(ctx, path.c_str());
92 }
93
94 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
95
96 if (endpoint.empty())
97 {
98 associationDefinitions->associations(assocs);
99 co_return;
100 }
101
102 if (isRunning)
103 {
104 debug("{SWID}: creating 'running' association to {OBJPATH}", "SWID",
105 swid, "OBJPATH", endpoint);
106 std::tuple<std::string, std::string, std::string> assocRunning = {
107 "running", "ran_on", endpoint};
108 assocs.push_back(assocRunning);
109 }
110 else
111 {
112 debug("{SWID}: creating 'activating' association to {OBJPATH}", "SWID",
113 swid, "OBJPATH", endpoint);
114 std::tuple<std::string, std::string, std::string> assocActivating = {
115 "activating", "activated_on", endpoint};
116 assocs.push_back(assocActivating);
117 }
118
119 associationDefinitions->associations(assocs);
120
121 co_return;
122}
123
Alexander Hansende5e76f2025-02-20 16:30:11 +0100124void Software::setVersion(const std::string& versionStr,
125 SoftwareVersion::VersionPurpose versionPurpose)
Alexander Hansencc372352025-01-14 14:15:39 +0100126{
127 debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr);
128
Alexander Hansende5e76f2025-02-20 16:30:11 +0100129 const bool emitSignal = !version;
130
Alexander Hansenccec7c62025-02-21 17:17:45 +0100131 if (!version)
Alexander Hansencc372352025-01-14 14:15:39 +0100132 {
Alexander Hansenccec7c62025-02-21 17:17:45 +0100133 version =
134 std::make_unique<SoftwareVersion>(ctx, objectPath.str.c_str());
Alexander Hansencc372352025-01-14 14:15:39 +0100135 }
136
Alexander Hansencc372352025-01-14 14:15:39 +0100137 version->version(versionStr);
Alexander Hansende5e76f2025-02-20 16:30:11 +0100138 version->purpose(versionPurpose);
139
140 if (emitSignal)
141 {
142 version->emit_added();
143 }
144}
145
146SoftwareVersion::VersionPurpose Software::getPurpose()
147{
148 return version->purpose();
Alexander Hansencc372352025-01-14 14:15:39 +0100149}
150
151void Software::setActivationBlocksTransition(bool enabled)
152{
153 if (!enabled)
154 {
155 activationBlocksTransition = nullptr;
156 return;
157 }
158
159 std::string path = objectPath;
160 activationBlocksTransition =
161 std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str());
162}
163
164void Software::setActivation(SoftwareActivation::Activations act)
165{
166 activation(act);
167}
168
169void Software::enableUpdate(
170 const std::set<RequestedApplyTimes>& allowedApplyTimes)
171{
172 if (updateIntf != nullptr)
173 {
174 error("[Software] update of {OBJPATH} has already been enabled",
175 "OBJPATH", objectPath);
176 return;
177 }
178
179 debug(
180 "[Software] enabling update of {OBJPATH} (adding the update interface)",
181 "OBJPATH", objectPath);
182
183 updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(),
184 *this, allowedApplyTimes);
185}