blob: d20451d1c02e5b88f83a8ea3f8fcbf747930f55b [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
Alexander Hansencc372352025-01-14 14:15:39 +010022Software::Software(sdbusplus::async::context& ctx, Device& parent) :
23 Software(ctx, parent, getRandomSoftwareId(parent))
24{}
25
26Software::Software(sdbusplus::async::context& ctx, Device& parent,
27 const std::string& swid) :
Alexander Hansendf628192025-06-18 16:28:59 +020028 SoftwareActivation(ctx, (baseObjPathSoftware + swid).c_str(),
29 Activation::properties_t{Activations::NotReady,
30 RequestedActivations::None}),
Alexander Hansencc372352025-01-14 14:15:39 +010031 objectPath(baseObjPathSoftware + swid), parentDevice(parent), swid(swid),
32 ctx(ctx)
33{
Alexander Hansencc372352025-01-14 14:15:39 +010034 std::string objPath = baseObjPathSoftware + swid;
35
Alexander Hansen0fdb6122025-07-09 14:33:13 +020036 emit_added();
37
Alexander Hansencc372352025-01-14 14:15:39 +010038 debug("{SWID}: created dbus interfaces on path {OBJPATH}", "SWID", swid,
39 "OBJPATH", objPath);
40};
41
Alexander Hansenf2c95a02024-11-26 11:16:44 +010042long int Software::getRandomId()
Alexander Hansencc372352025-01-14 14:15:39 +010043{
44 struct timespec ts;
45 clock_gettime(CLOCK_REALTIME, &ts);
46 unsigned int seed = ts.tv_nsec ^ getpid();
47 srandom(seed);
48 return random() % 10000;
49}
50
51std::string Software::getRandomSoftwareId(Device& parent)
52{
53 return std::format("{}_{}", parent.config.configName, getRandomId());
54}
55
Alexander Hansencc372352025-01-14 14:15:39 +010056sdbusplus::async::task<> Software::createInventoryAssociations(bool isRunning)
Alexander Hansencc372352025-01-14 14:15:39 +010057{
58 debug("{SWID}: setting association definitions", "SWID", swid);
59
60 std::string endpoint = "";
61
62 try
63 {
64 endpoint = co_await parentDevice.config.getInventoryItemObjectPath(ctx);
65 }
66 catch (std::exception& e)
67 {
Alexander Hansend73d5642025-07-23 14:05:06 +020068 error("Failed to create association with {ERROR}", "ERROR", e.what());
69 co_return;
Alexander Hansencc372352025-01-14 14:15:39 +010070 }
71
Alexander Hansencc372352025-01-14 14:15:39 +010072 if (endpoint.empty())
73 {
Alexander Hansencc372352025-01-14 14:15:39 +010074 co_return;
75 }
76
Alexander Hansendf628192025-06-18 16:28:59 +020077 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
78
Alexander Hansencc372352025-01-14 14:15:39 +010079 if (isRunning)
80 {
81 debug("{SWID}: creating 'running' association to {OBJPATH}", "SWID",
82 swid, "OBJPATH", endpoint);
83 std::tuple<std::string, std::string, std::string> assocRunning = {
84 "running", "ran_on", endpoint};
85 assocs.push_back(assocRunning);
86 }
87 else
88 {
89 debug("{SWID}: creating 'activating' association to {OBJPATH}", "SWID",
90 swid, "OBJPATH", endpoint);
91 std::tuple<std::string, std::string, std::string> assocActivating = {
92 "activating", "activated_on", endpoint};
93 assocs.push_back(assocActivating);
94 }
95
Alexander Hansend73d5642025-07-23 14:05:06 +020096 if (associationDefinitions)
97 {
98 associationDefinitions->associations(assocs);
99 }
100 else
101 {
102 std::string path = objectPath;
103 associationDefinitions =
104 std::make_unique<SoftwareAssociationDefinitions>(
105 ctx, path.c_str(),
106 SoftwareAssociationDefinitions::properties_t{assocs});
107 associationDefinitions->emit_added();
108 }
Alexander Hansencc372352025-01-14 14:15:39 +0100109
110 co_return;
111}
112
Alexander Hansende5e76f2025-02-20 16:30:11 +0100113void Software::setVersion(const std::string& versionStr,
114 SoftwareVersion::VersionPurpose versionPurpose)
Alexander Hansencc372352025-01-14 14:15:39 +0100115{
116 debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr);
117
Alexander Hansenccec7c62025-02-21 17:17:45 +0100118 if (!version)
Alexander Hansencc372352025-01-14 14:15:39 +0100119 {
Alexander Hansendf628192025-06-18 16:28:59 +0200120 version = std::make_unique<SoftwareVersion>(
121 ctx, objectPath.str.c_str(),
122 SoftwareVersion::properties_t{versionStr, versionPurpose});
123 version->emit_added();
124 return;
Alexander Hansencc372352025-01-14 14:15:39 +0100125 }
126
Alexander Hansencc372352025-01-14 14:15:39 +0100127 version->version(versionStr);
Alexander Hansende5e76f2025-02-20 16:30:11 +0100128 version->purpose(versionPurpose);
Alexander Hansende5e76f2025-02-20 16:30:11 +0100129}
130
Alexander Hansenb0cfda62025-07-18 16:30:32 +0200131std::optional<SoftwareVersion::VersionPurpose> Software::getPurpose()
Alexander Hansende5e76f2025-02-20 16:30:11 +0100132{
Alexander Hansenb0cfda62025-07-18 16:30:32 +0200133 if (!version)
134 {
135 return std::nullopt;
136 }
Alexander Hansende5e76f2025-02-20 16:30:11 +0100137 return version->purpose();
Alexander Hansencc372352025-01-14 14:15:39 +0100138}
139
140void Software::setActivationBlocksTransition(bool enabled)
141{
142 if (!enabled)
143 {
144 activationBlocksTransition = nullptr;
145 return;
146 }
147
148 std::string path = objectPath;
149 activationBlocksTransition =
150 std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str());
Alexander Hansen0fdb6122025-07-09 14:33:13 +0200151
152 activationBlocksTransition->emit_added();
Alexander Hansencc372352025-01-14 14:15:39 +0100153}
154
155void Software::setActivation(SoftwareActivation::Activations act)
156{
157 activation(act);
158}
159
160void Software::enableUpdate(
161 const std::set<RequestedApplyTimes>& allowedApplyTimes)
162{
163 if (updateIntf != nullptr)
164 {
165 error("[Software] update of {OBJPATH} has already been enabled",
166 "OBJPATH", objectPath);
167 return;
168 }
169
170 debug(
171 "[Software] enabling update of {OBJPATH} (adding the update interface)",
172 "OBJPATH", objectPath);
173
174 updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(),
175 *this, allowedApplyTimes);
176}