xref: /openbmc/phosphor-bmc-code-mgmt/eeprom-device/eeprom_device_software_manager.cpp (revision bd5081f0b99a27dde8101576524b2c02a4a580b6)
1994a77ffSKevin Tung #include "eeprom_device_software_manager.hpp"
2994a77ffSKevin Tung 
3994a77ffSKevin Tung #include "common/include/dbus_helper.hpp"
4994a77ffSKevin Tung #include "eeprom_device.hpp"
5994a77ffSKevin Tung 
6994a77ffSKevin Tung #include <phosphor-logging/lg2.hpp>
7994a77ffSKevin Tung #include <sdbusplus/async.hpp>
8994a77ffSKevin Tung #include <xyz/openbmc_project/ObjectMapper/client.hpp>
9994a77ffSKevin Tung 
10994a77ffSKevin Tung #include <fstream>
11994a77ffSKevin Tung #include <optional>
12994a77ffSKevin Tung #include <sstream>
13994a77ffSKevin Tung 
14994a77ffSKevin Tung PHOSPHOR_LOG2_USING;
15994a77ffSKevin Tung 
16994a77ffSKevin Tung namespace SoftwareInf = phosphor::software;
17994a77ffSKevin Tung 
18*30fd7e4cSKevin Tung const std::vector<std::string> emConfigTypes = {"PT5161LFirmware"};
19994a77ffSKevin Tung 
start()20994a77ffSKevin Tung void EEPROMDeviceSoftwareManager::start()
21994a77ffSKevin Tung {
22994a77ffSKevin Tung     std::vector<std::string> configIntfs;
23994a77ffSKevin Tung     configIntfs.reserve(emConfigTypes.size());
24994a77ffSKevin Tung 
25994a77ffSKevin Tung     std::transform(emConfigTypes.begin(), emConfigTypes.end(),
26994a77ffSKevin Tung                    std::back_inserter(configIntfs),
27994a77ffSKevin Tung                    [](const std::string& type) {
28994a77ffSKevin Tung                        return "xyz.openbmc_project.Configuration." + type;
29994a77ffSKevin Tung                    });
30994a77ffSKevin Tung 
31994a77ffSKevin Tung     ctx.spawn(initDevices(configIntfs));
32994a77ffSKevin Tung     ctx.run();
33994a77ffSKevin Tung }
34994a77ffSKevin Tung 
initDevice(const std::string & service,const std::string & path,SoftwareConfig & config)35994a77ffSKevin Tung sdbusplus::async::task<bool> EEPROMDeviceSoftwareManager::initDevice(
36994a77ffSKevin Tung     const std::string& service, const std::string& path, SoftwareConfig& config)
37994a77ffSKevin Tung {
38994a77ffSKevin Tung     const std::string configIface =
39994a77ffSKevin Tung         "xyz.openbmc_project.Configuration." + config.configType;
40994a77ffSKevin Tung 
41994a77ffSKevin Tung     std::optional<uint64_t> bus = co_await dbusGetRequiredProperty<uint64_t>(
42994a77ffSKevin Tung         ctx, service, path, configIface, "Bus");
43994a77ffSKevin Tung 
44994a77ffSKevin Tung     std::optional<uint64_t> address =
45994a77ffSKevin Tung         co_await dbusGetRequiredProperty<uint64_t>(ctx, service, path,
46994a77ffSKevin Tung                                                    configIface, "Address");
47994a77ffSKevin Tung 
48994a77ffSKevin Tung     std::optional<std::string> type =
49994a77ffSKevin Tung         co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
50994a77ffSKevin Tung                                                       configIface, "Type");
51994a77ffSKevin Tung 
52994a77ffSKevin Tung     std::optional<std::string> fwDevice =
53994a77ffSKevin Tung         co_await dbusGetRequiredProperty<std::string>(
54994a77ffSKevin Tung             ctx, service, path, configIface, "FirmwareDevice");
55994a77ffSKevin Tung 
56994a77ffSKevin Tung     if (!bus.has_value() || !address.has_value() || !type.has_value() ||
57994a77ffSKevin Tung         !fwDevice.has_value())
58994a77ffSKevin Tung     {
59994a77ffSKevin Tung         error("Missing EEPROM device config property");
60994a77ffSKevin Tung         co_return false;
61994a77ffSKevin Tung     }
62994a77ffSKevin Tung 
63994a77ffSKevin Tung     debug("EEPROM Device: Bus={BUS}, Address={ADDR}, Type={TYPE}, "
64994a77ffSKevin Tung           "Firmware Device={DEVICE}",
65994a77ffSKevin Tung           "BUS", bus.value(), "ADDR", address.value(), "TYPE", type.value(),
66994a77ffSKevin Tung           "DEVICE", fwDevice.value());
67994a77ffSKevin Tung 
68994a77ffSKevin Tung     std::unique_ptr<DeviceVersion> deviceVersion =
69994a77ffSKevin Tung         getVersionProvider(type.value(), bus.value(), address.value());
70994a77ffSKevin Tung 
71994a77ffSKevin Tung     if (!deviceVersion)
72994a77ffSKevin Tung     {
73994a77ffSKevin Tung         error("Failed to get version provider for chip type: {CHIP}", "CHIP",
74994a77ffSKevin Tung               type.value());
75994a77ffSKevin Tung         co_return false;
76994a77ffSKevin Tung     }
77994a77ffSKevin Tung 
78994a77ffSKevin Tung     std::string version = deviceVersion->getVersion();
79994a77ffSKevin Tung 
80994a77ffSKevin Tung     using ObjectMapper =
81994a77ffSKevin Tung         sdbusplus::client::xyz::openbmc_project::ObjectMapper<>;
82994a77ffSKevin Tung 
83994a77ffSKevin Tung     auto mapper = ObjectMapper(ctx)
84994a77ffSKevin Tung                       .service(ObjectMapper::default_service)
85994a77ffSKevin Tung                       .path(ObjectMapper::instance_path);
86994a77ffSKevin Tung 
87994a77ffSKevin Tung     auto res =
88994a77ffSKevin Tung         co_await mapper.get_sub_tree("/xyz/openbmc_project/inventory", 0, {});
89994a77ffSKevin Tung 
90994a77ffSKevin Tung     bus.reset();
91994a77ffSKevin Tung     address.reset();
92994a77ffSKevin Tung     type.reset();
93994a77ffSKevin Tung 
94994a77ffSKevin Tung     for (auto& [p, v] : res)
95994a77ffSKevin Tung     {
96994a77ffSKevin Tung         if (!p.ends_with(fwDevice.value()))
97994a77ffSKevin Tung         {
98994a77ffSKevin Tung             continue;
99994a77ffSKevin Tung         }
100994a77ffSKevin Tung 
101994a77ffSKevin Tung         for (auto& [s, ifaces] : v)
102994a77ffSKevin Tung         {
103994a77ffSKevin Tung             for (std::string& iface : ifaces)
104994a77ffSKevin Tung             {
105994a77ffSKevin Tung                 if (iface.starts_with("xyz.openbmc_project.Configuration."))
106994a77ffSKevin Tung                 {
107994a77ffSKevin Tung                     bus = co_await dbusGetRequiredProperty<uint64_t>(
108994a77ffSKevin Tung                         ctx, s, p, iface, "Bus");
109994a77ffSKevin Tung 
110994a77ffSKevin Tung                     address = co_await dbusGetRequiredProperty<uint64_t>(
111994a77ffSKevin Tung                         ctx, s, p, iface, "Address");
112994a77ffSKevin Tung 
113994a77ffSKevin Tung                     type = co_await dbusGetRequiredProperty<std::string>(
114994a77ffSKevin Tung                         ctx, s, p, iface, "Type");
115994a77ffSKevin Tung                     break;
116994a77ffSKevin Tung                 }
117994a77ffSKevin Tung             }
118994a77ffSKevin Tung             if (bus.has_value() && address.has_value() && type.has_value())
119994a77ffSKevin Tung             {
120994a77ffSKevin Tung                 break;
121994a77ffSKevin Tung             }
122994a77ffSKevin Tung         }
123994a77ffSKevin Tung         break;
124994a77ffSKevin Tung     }
125994a77ffSKevin Tung 
126994a77ffSKevin Tung     if (!bus.has_value() || !address.has_value() || !type.has_value())
127994a77ffSKevin Tung     {
128994a77ffSKevin Tung         error("Missing EEPROM config property");
129994a77ffSKevin Tung         co_return false;
130994a77ffSKevin Tung     }
131994a77ffSKevin Tung 
132994a77ffSKevin Tung     debug("EEPROM: Bus={BUS}, Address={ADDR}, Type={TYPE}", "BUS", bus.value(),
133994a77ffSKevin Tung           "ADDR", address.value(), "TYPE", type.value());
134994a77ffSKevin Tung 
135994a77ffSKevin Tung     const std::string configIfaceMux = configIface + ".MuxOutputs";
136994a77ffSKevin Tung     std::vector<std::string> gpioLines;
137994a77ffSKevin Tung     std::vector<bool> gpioPolarities;
138994a77ffSKevin Tung 
139994a77ffSKevin Tung     for (size_t i = 0; true; i++)
140994a77ffSKevin Tung     {
141994a77ffSKevin Tung         const std::string iface = configIfaceMux + std::to_string(i);
142994a77ffSKevin Tung 
143994a77ffSKevin Tung         std::optional<std::string> name =
144994a77ffSKevin Tung             co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
145994a77ffSKevin Tung                                                           iface, "Name");
146994a77ffSKevin Tung 
147994a77ffSKevin Tung         std::optional<std::string> polarity =
148994a77ffSKevin Tung             co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
149994a77ffSKevin Tung                                                           iface, "Polarity");
150994a77ffSKevin Tung 
151994a77ffSKevin Tung         if (!name.has_value() || !polarity.has_value())
152994a77ffSKevin Tung         {
153994a77ffSKevin Tung             break;
154994a77ffSKevin Tung         }
155994a77ffSKevin Tung 
156994a77ffSKevin Tung         gpioLines.push_back(name.value());
157994a77ffSKevin Tung         gpioPolarities.push_back(polarity.value() == "High");
158994a77ffSKevin Tung     }
159994a77ffSKevin Tung 
160994a77ffSKevin Tung     for (size_t i = 0; i < gpioLines.size(); i++)
161994a77ffSKevin Tung     {
162994a77ffSKevin Tung         debug("Mux gpio {NAME} polarity = {VALUE}", "NAME", gpioLines[i],
163994a77ffSKevin Tung               "VALUE", gpioPolarities[i]);
164994a77ffSKevin Tung     }
165994a77ffSKevin Tung 
166994a77ffSKevin Tung     auto eepromDevice = std::make_unique<EEPROMDevice>(
167994a77ffSKevin Tung         ctx, static_cast<uint16_t>(bus.value()),
168994a77ffSKevin Tung         static_cast<uint8_t>(address.value()), type.value(), gpioLines,
169994a77ffSKevin Tung         gpioPolarities, std::move(deviceVersion), config, this);
170994a77ffSKevin Tung 
171994a77ffSKevin Tung     std::unique_ptr<SoftwareInf::Software> software =
172994a77ffSKevin Tung         std::make_unique<SoftwareInf::Software>(ctx, *eepromDevice);
173994a77ffSKevin Tung 
174994a77ffSKevin Tung     software->setVersion(version.empty() ? "Unknown" : version);
175994a77ffSKevin Tung 
176994a77ffSKevin Tung     std::set<RequestedApplyTimes> allowedApplyTimes = {
177994a77ffSKevin Tung         RequestedApplyTimes::Immediate, RequestedApplyTimes::OnReset};
178994a77ffSKevin Tung 
179994a77ffSKevin Tung     software->enableUpdate(allowedApplyTimes);
180994a77ffSKevin Tung 
181994a77ffSKevin Tung     eepromDevice->softwareCurrent = std::move(software);
182994a77ffSKevin Tung 
183994a77ffSKevin Tung     devices.insert({config.objectPath, std::move(eepromDevice)});
184994a77ffSKevin Tung 
185994a77ffSKevin Tung     co_return true;
186994a77ffSKevin Tung }
187994a77ffSKevin Tung 
main()188994a77ffSKevin Tung int main()
189994a77ffSKevin Tung {
190994a77ffSKevin Tung     sdbusplus::async::context ctx;
191994a77ffSKevin Tung 
192994a77ffSKevin Tung     EEPROMDeviceSoftwareManager eepromDeviceSoftwareManager(ctx);
193994a77ffSKevin Tung 
194994a77ffSKevin Tung     eepromDeviceSoftwareManager.start();
195994a77ffSKevin Tung     return 0;
196994a77ffSKevin Tung }
197