1 #include "inventory_manager.hpp" 2 3 #include "common/utils.hpp" 4 #include "xyz/openbmc_project/Software/Version/server.hpp" 5 6 #include <libpldm/firmware_update.h> 7 8 #include <phosphor-logging/lg2.hpp> 9 10 #include <functional> 11 12 PHOSPHOR_LOG2_USING; 13 14 namespace pldm 15 { 16 namespace fw_update 17 { 18 void InventoryManager::discoverFDs(const std::vector<mctp_eid_t>& eids) 19 { 20 for (const auto& eid : eids) 21 { 22 auto instanceId = instanceIdDb.next(eid); 23 Request requestMsg(sizeof(pldm_msg_hdr) + 24 PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES); 25 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 26 auto rc = encode_query_device_identifiers_req( 27 instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request); 28 if (rc) 29 { 30 instanceIdDb.free(eid, instanceId); 31 error( 32 "Failed to encode query device identifiers req for endpoint ID '{EID}', response code '{RC}'", 33 "EID", eid, "RC", rc); 34 continue; 35 } 36 37 rc = handler.registerRequest( 38 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS, 39 std::move(requestMsg), 40 std::bind_front(&InventoryManager::queryDeviceIdentifiers, this)); 41 if (rc) 42 { 43 error( 44 "Failed to send query device identifiers request for endpoint ID '{EID}', response code '{RC}'", 45 "EID", eid, "RC", rc); 46 } 47 } 48 } 49 50 void InventoryManager::queryDeviceIdentifiers(mctp_eid_t eid, 51 const pldm_msg* response, 52 size_t respMsgLen) 53 { 54 if (response == nullptr || !respMsgLen) 55 { 56 error( 57 "No response received for query device identifiers for endpoint ID '{EID}'", 58 "EID", eid); 59 return; 60 } 61 62 uint8_t completionCode = PLDM_SUCCESS; 63 uint32_t deviceIdentifiersLen = 0; 64 uint8_t descriptorCount = 0; 65 uint8_t* descriptorPtr = nullptr; 66 67 auto rc = decode_query_device_identifiers_resp( 68 response, respMsgLen, &completionCode, &deviceIdentifiersLen, 69 &descriptorCount, &descriptorPtr); 70 if (rc) 71 { 72 error( 73 "Failed to decode query device identifiers response for endpoint ID '{EID}' and descriptor count '{DESCRIPTOR_COUNT}', response code '{RC}'", 74 "EID", eid, "DESCRIPTOR_COUNT", descriptorCount, "RC", rc); 75 return; 76 } 77 78 if (completionCode) 79 { 80 error( 81 "Failed to query device identifiers response for endpoint ID '{EID}', completion code '{CC}'", 82 "EID", eid, "CC", completionCode); 83 return; 84 } 85 86 Descriptors descriptors{}; 87 while (descriptorCount-- && (deviceIdentifiersLen > 0)) 88 { 89 uint16_t descriptorType = 0; 90 variable_field descriptorData{}; 91 92 rc = decode_descriptor_type_length_value( 93 descriptorPtr, deviceIdentifiersLen, &descriptorType, 94 &descriptorData); 95 if (rc) 96 { 97 error( 98 "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID '{EID}', response code '{RC}'", 99 "TYPE", descriptorType, "LENGTH", deviceIdentifiersLen, "EID", 100 eid, "RC", rc); 101 return; 102 } 103 104 if (descriptorType != PLDM_FWUP_VENDOR_DEFINED) 105 { 106 std::vector<uint8_t> descData( 107 descriptorData.ptr, descriptorData.ptr + descriptorData.length); 108 descriptors.emplace(descriptorType, std::move(descData)); 109 } 110 else 111 { 112 uint8_t descriptorTitleStrType = 0; 113 variable_field descriptorTitleStr{}; 114 variable_field vendorDefinedDescriptorData{}; 115 116 rc = decode_vendor_defined_descriptor_value( 117 descriptorData.ptr, descriptorData.length, 118 &descriptorTitleStrType, &descriptorTitleStr, 119 &vendorDefinedDescriptorData); 120 if (rc) 121 { 122 error( 123 "Failed to decode vendor-defined descriptor value for endpoint ID '{EID}', response code '{RC}'", 124 "EID", eid, "RC", rc); 125 return; 126 } 127 128 auto vendorDefinedDescriptorTitleStr = 129 utils::toString(descriptorTitleStr); 130 std::vector<uint8_t> vendorDescData( 131 vendorDefinedDescriptorData.ptr, 132 vendorDefinedDescriptorData.ptr + 133 vendorDefinedDescriptorData.length); 134 descriptors.emplace(descriptorType, 135 std::make_tuple(vendorDefinedDescriptorTitleStr, 136 vendorDescData)); 137 } 138 auto nextDescriptorOffset = 139 sizeof(pldm_descriptor_tlv().descriptor_type) + 140 sizeof(pldm_descriptor_tlv().descriptor_length) + 141 descriptorData.length; 142 descriptorPtr += nextDescriptorOffset; 143 deviceIdentifiersLen -= nextDescriptorOffset; 144 } 145 146 descriptorMap.emplace(eid, std::move(descriptors)); 147 148 // Send GetFirmwareParameters request 149 sendGetFirmwareParametersRequest(eid); 150 } 151 152 void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid) 153 { 154 auto instanceId = instanceIdDb.next(eid); 155 Request requestMsg(sizeof(pldm_msg_hdr) + 156 PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES); 157 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 158 auto rc = encode_get_firmware_parameters_req( 159 instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request); 160 if (rc) 161 { 162 instanceIdDb.free(eid, instanceId); 163 error( 164 "Failed to encode get firmware parameters req for endpoint ID '{EID}', response code '{RC}'", 165 "EID", eid, "RC", rc); 166 return; 167 } 168 169 rc = handler.registerRequest( 170 eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS, 171 std::move(requestMsg), 172 std::bind_front(&InventoryManager::getFirmwareParameters, this)); 173 if (rc) 174 { 175 error( 176 "Failed to send get firmware parameters request for endpoint ID '{EID}', response code '{RC}'", 177 "EID", eid, "RC", rc); 178 } 179 } 180 181 void InventoryManager::getFirmwareParameters(mctp_eid_t eid, 182 const pldm_msg* response, 183 size_t respMsgLen) 184 { 185 if (response == nullptr || !respMsgLen) 186 { 187 error( 188 "No response received for get firmware parameters for endpoint ID '{EID}'", 189 "EID", eid); 190 descriptorMap.erase(eid); 191 return; 192 } 193 194 pldm_get_firmware_parameters_resp fwParams{}; 195 variable_field activeCompImageSetVerStr{}; 196 variable_field pendingCompImageSetVerStr{}; 197 variable_field compParamTable{}; 198 199 auto rc = decode_get_firmware_parameters_resp( 200 response, respMsgLen, &fwParams, &activeCompImageSetVerStr, 201 &pendingCompImageSetVerStr, &compParamTable); 202 if (rc) 203 { 204 error( 205 "Failed to decode get firmware parameters response for endpoint ID '{EID}', response code '{RC}'", 206 "EID", eid, "RC", rc); 207 return; 208 } 209 210 if (fwParams.completion_code) 211 { 212 auto fw_param_cc = fwParams.completion_code; 213 error( 214 "Failed to get firmware parameters response for endpoint ID '{EID}', completion code '{CC}'", 215 "EID", eid, "CC", fw_param_cc); 216 return; 217 } 218 219 auto compParamPtr = compParamTable.ptr; 220 auto compParamTableLen = compParamTable.length; 221 pldm_component_parameter_entry compEntry{}; 222 variable_field activeCompVerStr{}; 223 variable_field pendingCompVerStr{}; 224 225 ComponentInfo componentInfo{}; 226 while (fwParams.comp_count-- && (compParamTableLen > 0)) 227 { 228 auto rc = decode_get_firmware_parameters_resp_comp_entry( 229 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr, 230 &pendingCompVerStr); 231 if (rc) 232 { 233 error( 234 "Failed to decode component parameter table entry for endpoint ID '{EID}', response code '{RC}'", 235 "EID", eid, "RC", rc); 236 return; 237 } 238 239 auto compClassification = compEntry.comp_classification; 240 auto compIdentifier = compEntry.comp_identifier; 241 componentInfo.emplace( 242 std::make_pair(compClassification, compIdentifier), 243 compEntry.comp_classification_index); 244 compParamPtr += sizeof(pldm_component_parameter_entry) + 245 activeCompVerStr.length + pendingCompVerStr.length; 246 compParamTableLen -= sizeof(pldm_component_parameter_entry) + 247 activeCompVerStr.length + pendingCompVerStr.length; 248 } 249 componentInfoMap.emplace(eid, std::move(componentInfo)); 250 } 251 252 } // namespace fw_update 253 254 } // namespace pldm 255