blob: b29cf8232b97e6f74ef5fd915843360a17ec4e02 [file] [log] [blame]
#include "eeprom_device_software_manager.hpp"
#include "common/include/dbus_helper.hpp"
#include "eeprom_device.hpp"
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/async.hpp>
#include <xyz/openbmc_project/ObjectMapper/client.hpp>
#include <fstream>
#include <optional>
#include <sstream>
PHOSPHOR_LOG2_USING;
namespace SoftwareInf = phosphor::software;
const std::vector<std::string> emConfigTypes = {"PT5161L"};
void EEPROMDeviceSoftwareManager::start()
{
std::vector<std::string> configIntfs;
configIntfs.reserve(emConfigTypes.size());
std::transform(emConfigTypes.begin(), emConfigTypes.end(),
std::back_inserter(configIntfs),
[](const std::string& type) {
return "xyz.openbmc_project.Configuration." + type;
});
ctx.spawn(initDevices(configIntfs));
ctx.run();
}
// NOLINTBEGIN(readability-static-accessed-through-instance)
sdbusplus::async::task<bool> EEPROMDeviceSoftwareManager::initDevice(
const std::string& service, const std::string& path, SoftwareConfig& config)
// NOLINTEND(readability-static-accessed-through-instance)
{
const std::string configIface =
"xyz.openbmc_project.Configuration." + config.configType;
std::optional<uint64_t> bus = co_await dbusGetRequiredProperty<uint64_t>(
ctx, service, path, configIface, "Bus");
std::optional<uint64_t> address =
co_await dbusGetRequiredProperty<uint64_t>(ctx, service, path,
configIface, "Address");
std::optional<std::string> type =
co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
configIface, "Type");
std::optional<std::string> fwDevice =
co_await dbusGetRequiredProperty<std::string>(
ctx, service, path, configIface, "FirmwareDevice");
if (!bus.has_value() || !address.has_value() || !type.has_value() ||
!fwDevice.has_value())
{
error("Missing EEPROM device config property");
co_return false;
}
debug("EEPROM Device: Bus={BUS}, Address={ADDR}, Type={TYPE}, "
"Firmware Device={DEVICE}",
"BUS", bus.value(), "ADDR", address.value(), "TYPE", type.value(),
"DEVICE", fwDevice.value());
std::unique_ptr<DeviceVersion> deviceVersion =
getVersionProvider(type.value(), bus.value(), address.value());
if (!deviceVersion)
{
error("Failed to get version provider for chip type: {CHIP}", "CHIP",
type.value());
co_return false;
}
std::string version = deviceVersion->getVersion();
using ObjectMapper =
sdbusplus::client::xyz::openbmc_project::ObjectMapper<>;
auto mapper = ObjectMapper(ctx)
.service(ObjectMapper::default_service)
.path(ObjectMapper::instance_path);
auto res =
co_await mapper.get_sub_tree("/xyz/openbmc_project/inventory", 0, {});
bus.reset();
address.reset();
type.reset();
for (auto& [p, v] : res)
{
if (!p.ends_with(fwDevice.value()))
{
continue;
}
for (auto& [s, ifaces] : v)
{
for (std::string& iface : ifaces)
{
if (iface.starts_with("xyz.openbmc_project.Configuration."))
{
bus = co_await dbusGetRequiredProperty<uint64_t>(
ctx, s, p, iface, "Bus");
address = co_await dbusGetRequiredProperty<uint64_t>(
ctx, s, p, iface, "Address");
type = co_await dbusGetRequiredProperty<std::string>(
ctx, s, p, iface, "Type");
break;
}
}
if (bus.has_value() && address.has_value() && type.has_value())
{
break;
}
}
break;
}
if (!bus.has_value() || !address.has_value() || !type.has_value())
{
error("Missing EEPROM config property");
co_return false;
}
debug("EEPROM: Bus={BUS}, Address={ADDR}, Type={TYPE}", "BUS", bus.value(),
"ADDR", address.value(), "TYPE", type.value());
const std::string configIfaceMux = configIface + ".MuxOutputs";
std::vector<std::string> gpioLines;
std::vector<bool> gpioPolarities;
for (size_t i = 0; true; i++)
{
const std::string iface = configIfaceMux + std::to_string(i);
std::optional<std::string> name =
co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
iface, "Name");
std::optional<std::string> polarity =
co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
iface, "Polarity");
if (!name.has_value() || !polarity.has_value())
{
break;
}
gpioLines.push_back(name.value());
gpioPolarities.push_back(polarity.value() == "High");
}
for (size_t i = 0; i < gpioLines.size(); i++)
{
debug("Mux gpio {NAME} polarity = {VALUE}", "NAME", gpioLines[i],
"VALUE", gpioPolarities[i]);
}
auto eepromDevice = std::make_unique<EEPROMDevice>(
ctx, static_cast<uint16_t>(bus.value()),
static_cast<uint8_t>(address.value()), type.value(), gpioLines,
gpioPolarities, std::move(deviceVersion), config, this);
std::unique_ptr<SoftwareInf::Software> software =
std::make_unique<SoftwareInf::Software>(ctx, *eepromDevice);
software->setVersion(version.empty() ? "Unknown" : version);
std::set<RequestedApplyTimes> allowedApplyTimes = {
RequestedApplyTimes::Immediate, RequestedApplyTimes::OnReset};
software->enableUpdate(allowedApplyTimes);
eepromDevice->softwareCurrent = std::move(software);
devices.insert({config.objectPath, std::move(eepromDevice)});
co_return true;
}
int main()
{
sdbusplus::async::context ctx;
EEPROMDeviceSoftwareManager eepromDeviceSoftwareManager(ctx);
eepromDeviceSoftwareManager.start();
return 0;
}