xref: /openbmc/phosphor-modbus/rtu/firmware/device_firmware.cpp (revision cf77ef540b925e10e3078bbdfbd795a0c1d9ff1f)
1*cf77ef54SJagpal Singh Gill #include "device_firmware.hpp"
2*cf77ef54SJagpal Singh Gill 
3*cf77ef54SJagpal Singh Gill #include "device/base_device.hpp"
4*cf77ef54SJagpal Singh Gill 
5*cf77ef54SJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
6*cf77ef54SJagpal Singh Gill 
7*cf77ef54SJagpal Singh Gill namespace phosphor::modbus::rtu::device
8*cf77ef54SJagpal Singh Gill {
9*cf77ef54SJagpal Singh Gill 
10*cf77ef54SJagpal Singh Gill PHOSPHOR_LOG2_USING;
11*cf77ef54SJagpal Singh Gill 
getRandomId()12*cf77ef54SJagpal Singh Gill static auto getRandomId() -> long int
13*cf77ef54SJagpal Singh Gill {
14*cf77ef54SJagpal Singh Gill     struct timespec ts;
15*cf77ef54SJagpal Singh Gill     clock_gettime(CLOCK_REALTIME, &ts);
16*cf77ef54SJagpal Singh Gill     unsigned int seed = ts.tv_nsec ^ getpid();
17*cf77ef54SJagpal Singh Gill     srandom(seed);
18*cf77ef54SJagpal Singh Gill     return random() % 10000;
19*cf77ef54SJagpal Singh Gill }
20*cf77ef54SJagpal Singh Gill 
getObjectPath(const config_intf::Config & config)21*cf77ef54SJagpal Singh Gill static auto getObjectPath(const config_intf::Config& config)
22*cf77ef54SJagpal Singh Gill     -> sdbusplus::message::object_path
23*cf77ef54SJagpal Singh Gill {
24*cf77ef54SJagpal Singh Gill     for (const auto& firmwareRegister : config.firmwareRegisters)
25*cf77ef54SJagpal Singh Gill     {
26*cf77ef54SJagpal Singh Gill         if (firmwareRegister.type == config_intf::FirmwareRegisterType::version)
27*cf77ef54SJagpal Singh Gill         {
28*cf77ef54SJagpal Singh Gill             if (firmwareRegister.name.empty())
29*cf77ef54SJagpal Singh Gill             {
30*cf77ef54SJagpal Singh Gill                 return sdbusplus::message::object_path(
31*cf77ef54SJagpal Singh Gill                            FirmwareIntf::namespace_path) /
32*cf77ef54SJagpal Singh Gill                        std::format("{}_{}", config.name, getRandomId());
33*cf77ef54SJagpal Singh Gill             }
34*cf77ef54SJagpal Singh Gill             else
35*cf77ef54SJagpal Singh Gill             {
36*cf77ef54SJagpal Singh Gill                 return sdbusplus::message::object_path(
37*cf77ef54SJagpal Singh Gill                            FirmwareIntf::namespace_path) /
38*cf77ef54SJagpal Singh Gill                        std::format("{}_{}_{}", config.name,
39*cf77ef54SJagpal Singh Gill                                    firmwareRegister.name, getRandomId());
40*cf77ef54SJagpal Singh Gill             }
41*cf77ef54SJagpal Singh Gill         }
42*cf77ef54SJagpal Singh Gill     }
43*cf77ef54SJagpal Singh Gill 
44*cf77ef54SJagpal Singh Gill     throw std::runtime_error(
45*cf77ef54SJagpal Singh Gill         "No firmware version register found for " + config.name);
46*cf77ef54SJagpal Singh Gill }
47*cf77ef54SJagpal Singh Gill 
48*cf77ef54SJagpal Singh Gill constexpr FirmwareIntf::Version::properties_t initVersion{
49*cf77ef54SJagpal Singh Gill     "Unknown", FirmwareIntf::VersionPurpose::Other};
50*cf77ef54SJagpal Singh Gill constexpr FirmwareIntf::Activation::properties_t initActivation{
51*cf77ef54SJagpal Singh Gill     FirmwareIntf::Activations::NotReady,
52*cf77ef54SJagpal Singh Gill     FirmwareIntf::RequestedActivations::None};
53*cf77ef54SJagpal Singh Gill constexpr FirmwareIntf::Definitions::properties_t initAssociations{};
54*cf77ef54SJagpal Singh Gill 
DeviceFirmware(sdbusplus::async::context & ctx,const config_intf::Config & config,PortIntf & serialPort)55*cf77ef54SJagpal Singh Gill DeviceFirmware::DeviceFirmware(sdbusplus::async::context& ctx,
56*cf77ef54SJagpal Singh Gill                                const config_intf::Config& config,
57*cf77ef54SJagpal Singh Gill                                PortIntf& serialPort) :
58*cf77ef54SJagpal Singh Gill     objectPath(getObjectPath(config)),
59*cf77ef54SJagpal Singh Gill     currentFirmware(
60*cf77ef54SJagpal Singh Gill         std::make_unique<FirmwareIntf>(ctx, objectPath.str.c_str(), initVersion,
61*cf77ef54SJagpal Singh Gill                                        initActivation, initAssociations)),
62*cf77ef54SJagpal Singh Gill     config(config), serialPort(serialPort)
63*cf77ef54SJagpal Singh Gill {
64*cf77ef54SJagpal Singh Gill     currentFirmware->Version::emit_added();
65*cf77ef54SJagpal Singh Gill     currentFirmware->Activation::emit_added();
66*cf77ef54SJagpal Singh Gill     currentFirmware->Definitions::emit_added();
67*cf77ef54SJagpal Singh Gill 
68*cf77ef54SJagpal Singh Gill     info("Device firmware {NAME} created successfully", "NAME", config.name);
69*cf77ef54SJagpal Singh Gill }
70*cf77ef54SJagpal Singh Gill 
readVersionRegister()71*cf77ef54SJagpal Singh Gill auto DeviceFirmware::readVersionRegister() -> sdbusplus::async::task<void>
72*cf77ef54SJagpal Singh Gill {
73*cf77ef54SJagpal Singh Gill     const auto it = std::find_if(
74*cf77ef54SJagpal Singh Gill         config.firmwareRegisters.begin(), config.firmwareRegisters.end(),
75*cf77ef54SJagpal Singh Gill         [](const config_intf::FirmwareRegister& firmwareRegister) {
76*cf77ef54SJagpal Singh Gill             return firmwareRegister.type ==
77*cf77ef54SJagpal Singh Gill                    config_intf::FirmwareRegisterType::version;
78*cf77ef54SJagpal Singh Gill         });
79*cf77ef54SJagpal Singh Gill 
80*cf77ef54SJagpal Singh Gill     if (it == config.firmwareRegisters.end())
81*cf77ef54SJagpal Singh Gill     {
82*cf77ef54SJagpal Singh Gill         error("No firmware version register found for {NAME}", "NAME",
83*cf77ef54SJagpal Singh Gill               config.name);
84*cf77ef54SJagpal Singh Gill         co_return;
85*cf77ef54SJagpal Singh Gill     }
86*cf77ef54SJagpal Singh Gill 
87*cf77ef54SJagpal Singh Gill     const config_intf::FirmwareRegister& versionRegister = *it;
88*cf77ef54SJagpal Singh Gill 
89*cf77ef54SJagpal Singh Gill     auto registers = std::vector<uint16_t>(versionRegister.size);
90*cf77ef54SJagpal Singh Gill     auto ret = co_await serialPort.readHoldingRegisters(
91*cf77ef54SJagpal Singh Gill         config.address, versionRegister.offset, config.baudRate, config.parity,
92*cf77ef54SJagpal Singh Gill         registers);
93*cf77ef54SJagpal Singh Gill     if (!ret)
94*cf77ef54SJagpal Singh Gill     {
95*cf77ef54SJagpal Singh Gill         error("Failed to read holding registers {NAME} for {DEVICE_ADDRESS}",
96*cf77ef54SJagpal Singh Gill               "NAME", versionRegister.name, "DEVICE_ADDRESS", config.address);
97*cf77ef54SJagpal Singh Gill         co_return;
98*cf77ef54SJagpal Singh Gill     }
99*cf77ef54SJagpal Singh Gill 
100*cf77ef54SJagpal Singh Gill     std::string strValue = "";
101*cf77ef54SJagpal Singh Gill 
102*cf77ef54SJagpal Singh Gill     for (const auto& value : registers)
103*cf77ef54SJagpal Singh Gill     {
104*cf77ef54SJagpal Singh Gill         strValue += static_cast<char>((value >> 8) & 0xFF);
105*cf77ef54SJagpal Singh Gill         strValue += static_cast<char>(value & 0xFF);
106*cf77ef54SJagpal Singh Gill     }
107*cf77ef54SJagpal Singh Gill 
108*cf77ef54SJagpal Singh Gill     currentFirmware->version(strValue);
109*cf77ef54SJagpal Singh Gill     currentFirmware->activation(FirmwareIntf::Activation::Activations::Active);
110*cf77ef54SJagpal Singh Gill     auto associationList =
111*cf77ef54SJagpal Singh Gill         std::vector<std::tuple<std::string, std::string, std::string>>{
112*cf77ef54SJagpal Singh Gill             {"running", "ran_on", config.inventoryPath}};
113*cf77ef54SJagpal Singh Gill     currentFirmware->associations(associationList);
114*cf77ef54SJagpal Singh Gill 
115*cf77ef54SJagpal Singh Gill     info("Firmware version {VERSION} for {NAME} at {DEVICE_ADDRESS}", "VERSION",
116*cf77ef54SJagpal Singh Gill          strValue, "NAME", config.name, "DEVICE_ADDRESS", config.address);
117*cf77ef54SJagpal Singh Gill }
118*cf77ef54SJagpal Singh Gill 
119*cf77ef54SJagpal Singh Gill } // namespace phosphor::modbus::rtu::device
120