xref: /openbmc/phosphor-bmc-code-mgmt/test/common/exampledevice/example_device.cpp (revision d880e4d1c5ad728d19fec1059420277520098d39)
1 #include "example_device.hpp"
2 
3 #include "common/include/device.hpp"
4 #include "common/include/software_config.hpp"
5 #include "common/include/software_manager.hpp"
6 
7 #include <phosphor-logging/lg2.hpp>
8 #include <sdbusplus/asio/connection.hpp>
9 #include <sdbusplus/asio/object_server.hpp>
10 #include <sdbusplus/async.hpp>
11 #include <sdbusplus/server.hpp>
12 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
13 #include <xyz/openbmc_project/Software/Update/server.hpp>
14 
15 #include <memory>
16 
17 PHOSPHOR_LOG2_USING;
18 
19 using namespace phosphor::software;
20 using namespace phosphor::software::config;
21 using namespace phosphor::software::manager;
22 using namespace phosphor::software::device;
23 using namespace phosphor::software::example_device;
24 
25 SoftwareConfig ExampleDevice::defaultConfig =
26     SoftwareConfig(exampleInvObjPath, exampleVendorIANA,
27                    exampleCompatibleHardware, "Nop", exampleName);
28 
getRandomId()29 long ExampleCodeUpdater::getRandomId()
30 {
31     struct timespec ts;
32     clock_gettime(CLOCK_REALTIME, &ts);
33     unsigned int seed = ts.tv_nsec ^ getpid();
34     srandom(seed);
35     return random() % 10000;
36 }
37 
38 // nop code updater needs unique suffix on dbus for parallel unit testing
ExampleCodeUpdater(sdbusplus::async::context & ctx,long uniqueSuffix)39 ExampleCodeUpdater::ExampleCodeUpdater(sdbusplus::async::context& ctx,
40                                        long uniqueSuffix) :
41     SoftwareManager(ctx, "ExampleUpdater" + std::to_string(uniqueSuffix))
42 {}
43 
ExampleCodeUpdater(sdbusplus::async::context & ctx,bool createDevice,const char * swVersion)44 ExampleCodeUpdater::ExampleCodeUpdater(
45     sdbusplus::async::context& ctx, bool createDevice, const char* swVersion) :
46     ExampleCodeUpdater(ctx)
47 {
48     if (!createDevice)
49     {
50         return;
51     }
52     const std::string exampleInvObjPath =
53         "/xyz/openbmc_project/inventory/system/board/ExampleBoard/ExampleDevice";
54     auto exampleDevice = std::make_unique<ExampleDevice>(ctx, &(*this));
55 
56     devices.insert({exampleInvObjPath, std::move(exampleDevice)});
57 
58     if (swVersion)
59     {
60         auto& device = getDevice();
61         device->softwareCurrent =
62             std::make_unique<ExampleSoftware>(ctx, *device);
63         device->softwareCurrent->setVersion(swVersion);
64     }
65 }
66 
getDevice()67 std::unique_ptr<ExampleDevice>& ExampleCodeUpdater::getDevice()
68 {
69     if (devices.empty())
70     {
71         throw std::invalid_argument(
72             "could not find any device, example CU wrongly initialized");
73     }
74 
75     auto& deviceRef = devices.begin()->second;
76 
77     return reinterpret_cast<std::unique_ptr<ExampleDevice>&>(deviceRef);
78 }
79 
initDevice(const std::string &,const std::string &,SoftwareConfig &)80 sdbusplus::async::task<bool> ExampleCodeUpdater::initDevice(
81     const std::string& /*unused*/, const std::string& /*unused*/,
82     SoftwareConfig& /*unused*/)
83 {
84     auto device = std::make_unique<ExampleDevice>(ctx, this);
85 
86     device->softwareCurrent = std::make_unique<ExampleSoftware>(ctx, *device);
87 
88     device->softwareCurrent->setVersion("v1.0",
89                                         SoftwareVersion::VersionPurpose::Other);
90     device->softwareCurrent->setActivation(
91         SoftwareActivation::Activations::Active);
92 
93     auto applyTimes = {RequestedApplyTimes::OnReset};
94     device->softwareCurrent->enableUpdate(applyTimes);
95 
96     devices.insert({exampleInvObjPath, std::move(device)});
97 
98     co_return true;
99 }
100 
ExampleDevice(sdbusplus::async::context & ctx,SoftwareManager * parent,const SoftwareConfig & config)101 ExampleDevice::ExampleDevice(sdbusplus::async::context& ctx,
102                              SoftwareManager* parent,
103                              const SoftwareConfig& config) :
104     Device(ctx, config, parent,
105            {RequestedApplyTimes::Immediate, RequestedApplyTimes::OnReset})
106 {}
107 
updateDevice(const uint8_t *,size_t compImageSize)108 sdbusplus::async::task<bool> ExampleDevice::updateDevice(
109     const uint8_t* /*unused*/, size_t compImageSize)
110 {
111     debug("Called device specific update function with image size {SIZE}",
112           "SIZE", compImageSize);
113 
114     deviceSpecificUpdateFunctionCalled = true;
115 
116     // Setting this property for demonstration purpose.
117     // For a real device, this could represent the
118     // percentage completion of writing the firmware,
119     // and any progress made in the update process within this function.
120     // There is no hard constraint on the values here,
121     // we do not have to reach any specific percentage.
122     // The percentage should be monotonic and increasing.
123     for (auto progress = 0; progress <= 100; progress += 20)
124     {
125         setUpdateProgress(progress);
126     }
127 
128     co_return true;
129 }
130 
ExampleSoftware(sdbusplus::async::context & ctx,ExampleDevice & parent)131 ExampleSoftware::ExampleSoftware(sdbusplus::async::context& ctx,
132                                  ExampleDevice& parent) : Software(ctx, parent)
133 {}
134