Pavithra Barithaya | a410c65 | 2021-07-22 01:32:47 -0500 | [diff] [blame] | 1 | #include "fru_oem_ibm.hpp" |
| 2 | |
Pavithra Barithaya | c8bcefb | 2021-11-23 07:03:00 -0600 | [diff] [blame^] | 3 | #include <com/ibm/VPD/Manager/client.hpp> |
Pavithra Barithaya | a410c65 | 2021-07-22 01:32:47 -0500 | [diff] [blame] | 4 | #include <phosphor-logging/lg2.hpp> |
| 5 | |
| 6 | #include <ranges> |
| 7 | |
| 8 | PHOSPHOR_LOG2_USING; |
| 9 | |
| 10 | namespace pldm |
| 11 | { |
| 12 | namespace responder |
| 13 | { |
| 14 | namespace oem_ibm_fru |
| 15 | { |
| 16 | |
| 17 | void pldm::responder::oem_ibm_fru::Handler::setIBMFruHandler( |
| 18 | pldm::responder::fru::Handler* handler) |
| 19 | { |
| 20 | fruHandler = handler; |
| 21 | } |
| 22 | |
| 23 | int pldm::responder::oem_ibm_fru::Handler::processOEMFRUTable( |
| 24 | const std::vector<uint8_t>& fruData) |
| 25 | { |
| 26 | uint8_t dataSize = 0; |
| 27 | const uint8_t* data = fruData.data(); |
| 28 | |
| 29 | while (dataSize < fruData.size()) |
| 30 | { |
| 31 | auto record = |
| 32 | reinterpret_cast<const pldm_fru_record_data_format*>(data); |
| 33 | if (!record) |
| 34 | { |
| 35 | return PLDM_ERROR_INVALID_DATA; |
| 36 | } |
| 37 | |
| 38 | auto& entityAssociationMap = getAssociateEntityMap(); |
| 39 | uint16_t fruRSI = le16toh(record->record_set_id); |
| 40 | |
| 41 | dataSize += sizeof(pldm_fru_record_data_format) - |
| 42 | sizeof(pldm_fru_record_tlv); |
| 43 | data += dataSize; |
| 44 | |
| 45 | for ([[maybe_unused]] const auto& i : |
| 46 | std::views::iota(0, (int)record->num_fru_fields)) |
| 47 | { |
| 48 | auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(data); |
| 49 | if (!tlv) |
| 50 | { |
| 51 | return PLDM_ERROR_INVALID_DATA; |
| 52 | } |
| 53 | |
| 54 | if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_PCIE_CONFIG_SPACE_DATA) |
| 55 | { |
| 56 | auto pcieData = |
| 57 | reinterpret_cast<const PcieConfigSpaceData*>(tlv->value); |
| 58 | |
| 59 | if (!pcieData) |
| 60 | { |
| 61 | return PLDM_ERROR_INVALID_DATA; |
| 62 | } |
| 63 | auto vendorId = std::to_string(htole16(pcieData->vendorId)); |
| 64 | auto deviceId = std::to_string(htole16(pcieData->deviceId)); |
| 65 | auto revisionId = std::to_string(pcieData->revisionId); |
| 66 | |
| 67 | std::stringstream ss; |
| 68 | |
| 69 | for (const auto& ele : pcieData->classCode) |
| 70 | { |
| 71 | ss << std::setfill('0') << std::setw(2) << std::hex << ele; |
| 72 | } |
| 73 | std::string classCode = ss.str(); |
| 74 | |
| 75 | auto subSystemVendorId = |
| 76 | std::to_string(htole16(pcieData->subSystemVendorId)); |
| 77 | auto subSystemId = |
| 78 | std::to_string(htole16(pcieData->subSystemId)); |
| 79 | |
| 80 | updateDBusProperty(fruRSI, entityAssociationMap, vendorId, |
| 81 | deviceId, revisionId, classCode, |
| 82 | subSystemVendorId, subSystemId); |
| 83 | } |
Pavithra Barithaya | c8bcefb | 2021-11-23 07:03:00 -0600 | [diff] [blame^] | 84 | |
| 85 | if (tlv->type == PLDM_OEM_IBM_FRU_FIELD_TYPE_FIRMWARE_UAK) |
| 86 | { |
| 87 | std::vector<uint8_t> value(&tlv->value[0], |
| 88 | &tlv->value[tlv->length]); |
| 89 | setFirmwareUAK(value); |
| 90 | } |
Pavithra Barithaya | a410c65 | 2021-07-22 01:32:47 -0500 | [diff] [blame] | 91 | // length of tlv is removed from the structure pldm_fru_record_tlv |
| 92 | // and the new tlv length is added back. |
| 93 | dataSize += sizeof(pldm_fru_record_tlv) - sizeof(uint8_t) + |
| 94 | tlv->length; |
| 95 | data += dataSize; |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | return PLDM_SUCCESS; |
| 100 | } |
| 101 | |
| 102 | void Handler::updateDBusProperty( |
| 103 | uint16_t fruRSI, const AssociatedEntityMap& fruAssociationMap, |
| 104 | const std::string& vendorId, const std::string& deviceId, |
| 105 | const std::string& revisionId, const std::string& classCode, |
| 106 | const std::string& subSystemVendorId, const std::string& subSystemId) |
| 107 | { |
| 108 | uint16_t entityType{}; |
| 109 | uint16_t entityInstanceNum{}; |
| 110 | uint16_t containerId{}; |
| 111 | uint16_t terminusHandle{}; |
| 112 | const pldm_pdr_record* record{}; |
| 113 | |
| 114 | record = pldm_pdr_fru_record_set_find_by_rsi( |
| 115 | pdrRepo, fruRSI, &terminusHandle, &entityType, &entityInstanceNum, |
| 116 | &containerId); |
| 117 | |
| 118 | if (record) |
| 119 | { |
| 120 | for (const auto& [key, value] : fruAssociationMap) |
| 121 | { |
| 122 | if (entityInstanceNum == value.entity_instance_num && |
| 123 | entityType == value.entity_type && |
| 124 | containerId == value.entity_container_id) |
| 125 | { |
| 126 | dbus_map_update(key, "Function0VendorId", vendorId); |
| 127 | dbus_map_update(key, "Function0DeviceId", deviceId); |
| 128 | dbus_map_update(key, "Function0RevisionId", revisionId); |
| 129 | dbus_map_update(key, "Function0ClassCode", classCode); |
| 130 | dbus_map_update(key, "Function0SubsystemVendorId", |
| 131 | subSystemVendorId); |
| 132 | dbus_map_update(key, "Function0SubsystemId", subSystemId); |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | void Handler::dbus_map_update(const std::string& adapterObjPath, |
| 139 | const std::string& propertyName, |
| 140 | const std::string& propValue) |
| 141 | { |
| 142 | pldm::utils::PropertyValue value = propValue; |
| 143 | pldm::utils::DBusMapping dbusMapping; |
| 144 | dbusMapping.objectPath = adapterObjPath; |
| 145 | dbusMapping.interface = "xyz.openbmc_project.Inventory.Item.PCIeDevice"; |
| 146 | dbusMapping.propertyName = propertyName; |
| 147 | dbusMapping.propertyType = "string"; |
| 148 | try |
| 149 | { |
| 150 | pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); |
| 151 | } |
| 152 | catch (const std::exception& e) |
| 153 | { |
| 154 | error("Failed to set '{PROPERTY}' property: {ERROR}", "PROPERTY", |
| 155 | propertyName, "ERROR", e); |
| 156 | } |
| 157 | } |
Pavithra Barithaya | c8bcefb | 2021-11-23 07:03:00 -0600 | [diff] [blame^] | 158 | |
| 159 | void Handler::setFirmwareUAK(const std::vector<uint8_t>& data) |
| 160 | { |
| 161 | using VPDManager = sdbusplus::client::com::ibm::vpd::Manager<>; |
| 162 | |
| 163 | static constexpr auto uakObjPath = "/com/ibm/VPD/Manager"; |
| 164 | static constexpr auto fruPath = |
| 165 | "/xyz/openbmc_project/inventory/system/chassis/motherboard"; |
| 166 | |
| 167 | auto& bus = pldm::utils::DBusHandler::getBus(); |
| 168 | try |
| 169 | { |
| 170 | auto service = pldm::utils::DBusHandler().getService( |
| 171 | uakObjPath, VPDManager::interface); |
| 172 | auto method = bus.new_method_call( |
| 173 | service.c_str(), uakObjPath, VPDManager::interface, "WriteKeyword"); |
| 174 | method.append(static_cast<sdbusplus::message::object_path>(fruPath), |
| 175 | "UTIL", "D8", data); |
| 176 | bus.call_noreply(method); |
| 177 | } |
| 178 | catch (const std::exception& e) |
| 179 | { |
| 180 | error("Failed to make a DBus call to VPD manager: {ERROR}", "ERROR", e); |
| 181 | } |
| 182 | } |
| 183 | |
Pavithra Barithaya | a410c65 | 2021-07-22 01:32:47 -0500 | [diff] [blame] | 184 | } // namespace oem_ibm_fru |
| 185 | } // namespace responder |
| 186 | } // namespace pldm |