blob: 23672134e6654c0da7405367596817ee6e5de16b [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 Hansen5622ee92025-02-18 14:13:30 +0100167 softwarePending->setVersion(componentVersion);
Alexander Hansencc372352025-01-14 14:15:39 +0100168
Alexander Hansen5622ee92025-02-18 14:13:30 +0100169 std::string objPath = softwarePending->objectPath;
Alexander Hansencc372352025-01-14 14:15:39 +0100170
Alexander Hansen5622ee92025-02-18 14:13:30 +0100171 softwarePending->softwareActivationProgress =
Alexander Hansencc372352025-01-14 14:15:39 +0100172 std::make_unique<SoftwareActivationProgress>(ctx, objPath.c_str());
173
Alexander Hansen5622ee92025-02-18 14:13:30 +0100174 softwarePending->setActivationBlocksTransition(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100175
Alexander Hansen5622ee92025-02-18 14:13:30 +0100176 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100177 ActivationInterface::Activations::Activating);
178
179 bool success =
180 co_await updateDevice(matchingComponentImage, componentImageSize);
181
182 if (success)
183 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100184 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100185 ActivationInterface::Activations::Active);
186 }
187
Alexander Hansen5622ee92025-02-18 14:13:30 +0100188 softwarePending->setActivationBlocksTransition(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100189
Alexander Hansen5622ee92025-02-18 14:13:30 +0100190 softwarePending->softwareActivationProgress = nullptr;
Alexander Hansencc372352025-01-14 14:15:39 +0100191
192 if (!success)
193 {
194 // do not apply the update, it has failed.
195 // We can delete the new software version.
196
197 co_return false;
198 }
199
200 if (applyTime == applyTimeImmediate)
201 {
202 co_await resetDevice();
203
Alexander Hansen5622ee92025-02-18 14:13:30 +0100204 co_await softwarePending->createInventoryAssociations(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100205
Alexander Hansen5622ee92025-02-18 14:13:30 +0100206 softwarePending->enableUpdate(allowedApplyTimes);
Alexander Hansencc372352025-01-14 14:15:39 +0100207 }
208 else
209 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100210 co_await softwarePending->createInventoryAssociations(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100211 }
212
213 co_return true;
214}