blob: df964a252bf337b316f3370ded2b881b1439e7cb [file] [log] [blame]
Alexander Hansencc372352025-01-14 14:15:39 +01001#include "software_update.hpp"
2
3#include "device.hpp"
4#include "software.hpp"
5
6#include <phosphor-logging/elog-errors.hpp>
7#include <phosphor-logging/elog.hpp>
8#include <phosphor-logging/lg2.hpp>
9#include <sdbusplus/async/context.hpp>
10#include <xyz/openbmc_project/Software/Update/aserver.hpp>
11
12PHOSPHOR_LOG2_USING;
13
14using Unavailable = sdbusplus::xyz::openbmc_project::Common::Error::Unavailable;
15
16using namespace phosphor::logging;
17using namespace phosphor::software::update;
18using namespace phosphor::software::device;
19using namespace phosphor::software;
20
21namespace SoftwareLogging = phosphor::logging::xyz::openbmc_project::software;
22namespace SoftwareErrors =
23 sdbusplus::error::xyz::openbmc_project::software::image;
24
25SoftwareUpdate::SoftwareUpdate(
26 sdbusplus::async::context& ctx, const char* path, Software& software,
27 const std::set<RequestedApplyTimes>& allowedApplyTimes) :
28 sdbusplus::aserver::xyz::openbmc_project::software::Update<SoftwareUpdate>(
29 ctx, path),
30 software(software), allowedApplyTimes(allowedApplyTimes)
Alexander Hansen8b4ab1e2025-04-10 14:25:53 +020031{
32 emit_added();
33}
34
35SoftwareUpdate::~SoftwareUpdate()
36{
37 emit_removed();
38}
Alexander Hansencc372352025-01-14 14:15:39 +010039
40auto SoftwareUpdate::method_call(start_update_t /*unused*/, auto image,
41 auto applyTime)
42 -> sdbusplus::async::task<start_update_t::return_type>
43{
44 debug("Requesting Image update with {FD}", "FD", image.fd);
45
46 Device& device = software.parentDevice;
47
48 if (device.updateInProgress)
49 {
50 error("An update is already in progress, cannot update.");
51 report<Unavailable>();
52 co_return sdbusplus::message::object_path();
53 }
54
55 device.updateInProgress = true;
56
57 // check if the apply time is allowed by our device
58 if (!allowedApplyTimes.contains(applyTime))
59 {
60 error(
61 "the selected apply time {APPLYTIME} is not allowed by the device",
62 "APPLYTIME", applyTime);
63 device.updateInProgress = false;
64 report<Unavailable>();
65 co_return sdbusplus::message::object_path();
66 }
67
68 debug("started asynchronous update with fd {FD}", "FD", image.fd);
69
70 int imageDup = dup(image.fd);
71
72 if (imageDup < 0)
73 {
74 error("ERROR calling dup on fd: {ERR}", "ERR", strerror(errno));
75 device.updateInProgress = false;
76 co_return software.objectPath;
77 }
78
79 debug("starting async update with FD: {FD}\n", "FD", imageDup);
80
81 std::unique_ptr<Software> softwareInstance =
82 std::make_unique<Software>(ctx, device);
83
84 softwareInstance->setActivation(ActivationInterface::Activations::NotReady);
85
86 std::string newObjPath = softwareInstance->objectPath;
87
88 // NOLINTBEGIN(readability-static-accessed-through-instance)
89 ctx.spawn(
90 [](Device& device, int imageDup, RequestedApplyTimes applyTime,
91 std::unique_ptr<Software> swupdate) -> sdbusplus::async::task<> {
92 co_await device.startUpdateAsync(imageDup, applyTime,
93 std::move(swupdate));
94 device.updateInProgress = false;
95 close(imageDup);
96 co_return;
97 }(device, imageDup, applyTime, std::move(softwareInstance)));
98 // NOLINTEND
99
100 // We need the object path for the new software here.
101 // It must be the same as constructed during the update process.
102 // This is so that bmcweb and redfish clients can keep track of the update
103 // process.
104 co_return newObjPath;
105}
106
107auto SoftwareUpdate::get_property(allowed_apply_times_t /*unused*/) const
108{
109 return allowedApplyTimes;
110}