blob: 4b4ddda1bc9c01034944072236dc0be4ebbd48ce [file] [log] [blame] [edit]
#include "fru_device.hpp"
#include "fru_utils.hpp"
#include "pcie_bifurcation_utils.hpp"
#include <bus_bifurcation.hpp>
#include <sdbusplus/bus.hpp>
#include <cstdint>
#include <exception>
#include <iostream>
#include <numeric>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
namespace google::pcie_bifurcation
{
using Value = std::variant<uint64_t, std::vector<uint64_t>>;
using ObjectType =
std::unordered_map<std::string, std::unordered_map<std::string, Value>>;
using ManagedObjectType =
std::vector<std::pair<sdbusplus::message::object_path, ObjectType>>;
constexpr std::string_view PcieBifurcationKeyPrefix = "PCIe-bifurcation:";
constexpr std::string_view BadAmphenolPcieBifurcationKeyPrefix =
"\001PCIe-bifurcation:";
BusPCIeBifurcation::BusPCIeBifurcation(int slotIndex, int bus,
std::string bifurcationStr,
bool skipLaneSum) :
slotIndex_(slotIndex), i2cBus_(bus),
bifurcations_(parseBifurcationString(bifurcationStr, skipLaneSum))
{}
const std::vector<uint8_t>& BusPCIeBifurcation::getBifurcation() const
{
return bifurcations_;
}
void BusPCIeBifurcation::updateAddress(int addr)
{
address_ = addr;
}
void BusPCIeBifurcation::updateValue(std::string_view bifurcation)
{
if (!bifurcations_.empty())
{
// already got bifurcation info
return;
}
if (!bifurcation.starts_with(PcieBifurcationKeyPrefix) &&
!bifurcation.starts_with(BadAmphenolPcieBifurcationKeyPrefix))
{
return;
}
auto prefix = bifurcation.starts_with(PcieBifurcationKeyPrefix)
? PcieBifurcationKeyPrefix
: BadAmphenolPcieBifurcationKeyPrefix;
auto bifurcationStr = bifurcation.substr(prefix.size());
bifurcations_ = parseBifurcationString(bifurcationStr, false);
}
void BusPCIeBifurcation::populateBifurcation()
{
// if static value was set or found by BOARD_INFO_AM* then do nothing
// fallback to get from entity manager
if (bifurcations_.empty() && !associateEMPath_.empty())
{
auto sysBus = sdbusplus::bus::new_bus();
bifurcations_ = parseDevices(sysBus, associateEMPath_);
}
// fallback to get by reading fru content
if (bifurcations_.empty() && i2cBus_ > 0 && address_ > 0)
{
auto fruBifurcation = getBifurcationFromFRU(i2cBus_, address_);
if (fruBifurcation.has_value())
{
std::cout << "Added bifurcation information for bus '" << i2cBus_
<< "' and address '" << address_ << "'" << std::endl;
bifurcations_ = parseBifurcationString(
fruBifurcation->pcieBifurcationStr, false);
}
}
}
void BusPCIeBifurcation::updateEMPath(std::string path)
{
associateEMPath_ = std::move(path);
}
} // namespace google::pcie_bifurcation