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