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