blob: b71b2cb47eac1754a6c48d3b128f0d8062b490e1 [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
Alexander Hansencc372352025-01-14 14:15:39 +010035sdbusplus::async::task<bool> Device::getImageInfo(
36 std::unique_ptr<void, std::function<void(void*)>>& pldmPackage,
37 size_t pldmPackageSize, uint8_t** matchingComponentImage,
38 size_t* componentImageSize, std::string& componentVersion)
39
Alexander Hansencc372352025-01-14 14:15:39 +010040{
41 std::shared_ptr<PackageParser> packageParser =
42 pldm_package_util::parsePLDMPackage(
43 static_cast<uint8_t*>(pldmPackage.get()), pldmPackageSize);
44
45 if (packageParser == nullptr)
46 {
47 error("could not parse PLDM package");
48 co_return false;
49 }
50
51 uint32_t componentOffset = 0;
52 const int status = pldm_package_util::extractMatchingComponentImage(
53 packageParser, config.compatibleHardware, config.vendorIANA,
54 &componentOffset, componentImageSize, componentVersion);
55
56 if (status != 0)
57 {
58 error("could not extract matching component image");
59 co_return false;
60 }
61
62 *matchingComponentImage =
63 static_cast<uint8_t*>(pldmPackage.get()) + componentOffset;
64
65 co_return true;
66}
67
Alexander Hansencc372352025-01-14 14:15:39 +010068sdbusplus::async::task<bool> Device::startUpdateAsync(
69 sdbusplus::message::unix_fd image, RequestedApplyTimes applyTime,
70 std::unique_ptr<Software> softwarePendingIn)
Alexander Hansencc372352025-01-14 14:15:39 +010071{
72 debug("starting the async update with memfd {FD}", "FD", image.fd);
73
74 size_t pldm_pkg_size = 0;
75 auto pldm_pkg = pldm_package_util::mmapImagePackage(image, &pldm_pkg_size);
76
77 if (pldm_pkg == nullptr)
78 {
79 softwarePendingIn->setActivation(ActivationInvalid);
80 co_return false;
81 }
82
83 uint8_t* componentImage;
84 size_t componentImageSize = 0;
85 std::string componentVersion;
86
87 if (!co_await getImageInfo(pldm_pkg, pldm_pkg_size, &componentImage,
88 &componentImageSize, componentVersion))
89 {
90 error("could not extract matching component image");
91 softwarePendingIn->setActivation(ActivationInvalid);
92 co_return false;
93 }
94
Alexander Hansen5622ee92025-02-18 14:13:30 +010095 std::unique_ptr<Software> softwarePendingOld = std::move(softwarePending);
96
97 softwarePending = std::move(softwarePendingIn);
98 softwarePendingIn = nullptr;
99
Alexander Hansencc372352025-01-14 14:15:39 +0100100 const bool success = co_await continueUpdateWithMappedPackage(
Alexander Hansen5622ee92025-02-18 14:13:30 +0100101 componentImage, componentImageSize, componentVersion, applyTime);
Alexander Hansencc372352025-01-14 14:15:39 +0100102
Alexander Hansen5622ee92025-02-18 14:13:30 +0100103 if (!success)
Alexander Hansencc372352025-01-14 14:15:39 +0100104 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100105 softwarePending->setActivation(ActivationFailed);
Alexander Hansencc372352025-01-14 14:15:39 +0100106 error("Failed to update the software for {SWID}", "SWID",
107 softwareCurrent->swid);
Alexander Hansen5622ee92025-02-18 14:13:30 +0100108
109 softwarePending = std::move(softwarePendingOld);
110
111 co_return false;
112 }
113
114 if (applyTime == RequestedApplyTimes::Immediate)
115 {
116 softwareCurrent = std::move(softwarePending);
117
118 // In case an immediate update is triggered after an update for
119 // onReset.
120 softwarePending = nullptr;
121
122 debug("Successfully updated to software version {SWID}", "SWID",
123 softwareCurrent->swid);
Alexander Hansencc372352025-01-14 14:15:39 +0100124 }
125
Alexander Hansen5622ee92025-02-18 14:13:30 +0100126 co_return true;
Alexander Hansencc372352025-01-14 14:15:39 +0100127}
128
129std::string Device::getEMConfigType() const
130{
131 return config.configType;
132}
133
Alexander Hansencc372352025-01-14 14:15:39 +0100134sdbusplus::async::task<bool> Device::resetDevice()
Alexander Hansencc372352025-01-14 14:15:39 +0100135{
136 debug("Default implementation for device reset");
137
138 co_return true;
139}
140
141bool Device::setUpdateProgress(uint8_t progress) const
142{
143 if (!softwarePending || !softwarePending->softwareActivationProgress)
144 {
145 return false;
146 }
147
148 softwarePending->softwareActivationProgress->setProgress(progress);
149
150 return true;
151}
152
Alexander Hansencc372352025-01-14 14:15:39 +0100153sdbusplus::async::task<bool> Device::continueUpdateWithMappedPackage(
154 const uint8_t* matchingComponentImage, size_t componentImageSize,
Alexander Hansen5622ee92025-02-18 14:13:30 +0100155 const std::string& componentVersion, RequestedApplyTimes applyTime)
Alexander Hansencc372352025-01-14 14:15:39 +0100156{
Alexander Hansen5622ee92025-02-18 14:13:30 +0100157 softwarePending->setActivation(ActivationInterface::Activations::Ready);
Alexander Hansencc372352025-01-14 14:15:39 +0100158
Alexander Hansende5e76f2025-02-20 16:30:11 +0100159 softwarePending->setVersion(componentVersion,
160 softwareCurrent->getPurpose());
Alexander Hansencc372352025-01-14 14:15:39 +0100161
Alexander Hansen5622ee92025-02-18 14:13:30 +0100162 std::string objPath = softwarePending->objectPath;
Alexander Hansencc372352025-01-14 14:15:39 +0100163
Alexander Hansen5622ee92025-02-18 14:13:30 +0100164 softwarePending->softwareActivationProgress =
Alexander Hansencc372352025-01-14 14:15:39 +0100165 std::make_unique<SoftwareActivationProgress>(ctx, objPath.c_str());
166
Alexander Hansen5622ee92025-02-18 14:13:30 +0100167 softwarePending->setActivationBlocksTransition(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100168
Alexander Hansen5622ee92025-02-18 14:13:30 +0100169 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100170 ActivationInterface::Activations::Activating);
171
172 bool success =
173 co_await updateDevice(matchingComponentImage, componentImageSize);
174
175 if (success)
176 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100177 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100178 ActivationInterface::Activations::Active);
179 }
180
Alexander Hansen5622ee92025-02-18 14:13:30 +0100181 softwarePending->setActivationBlocksTransition(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100182
Alexander Hansen5622ee92025-02-18 14:13:30 +0100183 softwarePending->softwareActivationProgress = nullptr;
Alexander Hansencc372352025-01-14 14:15:39 +0100184
185 if (!success)
186 {
187 // do not apply the update, it has failed.
188 // We can delete the new software version.
189
190 co_return false;
191 }
192
193 if (applyTime == applyTimeImmediate)
194 {
195 co_await resetDevice();
196
Alexander Hansen5622ee92025-02-18 14:13:30 +0100197 co_await softwarePending->createInventoryAssociations(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100198
Alexander Hansen5622ee92025-02-18 14:13:30 +0100199 softwarePending->enableUpdate(allowedApplyTimes);
Alexander Hansencc372352025-01-14 14:15:39 +0100200 }
201 else
202 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100203 co_await softwarePending->createInventoryAssociations(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100204 }
205
206 co_return true;
207}