blob: b29cf8232b97e6f74ef5fd915843360a17ec4e02 [file] [log] [blame]
Kevin Tung994a77f2024-12-23 17:48:56 +08001#include "eeprom_device_software_manager.hpp"
2
3#include "common/include/dbus_helper.hpp"
4#include "eeprom_device.hpp"
5
6#include <phosphor-logging/lg2.hpp>
7#include <sdbusplus/async.hpp>
8#include <xyz/openbmc_project/ObjectMapper/client.hpp>
9
10#include <fstream>
11#include <optional>
12#include <sstream>
13
14PHOSPHOR_LOG2_USING;
15
16namespace SoftwareInf = phosphor::software;
17
18const std::vector<std::string> emConfigTypes = {"PT5161L"};
19
20void EEPROMDeviceSoftwareManager::start()
21{
22 std::vector<std::string> configIntfs;
23 configIntfs.reserve(emConfigTypes.size());
24
25 std::transform(emConfigTypes.begin(), emConfigTypes.end(),
26 std::back_inserter(configIntfs),
27 [](const std::string& type) {
28 return "xyz.openbmc_project.Configuration." + type;
29 });
30
31 ctx.spawn(initDevices(configIntfs));
32 ctx.run();
33}
34
35// NOLINTBEGIN(readability-static-accessed-through-instance)
36sdbusplus::async::task<bool> EEPROMDeviceSoftwareManager::initDevice(
37 const std::string& service, const std::string& path, SoftwareConfig& config)
38// NOLINTEND(readability-static-accessed-through-instance)
39{
40 const std::string configIface =
41 "xyz.openbmc_project.Configuration." + config.configType;
42
43 std::optional<uint64_t> bus = co_await dbusGetRequiredProperty<uint64_t>(
44 ctx, service, path, configIface, "Bus");
45
46 std::optional<uint64_t> address =
47 co_await dbusGetRequiredProperty<uint64_t>(ctx, service, path,
48 configIface, "Address");
49
50 std::optional<std::string> type =
51 co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
52 configIface, "Type");
53
54 std::optional<std::string> fwDevice =
55 co_await dbusGetRequiredProperty<std::string>(
56 ctx, service, path, configIface, "FirmwareDevice");
57
58 if (!bus.has_value() || !address.has_value() || !type.has_value() ||
59 !fwDevice.has_value())
60 {
61 error("Missing EEPROM device config property");
62 co_return false;
63 }
64
65 debug("EEPROM Device: Bus={BUS}, Address={ADDR}, Type={TYPE}, "
66 "Firmware Device={DEVICE}",
67 "BUS", bus.value(), "ADDR", address.value(), "TYPE", type.value(),
68 "DEVICE", fwDevice.value());
69
70 std::unique_ptr<DeviceVersion> deviceVersion =
71 getVersionProvider(type.value(), bus.value(), address.value());
72
73 if (!deviceVersion)
74 {
75 error("Failed to get version provider for chip type: {CHIP}", "CHIP",
76 type.value());
77 co_return false;
78 }
79
80 std::string version = deviceVersion->getVersion();
81
82 using ObjectMapper =
83 sdbusplus::client::xyz::openbmc_project::ObjectMapper<>;
84
85 auto mapper = ObjectMapper(ctx)
86 .service(ObjectMapper::default_service)
87 .path(ObjectMapper::instance_path);
88
89 auto res =
90 co_await mapper.get_sub_tree("/xyz/openbmc_project/inventory", 0, {});
91
92 bus.reset();
93 address.reset();
94 type.reset();
95
96 for (auto& [p, v] : res)
97 {
98 if (!p.ends_with(fwDevice.value()))
99 {
100 continue;
101 }
102
103 for (auto& [s, ifaces] : v)
104 {
105 for (std::string& iface : ifaces)
106 {
107 if (iface.starts_with("xyz.openbmc_project.Configuration."))
108 {
109 bus = co_await dbusGetRequiredProperty<uint64_t>(
110 ctx, s, p, iface, "Bus");
111
112 address = co_await dbusGetRequiredProperty<uint64_t>(
113 ctx, s, p, iface, "Address");
114
115 type = co_await dbusGetRequiredProperty<std::string>(
116 ctx, s, p, iface, "Type");
117 break;
118 }
119 }
120 if (bus.has_value() && address.has_value() && type.has_value())
121 {
122 break;
123 }
124 }
125 break;
126 }
127
128 if (!bus.has_value() || !address.has_value() || !type.has_value())
129 {
130 error("Missing EEPROM config property");
131 co_return false;
132 }
133
134 debug("EEPROM: Bus={BUS}, Address={ADDR}, Type={TYPE}", "BUS", bus.value(),
135 "ADDR", address.value(), "TYPE", type.value());
136
137 const std::string configIfaceMux = configIface + ".MuxOutputs";
138 std::vector<std::string> gpioLines;
139 std::vector<bool> gpioPolarities;
140
141 for (size_t i = 0; true; i++)
142 {
143 const std::string iface = configIfaceMux + std::to_string(i);
144
145 std::optional<std::string> name =
146 co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
147 iface, "Name");
148
149 std::optional<std::string> polarity =
150 co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
151 iface, "Polarity");
152
153 if (!name.has_value() || !polarity.has_value())
154 {
155 break;
156 }
157
158 gpioLines.push_back(name.value());
159 gpioPolarities.push_back(polarity.value() == "High");
160 }
161
162 for (size_t i = 0; i < gpioLines.size(); i++)
163 {
164 debug("Mux gpio {NAME} polarity = {VALUE}", "NAME", gpioLines[i],
165 "VALUE", gpioPolarities[i]);
166 }
167
168 auto eepromDevice = std::make_unique<EEPROMDevice>(
169 ctx, static_cast<uint16_t>(bus.value()),
170 static_cast<uint8_t>(address.value()), type.value(), gpioLines,
171 gpioPolarities, std::move(deviceVersion), config, this);
172
173 std::unique_ptr<SoftwareInf::Software> software =
174 std::make_unique<SoftwareInf::Software>(ctx, *eepromDevice);
175
176 software->setVersion(version.empty() ? "Unknown" : version);
177
178 std::set<RequestedApplyTimes> allowedApplyTimes = {
179 RequestedApplyTimes::Immediate, RequestedApplyTimes::OnReset};
180
181 software->enableUpdate(allowedApplyTimes);
182
183 eepromDevice->softwareCurrent = std::move(software);
184
185 devices.insert({config.objectPath, std::move(eepromDevice)});
186
187 co_return true;
188}
189
190int main()
191{
192 sdbusplus::async::context ctx;
193
194 EEPROMDeviceSoftwareManager eepromDeviceSoftwareManager(ctx);
195
196 eepromDeviceSoftwareManager.start();
197 return 0;
198}