| #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 |