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