blob: 1e4b81092d000914a8bd93a5f1bdf7ac8b2546f8 [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>
Alexander Hansendf628192025-06-18 16:28:59 +020012#include <xyz/openbmc_project/Software/ActivationProgress/aserver.hpp>
Alexander Hansencc372352025-01-14 14:15:39 +010013#include <xyz/openbmc_project/State/Host/client.hpp>
14
15#include <utility>
16
17PHOSPHOR_LOG2_USING;
18
19using namespace phosphor::software::device;
20
Alexander Hansendf628192025-06-18 16:28:59 +020021using SoftwareActivationProgress =
22 sdbusplus::aserver::xyz::openbmc_project::software::ActivationProgress<
23 phosphor::software::Software>;
24
25using SoftwareActivationProgressProperties = sdbusplus::common::xyz::
26 openbmc_project::software::ActivationProgress::properties_t;
27
Alexander Hansencc372352025-01-14 14:15:39 +010028const auto applyTimeImmediate = sdbusplus::common::xyz::openbmc_project::
29 software::ApplyTime::RequestedApplyTimes::Immediate;
30
31const auto ActivationInvalid = ActivationInterface::Activations::Invalid;
32const auto ActivationFailed = ActivationInterface::Activations::Failed;
33
34Device::Device(sdbusplus::async::context& ctx, const SoftwareConfig& config,
35 manager::SoftwareManager* parent,
36 std::set<RequestedApplyTimes> allowedApplyTimes =
37 {RequestedApplyTimes::Immediate,
38 RequestedApplyTimes::OnReset}) :
39 allowedApplyTimes(std::move(allowedApplyTimes)), config(config),
40 parent(parent), ctx(ctx)
41{}
42
Alexander Hansencc372352025-01-14 14:15:39 +010043sdbusplus::async::task<bool> Device::getImageInfo(
44 std::unique_ptr<void, std::function<void(void*)>>& pldmPackage,
45 size_t pldmPackageSize, uint8_t** matchingComponentImage,
46 size_t* componentImageSize, std::string& componentVersion)
47
Alexander Hansencc372352025-01-14 14:15:39 +010048{
49 std::shared_ptr<PackageParser> packageParser =
50 pldm_package_util::parsePLDMPackage(
51 static_cast<uint8_t*>(pldmPackage.get()), pldmPackageSize);
52
53 if (packageParser == nullptr)
54 {
55 error("could not parse PLDM package");
56 co_return false;
57 }
58
59 uint32_t componentOffset = 0;
60 const int status = pldm_package_util::extractMatchingComponentImage(
61 packageParser, config.compatibleHardware, config.vendorIANA,
62 &componentOffset, componentImageSize, componentVersion);
63
64 if (status != 0)
65 {
66 error("could not extract matching component image");
67 co_return false;
68 }
69
70 *matchingComponentImage =
71 static_cast<uint8_t*>(pldmPackage.get()) + componentOffset;
72
73 co_return true;
74}
75
Alexander Hansencc372352025-01-14 14:15:39 +010076sdbusplus::async::task<bool> Device::startUpdateAsync(
77 sdbusplus::message::unix_fd image, RequestedApplyTimes applyTime,
78 std::unique_ptr<Software> softwarePendingIn)
Alexander Hansencc372352025-01-14 14:15:39 +010079{
80 debug("starting the async update with memfd {FD}", "FD", image.fd);
81
82 size_t pldm_pkg_size = 0;
83 auto pldm_pkg = pldm_package_util::mmapImagePackage(image, &pldm_pkg_size);
84
85 if (pldm_pkg == nullptr)
86 {
87 softwarePendingIn->setActivation(ActivationInvalid);
88 co_return false;
89 }
90
91 uint8_t* componentImage;
92 size_t componentImageSize = 0;
93 std::string componentVersion;
94
95 if (!co_await getImageInfo(pldm_pkg, pldm_pkg_size, &componentImage,
96 &componentImageSize, componentVersion))
97 {
98 error("could not extract matching component image");
99 softwarePendingIn->setActivation(ActivationInvalid);
100 co_return false;
101 }
102
Alexander Hansen5622ee92025-02-18 14:13:30 +0100103 std::unique_ptr<Software> softwarePendingOld = std::move(softwarePending);
104
105 softwarePending = std::move(softwarePendingIn);
106 softwarePendingIn = nullptr;
107
Alexander Hansencc372352025-01-14 14:15:39 +0100108 const bool success = co_await continueUpdateWithMappedPackage(
Alexander Hansen5622ee92025-02-18 14:13:30 +0100109 componentImage, componentImageSize, componentVersion, applyTime);
Alexander Hansencc372352025-01-14 14:15:39 +0100110
Alexander Hansen5622ee92025-02-18 14:13:30 +0100111 if (!success)
Alexander Hansencc372352025-01-14 14:15:39 +0100112 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100113 softwarePending->setActivation(ActivationFailed);
Alexander Hansencc372352025-01-14 14:15:39 +0100114 error("Failed to update the software for {SWID}", "SWID",
115 softwareCurrent->swid);
Alexander Hansen5622ee92025-02-18 14:13:30 +0100116
117 softwarePending = std::move(softwarePendingOld);
118
119 co_return false;
120 }
121
122 if (applyTime == RequestedApplyTimes::Immediate)
123 {
124 softwareCurrent = std::move(softwarePending);
125
126 // In case an immediate update is triggered after an update for
127 // onReset.
128 softwarePending = nullptr;
129
130 debug("Successfully updated to software version {SWID}", "SWID",
131 softwareCurrent->swid);
Alexander Hansencc372352025-01-14 14:15:39 +0100132 }
133
Alexander Hansen5622ee92025-02-18 14:13:30 +0100134 co_return true;
Alexander Hansencc372352025-01-14 14:15:39 +0100135}
136
137std::string Device::getEMConfigType() const
138{
139 return config.configType;
140}
141
Alexander Hansencc372352025-01-14 14:15:39 +0100142sdbusplus::async::task<bool> Device::resetDevice()
Alexander Hansencc372352025-01-14 14:15:39 +0100143{
144 debug("Default implementation for device reset");
145
146 co_return true;
147}
148
149bool Device::setUpdateProgress(uint8_t progress) const
150{
151 if (!softwarePending || !softwarePending->softwareActivationProgress)
152 {
153 return false;
154 }
155
Alexander Hansendf628192025-06-18 16:28:59 +0200156 softwarePending->softwareActivationProgress->progress(progress);
Alexander Hansencc372352025-01-14 14:15:39 +0100157
158 return true;
159}
160
Alexander Hansencc372352025-01-14 14:15:39 +0100161sdbusplus::async::task<bool> Device::continueUpdateWithMappedPackage(
162 const uint8_t* matchingComponentImage, size_t componentImageSize,
Alexander Hansen5622ee92025-02-18 14:13:30 +0100163 const std::string& componentVersion, RequestedApplyTimes applyTime)
Alexander Hansencc372352025-01-14 14:15:39 +0100164{
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 Hansendf628192025-06-18 16:28:59 +0200173 std::make_unique<SoftwareActivationProgress>(
174 ctx, objPath.c_str(), SoftwareActivationProgressProperties{0});
Alexander Hansencc372352025-01-14 14:15:39 +0100175
Alexander Hansen5622ee92025-02-18 14:13:30 +0100176 softwarePending->setActivationBlocksTransition(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100177
Alexander Hansen5622ee92025-02-18 14:13:30 +0100178 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100179 ActivationInterface::Activations::Activating);
180
181 bool success =
182 co_await updateDevice(matchingComponentImage, componentImageSize);
183
184 if (success)
185 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100186 softwarePending->setActivation(
Alexander Hansencc372352025-01-14 14:15:39 +0100187 ActivationInterface::Activations::Active);
188 }
189
Alexander Hansen5622ee92025-02-18 14:13:30 +0100190 softwarePending->setActivationBlocksTransition(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100191
Alexander Hansen5622ee92025-02-18 14:13:30 +0100192 softwarePending->softwareActivationProgress = nullptr;
Alexander Hansencc372352025-01-14 14:15:39 +0100193
194 if (!success)
195 {
196 // do not apply the update, it has failed.
197 // We can delete the new software version.
198
199 co_return false;
200 }
201
202 if (applyTime == applyTimeImmediate)
203 {
204 co_await resetDevice();
205
Alexander Hansen5622ee92025-02-18 14:13:30 +0100206 co_await softwarePending->createInventoryAssociations(true);
Alexander Hansencc372352025-01-14 14:15:39 +0100207
Alexander Hansen5622ee92025-02-18 14:13:30 +0100208 softwarePending->enableUpdate(allowedApplyTimes);
Alexander Hansencc372352025-01-14 14:15:39 +0100209 }
210 else
211 {
Alexander Hansen5622ee92025-02-18 14:13:30 +0100212 co_await softwarePending->createInventoryAssociations(false);
Alexander Hansencc372352025-01-14 14:15:39 +0100213 }
214
215 co_return true;
216}