blob: 1554b054c2554ff570e1a9862bca1b17358e71bc [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 Hansen53c7c0e2025-07-29 12:37:13 +020077 createInventoryAssociation(isRunning, endpoint);
78}
79
80void Software::createInventoryAssociation(bool isRunning,
81 std::string objectPath)
82{
Alexander Hansendf628192025-06-18 16:28:59 +020083 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
84
Alexander Hansencc372352025-01-14 14:15:39 +010085 if (isRunning)
86 {
87 debug("{SWID}: creating 'running' association to {OBJPATH}", "SWID",
Alexander Hansen53c7c0e2025-07-29 12:37:13 +020088 swid, "OBJPATH", objectPath);
Alexander Hansencc372352025-01-14 14:15:39 +010089 std::tuple<std::string, std::string, std::string> assocRunning = {
Alexander Hansen53c7c0e2025-07-29 12:37:13 +020090 "running", "ran_on", objectPath};
Alexander Hansencc372352025-01-14 14:15:39 +010091 assocs.push_back(assocRunning);
92 }
93 else
94 {
95 debug("{SWID}: creating 'activating' association to {OBJPATH}", "SWID",
Alexander Hansen53c7c0e2025-07-29 12:37:13 +020096 swid, "OBJPATH", objectPath);
Alexander Hansencc372352025-01-14 14:15:39 +010097 std::tuple<std::string, std::string, std::string> assocActivating = {
Alexander Hansen53c7c0e2025-07-29 12:37:13 +020098 "activating", "activated_on", objectPath};
Alexander Hansencc372352025-01-14 14:15:39 +010099 assocs.push_back(assocActivating);
100 }
101
Alexander Hansend73d5642025-07-23 14:05:06 +0200102 if (associationDefinitions)
103 {
104 associationDefinitions->associations(assocs);
105 }
106 else
107 {
Alexander Hansend73d5642025-07-23 14:05:06 +0200108 associationDefinitions =
109 std::make_unique<SoftwareAssociationDefinitions>(
Alexander Hansen53c7c0e2025-07-29 12:37:13 +0200110 ctx, Software::objectPath.str.c_str(),
Alexander Hansend73d5642025-07-23 14:05:06 +0200111 SoftwareAssociationDefinitions::properties_t{assocs});
112 associationDefinitions->emit_added();
113 }
Alexander Hansencc372352025-01-14 14:15:39 +0100114}
115
Alexander Hansende5e76f2025-02-20 16:30:11 +0100116void Software::setVersion(const std::string& versionStr,
117 SoftwareVersion::VersionPurpose versionPurpose)
Alexander Hansencc372352025-01-14 14:15:39 +0100118{
119 debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr);
120
Alexander Hansenccec7c62025-02-21 17:17:45 +0100121 if (!version)
Alexander Hansencc372352025-01-14 14:15:39 +0100122 {
Alexander Hansendf628192025-06-18 16:28:59 +0200123 version = std::make_unique<SoftwareVersion>(
124 ctx, objectPath.str.c_str(),
125 SoftwareVersion::properties_t{versionStr, versionPurpose});
126 version->emit_added();
127 return;
Alexander Hansencc372352025-01-14 14:15:39 +0100128 }
129
Alexander Hansencc372352025-01-14 14:15:39 +0100130 version->version(versionStr);
Alexander Hansende5e76f2025-02-20 16:30:11 +0100131 version->purpose(versionPurpose);
Alexander Hansende5e76f2025-02-20 16:30:11 +0100132}
133
Alexander Hansenb0cfda62025-07-18 16:30:32 +0200134std::optional<SoftwareVersion::VersionPurpose> Software::getPurpose()
Alexander Hansende5e76f2025-02-20 16:30:11 +0100135{
Alexander Hansenb0cfda62025-07-18 16:30:32 +0200136 if (!version)
137 {
138 return std::nullopt;
139 }
Alexander Hansende5e76f2025-02-20 16:30:11 +0100140 return version->purpose();
Alexander Hansencc372352025-01-14 14:15:39 +0100141}
142
143void Software::setActivationBlocksTransition(bool enabled)
144{
145 if (!enabled)
146 {
147 activationBlocksTransition = nullptr;
148 return;
149 }
150
151 std::string path = objectPath;
152 activationBlocksTransition =
153 std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str());
Alexander Hansen0fdb6122025-07-09 14:33:13 +0200154
155 activationBlocksTransition->emit_added();
Alexander Hansencc372352025-01-14 14:15:39 +0100156}
157
158void Software::setActivation(SoftwareActivation::Activations act)
159{
160 activation(act);
161}
162
163void Software::enableUpdate(
164 const std::set<RequestedApplyTimes>& allowedApplyTimes)
165{
166 if (updateIntf != nullptr)
167 {
168 error("[Software] update of {OBJPATH} has already been enabled",
169 "OBJPATH", objectPath);
170 return;
171 }
172
173 debug(
174 "[Software] enabling update of {OBJPATH} (adding the update interface)",
175 "OBJPATH", objectPath);
176
177 updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(),
178 *this, allowedApplyTimes);
179}