blob: 9e2278d87cb8e3bf9940b0a35b083cb00690226d [file] [log] [blame]
Alexander Hansencc372352025-01-14 14:15:39 +01001#include "device.hpp"
2
3#include "common/pldm/pldm_package_util.hpp"
4#include "software.hpp"
5#include "software_manager.hpp"
6
7#include <phosphor-logging/lg2.hpp>
8#include <sdbusplus/asio/object_server.hpp>
9#include <sdbusplus/async/context.hpp>
10#include <sdbusplus/bus.hpp>
11#include <xyz/openbmc_project/Association/Definitions/server.hpp>
12#include <xyz/openbmc_project/State/Host/client.hpp>
13
14#include <utility>
15
16PHOSPHOR_LOG2_USING;
17
18using namespace phosphor::software::device;
19
20const auto applyTimeImmediate = sdbusplus::common::xyz::openbmc_project::
21 software::ApplyTime::RequestedApplyTimes::Immediate;
22
23const auto ActivationInvalid = ActivationInterface::Activations::Invalid;
24const auto ActivationFailed = ActivationInterface::Activations::Failed;
25
26Device::Device(sdbusplus::async::context& ctx, const SoftwareConfig& config,
27 manager::SoftwareManager* parent,
28 std::set<RequestedApplyTimes> allowedApplyTimes =
29 {RequestedApplyTimes::Immediate,
30 RequestedApplyTimes::OnReset}) :
31 allowedApplyTimes(std::move(allowedApplyTimes)), config(config),
32 parent(parent), ctx(ctx)
33{}
34
35// NOLINTBEGIN(readability-static-accessed-through-instance)
36sdbusplus::async::task<bool> Device::getImageInfo(
37 std::unique_ptr<void, std::function<void(void*)>>& pldmPackage,
38 size_t pldmPackageSize, uint8_t** matchingComponentImage,
39 size_t* componentImageSize, std::string& componentVersion)
40
41// NOLINTEND(readability-static-accessed-through-instance)
42{
43 std::shared_ptr<PackageParser> packageParser =
44 pldm_package_util::parsePLDMPackage(
45 static_cast<uint8_t*>(pldmPackage.get()), pldmPackageSize);
46
47 if (packageParser == nullptr)
48 {
49 error("could not parse PLDM package");
50 co_return false;
51 }
52
53 uint32_t componentOffset = 0;
54 const int status = pldm_package_util::extractMatchingComponentImage(
55 packageParser, config.compatibleHardware, config.vendorIANA,
56 &componentOffset, componentImageSize, componentVersion);
57
58 if (status != 0)
59 {
60 error("could not extract matching component image");
61 co_return false;
62 }
63
64 *matchingComponentImage =
65 static_cast<uint8_t*>(pldmPackage.get()) + componentOffset;
66
67 co_return true;
68}
69
70// NOLINTBEGIN(readability-static-accessed-through-instance)
71sdbusplus::async::task<bool> Device::startUpdateAsync(
72 sdbusplus::message::unix_fd image, RequestedApplyTimes applyTime,
73 std::unique_ptr<Software> softwarePendingIn)
74// NOLINTEND(readability-static-accessed-through-instance)
75{
76 debug("starting the async update with memfd {FD}", "FD", image.fd);
77
78 size_t pldm_pkg_size = 0;
79 auto pldm_pkg = pldm_package_util::mmapImagePackage(image, &pldm_pkg_size);
80
81 if (pldm_pkg == nullptr)
82 {
83 softwarePendingIn->setActivation(ActivationInvalid);
84 co_return false;
85 }
86
87 uint8_t* componentImage;
88 size_t componentImageSize = 0;
89 std::string componentVersion;
90
91 if (!co_await getImageInfo(pldm_pkg, pldm_pkg_size, &componentImage,
92 &componentImageSize, componentVersion))
93 {
94 error("could not extract matching component image");
95 softwarePendingIn->setActivation(ActivationInvalid);
96 co_return false;
97 }
98
Alexander Hansen5622ee92025-02-18 14:13:30 +010099 std::unique_ptr<Software> softwarePendingOld = std::move(softwarePending);
100
101 softwarePending = std::move(softwarePendingIn);
102 softwarePendingIn = nullptr;
103
Alexander Hansencc372352025-01-14 14:15:39 +0100104 const bool success = co_await continueUpdateWithMappedPackage(
Alexander Hansen5622ee92025-02-18 14:13:30 +0100105 componentImage, componentImageSize, componentVersion, applyTime);
Alexander Hansencc372352025-01-14 14:15:39 +0100106
Alexander Hansen5622ee92025-02-18 14:13:30 +0100107 if (!success)
Alexander Hansencc372352025-01-14 14:15:39 +0100108 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100109 softwarePending->setActivation(ActivationFailed);
Alexander Hansencc372352025-01-14 14:15:39 +0100110 error("Failed to update the software for {SWID}", "SWID",
111 softwareCurrent->swid);
Alexander Hansen5622ee92025-02-18 14:13:30 +0100112
113 softwarePending = std::move(softwarePendingOld);
114
115 co_return false;
116 }
117
118 if (applyTime == RequestedApplyTimes::Immediate)
119 {
120 softwareCurrent = std::move(softwarePending);
121
122 // In case an immediate update is triggered after an update for
123 // onReset.
124 softwarePending = nullptr;
125
126 debug("Successfully updated to software version {SWID}", "SWID",
127 softwareCurrent->swid);
Alexander Hansencc372352025-01-14 14:15:39 +0100128 }
129
Alexander Hansen5622ee92025-02-18 14:13:30 +0100130 co_return true;
Alexander Hansencc372352025-01-14 14:15:39 +0100131}
132
133std::string Device::getEMConfigType() const
134{
135 return config.configType;
136}
137
138// NOLINTBEGIN(readability-static-accessed-through-instance)
139sdbusplus::async::task<bool> Device::resetDevice()
140// NOLINTEND(readability-static-accessed-through-instance)
141{
142 debug("Default implementation for device reset");
143
144 co_return true;
145}
146
147bool Device::setUpdateProgress(uint8_t progress) const
148{
149 if (!softwarePending || !softwarePending->softwareActivationProgress)
150 {
151 return false;
152 }
153
154 softwarePending->softwareActivationProgress->setProgress(progress);
155
156 return true;
157}
158
159// NOLINTBEGIN(readability-static-accessed-through-instance)
160sdbusplus::async::task<bool> Device::continueUpdateWithMappedPackage(
161 const uint8_t* matchingComponentImage, size_t componentImageSize,
Alexander Hansen5622ee92025-02-18 14:13:30 +0100162 const std::string& componentVersion, RequestedApplyTimes applyTime)
Alexander Hansencc372352025-01-14 14:15:39 +0100163// NOLINTEND(readability-static-accessed-through-instance)
164{
Alexander Hansen5622ee92025-02-18 14:13:30 +0100165 softwarePending->setActivation(ActivationInterface::Activations::Ready);
Alexander Hansencc372352025-01-14 14:15:39 +0100166
Alexander Hansende5e76f2025-02-20 16:30:11 +0100167 softwarePending->setVersion(componentVersion,
168 softwareCurrent->getPurpose());
Alexander Hansencc372352025-01-14 14:15:39 +0100169
Alexander Hansen5622ee92025-02-18 14:13:30 +0100170 std::string objPath = softwarePending->objectPath;
Alexander Hansencc372352025-01-14 14:15:39 +0100171
Alexander Hansen5622ee92025-02-18 14:13:30 +0100172 softwarePending->softwareActivationProgress =
Alexander Hansencc372352025-01-14 14:15:39 +0100173 std::make_unique<SoftwareActivationProgress>(ctx, objPath.c_str());
174
Alexander Hansen5622ee92025-02-18 14:13:30 +0100175 softwarePending->setActivationBlocksTransition(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100176
Alexander Hansen5622ee92025-02-18 14:13:30 +0100177 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100178 ActivationInterface::Activations::Activating);
179
180 bool success =
181 co_await updateDevice(matchingComponentImage, componentImageSize);
182
183 if (success)
184 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100185 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100186 ActivationInterface::Activations::Active);
187 }
188
Alexander Hansen5622ee92025-02-18 14:13:30 +0100189 softwarePending->setActivationBlocksTransition(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100190
Alexander Hansen5622ee92025-02-18 14:13:30 +0100191 softwarePending->softwareActivationProgress = nullptr;
Alexander Hansencc372352025-01-14 14:15:39 +0100192
193 if (!success)
194 {
195 // do not apply the update, it has failed.
196 // We can delete the new software version.
197
198 co_return false;
199 }
200
201 if (applyTime == applyTimeImmediate)
202 {
203 co_await resetDevice();
204
Alexander Hansen5622ee92025-02-18 14:13:30 +0100205 co_await softwarePending->createInventoryAssociations(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100206
Alexander Hansen5622ee92025-02-18 14:13:30 +0100207 softwarePending->enableUpdate(allowedApplyTimes);
Alexander Hansencc372352025-01-14 14:15:39 +0100208 }
209 else
210 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100211 co_await softwarePending->createInventoryAssociations(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100212 }
213
214 co_return true;
215}