1 #include "fru_oem_ibm.hpp" 2 3 #include <phosphor-logging/lg2.hpp> 4 5 #include <ranges> 6 7 PHOSPHOR_LOG2_USING; 8 9 namespace pldm 10 { 11 namespace responder 12 { 13 namespace oem_ibm_fru 14 { 15 16 void pldm::responder::oem_ibm_fru::Handler::setIBMFruHandler( 17 pldm::responder::fru::Handler* handler) 18 { 19 fruHandler = handler; 20 } 21 22 int pldm::responder::oem_ibm_fru::Handler::processOEMFRUTable( 23 const std::vector<uint8_t>& fruData) 24 { 25 uint8_t dataSize = 0; 26 const uint8_t* data = fruData.data(); 27 28 while (dataSize < fruData.size()) 29 { 30 auto record = 31 reinterpret_cast<const pldm_fru_record_data_format*>(data); 32 if (!record) 33 { 34 return PLDM_ERROR_INVALID_DATA; 35 } 36 37 auto& entityAssociationMap = getAssociateEntityMap(); 38 uint16_t fruRSI = le16toh(record->record_set_id); 39 40 dataSize += sizeof(pldm_fru_record_data_format) - 41 sizeof(pldm_fru_record_tlv); 42 data += dataSize; 43 44 for ([[maybe_unused]] const auto& i : 45 std::views::iota(0, (int)record->num_fru_fields)) 46 { 47 auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(data); 48 if (!tlv) 49 { 50 return PLDM_ERROR_INVALID_DATA; 51 } 52 53 if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_PCIE_CONFIG_SPACE_DATA) 54 { 55 auto pcieData = 56 reinterpret_cast<const PcieConfigSpaceData*>(tlv->value); 57 58 if (!pcieData) 59 { 60 return PLDM_ERROR_INVALID_DATA; 61 } 62 auto vendorId = std::to_string(htole16(pcieData->vendorId)); 63 auto deviceId = std::to_string(htole16(pcieData->deviceId)); 64 auto revisionId = std::to_string(pcieData->revisionId); 65 66 std::stringstream ss; 67 68 for (const auto& ele : pcieData->classCode) 69 { 70 ss << std::setfill('0') << std::setw(2) << std::hex << ele; 71 } 72 std::string classCode = ss.str(); 73 74 auto subSystemVendorId = 75 std::to_string(htole16(pcieData->subSystemVendorId)); 76 auto subSystemId = 77 std::to_string(htole16(pcieData->subSystemId)); 78 79 updateDBusProperty(fruRSI, entityAssociationMap, vendorId, 80 deviceId, revisionId, classCode, 81 subSystemVendorId, subSystemId); 82 } 83 // length of tlv is removed from the structure pldm_fru_record_tlv 84 // and the new tlv length is added back. 85 dataSize += sizeof(pldm_fru_record_tlv) - sizeof(uint8_t) + 86 tlv->length; 87 data += dataSize; 88 } 89 } 90 91 return PLDM_SUCCESS; 92 } 93 94 void Handler::updateDBusProperty( 95 uint16_t fruRSI, const AssociatedEntityMap& fruAssociationMap, 96 const std::string& vendorId, const std::string& deviceId, 97 const std::string& revisionId, const std::string& classCode, 98 const std::string& subSystemVendorId, const std::string& subSystemId) 99 { 100 uint16_t entityType{}; 101 uint16_t entityInstanceNum{}; 102 uint16_t containerId{}; 103 uint16_t terminusHandle{}; 104 const pldm_pdr_record* record{}; 105 106 record = pldm_pdr_fru_record_set_find_by_rsi( 107 pdrRepo, fruRSI, &terminusHandle, &entityType, &entityInstanceNum, 108 &containerId); 109 110 if (record) 111 { 112 for (const auto& [key, value] : fruAssociationMap) 113 { 114 if (entityInstanceNum == value.entity_instance_num && 115 entityType == value.entity_type && 116 containerId == value.entity_container_id) 117 { 118 dbus_map_update(key, "Function0VendorId", vendorId); 119 dbus_map_update(key, "Function0DeviceId", deviceId); 120 dbus_map_update(key, "Function0RevisionId", revisionId); 121 dbus_map_update(key, "Function0ClassCode", classCode); 122 dbus_map_update(key, "Function0SubsystemVendorId", 123 subSystemVendorId); 124 dbus_map_update(key, "Function0SubsystemId", subSystemId); 125 } 126 } 127 } 128 } 129 130 void Handler::dbus_map_update(const std::string& adapterObjPath, 131 const std::string& propertyName, 132 const std::string& propValue) 133 { 134 pldm::utils::PropertyValue value = propValue; 135 pldm::utils::DBusMapping dbusMapping; 136 dbusMapping.objectPath = adapterObjPath; 137 dbusMapping.interface = "xyz.openbmc_project.Inventory.Item.PCIeDevice"; 138 dbusMapping.propertyName = propertyName; 139 dbusMapping.propertyType = "string"; 140 try 141 { 142 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 143 } 144 catch (const std::exception& e) 145 { 146 error("Failed to set '{PROPERTY}' property: {ERROR}", "PROPERTY", 147 propertyName, "ERROR", e); 148 } 149 } 150 } // namespace oem_ibm_fru 151 } // namespace responder 152 } // namespace pldm 153