blob: 3a02763e1f637f7fc8b38ad6c758de0df62688e4 [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
36 debug("{SWID}: created dbus interfaces on path {OBJPATH}", "SWID", swid,
37 "OBJPATH", objPath);
38};
39
Alexander Hansenf2c95a02024-11-26 11:16:44 +010040long int Software::getRandomId()
Alexander Hansencc372352025-01-14 14:15:39 +010041{
42 struct timespec ts;
43 clock_gettime(CLOCK_REALTIME, &ts);
44 unsigned int seed = ts.tv_nsec ^ getpid();
45 srandom(seed);
46 return random() % 10000;
47}
48
49std::string Software::getRandomSoftwareId(Device& parent)
50{
51 return std::format("{}_{}", parent.config.configName, getRandomId());
52}
53
Alexander Hansencc372352025-01-14 14:15:39 +010054sdbusplus::async::task<> Software::createInventoryAssociations(bool isRunning)
Alexander Hansencc372352025-01-14 14:15:39 +010055{
56 debug("{SWID}: setting association definitions", "SWID", swid);
57
58 std::string endpoint = "";
59
60 try
61 {
62 endpoint = co_await parentDevice.config.getInventoryItemObjectPath(ctx);
63 }
64 catch (std::exception& e)
65 {
66 error(e.what());
67 }
68
69 if (!associationDefinitions)
70 {
71 std::string path = objectPath;
72 associationDefinitions =
Alexander Hansendf628192025-06-18 16:28:59 +020073 std::make_unique<SoftwareAssociationDefinitions>(
74 ctx, path.c_str(),
75 SoftwareAssociationDefinitions::properties_t{{}});
Alexander Hansencc372352025-01-14 14:15:39 +010076 }
77
Alexander Hansencc372352025-01-14 14:15:39 +010078 if (endpoint.empty())
79 {
Alexander Hansencc372352025-01-14 14:15:39 +010080 co_return;
81 }
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",
88 swid, "OBJPATH", endpoint);
89 std::tuple<std::string, std::string, std::string> assocRunning = {
90 "running", "ran_on", endpoint};
91 assocs.push_back(assocRunning);
92 }
93 else
94 {
95 debug("{SWID}: creating 'activating' association to {OBJPATH}", "SWID",
96 swid, "OBJPATH", endpoint);
97 std::tuple<std::string, std::string, std::string> assocActivating = {
98 "activating", "activated_on", endpoint};
99 assocs.push_back(assocActivating);
100 }
101
102 associationDefinitions->associations(assocs);
103
104 co_return;
105}
106
Alexander Hansende5e76f2025-02-20 16:30:11 +0100107void Software::setVersion(const std::string& versionStr,
108 SoftwareVersion::VersionPurpose versionPurpose)
Alexander Hansencc372352025-01-14 14:15:39 +0100109{
110 debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr);
111
Alexander Hansenccec7c62025-02-21 17:17:45 +0100112 if (!version)
Alexander Hansencc372352025-01-14 14:15:39 +0100113 {
Alexander Hansendf628192025-06-18 16:28:59 +0200114 version = std::make_unique<SoftwareVersion>(
115 ctx, objectPath.str.c_str(),
116 SoftwareVersion::properties_t{versionStr, versionPurpose});
117 version->emit_added();
118 return;
Alexander Hansencc372352025-01-14 14:15:39 +0100119 }
120
Alexander Hansencc372352025-01-14 14:15:39 +0100121 version->version(versionStr);
Alexander Hansende5e76f2025-02-20 16:30:11 +0100122 version->purpose(versionPurpose);
Alexander Hansende5e76f2025-02-20 16:30:11 +0100123}
124
125SoftwareVersion::VersionPurpose Software::getPurpose()
126{
127 return version->purpose();
Alexander Hansencc372352025-01-14 14:15:39 +0100128}
129
130void Software::setActivationBlocksTransition(bool enabled)
131{
132 if (!enabled)
133 {
134 activationBlocksTransition = nullptr;
135 return;
136 }
137
138 std::string path = objectPath;
139 activationBlocksTransition =
140 std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str());
141}
142
143void Software::setActivation(SoftwareActivation::Activations act)
144{
145 activation(act);
146}
147
148void Software::enableUpdate(
149 const std::set<RequestedApplyTimes>& allowedApplyTimes)
150{
151 if (updateIntf != nullptr)
152 {
153 error("[Software] update of {OBJPATH} has already been enabled",
154 "OBJPATH", objectPath);
155 return;
156 }
157
158 debug(
159 "[Software] enabling update of {OBJPATH} (adding the update interface)",
160 "OBJPATH", objectPath);
161
162 updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(),
163 *this, allowedApplyTimes);
164}