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 = requester.getInstanceId(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 requester.markFree(eid, instanceId); 31 error( 32 "encode_query_device_identifiers_req failed, EID={EID}, RC = {RC}", 33 "EID", unsigned(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::move(std::bind_front(&InventoryManager::queryDeviceIdentifiers, 41 this))); 42 if (rc) 43 { 44 error( 45 "Failed to send QueryDeviceIdentifiers request, EID={EID}, RC = {RC}", 46 "EID", unsigned(eid), "RC", rc); 47 } 48 } 49 } 50 51 void InventoryManager::queryDeviceIdentifiers(mctp_eid_t eid, 52 const pldm_msg* response, 53 size_t respMsgLen) 54 { 55 if (response == nullptr || !respMsgLen) 56 { 57 error("No response received for QueryDeviceIdentifiers, EID={EID}", 58 "EID", unsigned(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 "Decoding QueryDeviceIdentifiers response failed, EID={EID}, RC = {RC}", 74 "EID", unsigned(eid), "RC", rc); 75 return; 76 } 77 78 if (completionCode) 79 { 80 error( 81 "QueryDeviceIdentifiers response failed with error completion code, EID={EID}, CC = {CC}", 82 "EID", unsigned(eid), "CC", unsigned(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 "Decoding descriptor type, length and value failed, EID={EID}, RC = {RC}", 99 "EID", unsigned(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 "Decoding Vendor-defined descriptor value failed, EID={EID}, RC = {RC}", 123 "EID", unsigned(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 = requester.getInstanceId(eid); 154 Request requestMsg(sizeof(pldm_msg_hdr) + 155 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 requester.markFree(eid, instanceId); 162 error("encode_get_firmware_parameters_req failed, EID={EID}, RC = {RC}", 163 "EID", unsigned(eid), "RC", rc); 164 return; 165 } 166 167 rc = handler.registerRequest( 168 eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS, 169 std::move(requestMsg), 170 std::move( 171 std::bind_front(&InventoryManager::getFirmwareParameters, this))); 172 if (rc) 173 { 174 error( 175 "Failed to send GetFirmwareParameters request, EID={EID}, RC = {RC}", 176 "EID", unsigned(eid), "RC", rc); 177 } 178 } 179 180 void InventoryManager::getFirmwareParameters(mctp_eid_t eid, 181 const pldm_msg* response, 182 size_t respMsgLen) 183 { 184 if (response == nullptr || !respMsgLen) 185 { 186 error("No response received for GetFirmwareParameters, EID={EID}", 187 "EID", unsigned(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 "Decoding GetFirmwareParameters response failed, EID={EID}, RC = {RC}", 204 "EID", unsigned(eid), "RC", rc); 205 return; 206 } 207 208 if (fwParams.completion_code) 209 { 210 error( 211 "GetFirmwareParameters response failed with error completion code, EID={EID}, CC = {CC}", 212 "EID", unsigned(eid), "CC", unsigned(fwParams.completion_code)); 213 return; 214 } 215 216 auto compParamPtr = compParamTable.ptr; 217 auto compParamTableLen = compParamTable.length; 218 pldm_component_parameter_entry compEntry{}; 219 variable_field activeCompVerStr{}; 220 variable_field pendingCompVerStr{}; 221 222 ComponentInfo componentInfo{}; 223 while (fwParams.comp_count-- && (compParamTableLen > 0)) 224 { 225 auto rc = decode_get_firmware_parameters_resp_comp_entry( 226 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr, 227 &pendingCompVerStr); 228 if (rc) 229 { 230 error( 231 "Decoding component parameter table entry failed, EID={EID}, RC = {RC}", 232 "EID", unsigned(eid), "RC", rc); 233 return; 234 } 235 236 auto compClassification = compEntry.comp_classification; 237 auto compIdentifier = compEntry.comp_identifier; 238 componentInfo.emplace( 239 std::make_pair(compClassification, compIdentifier), 240 compEntry.comp_classification_index); 241 compParamPtr += sizeof(pldm_component_parameter_entry) + 242 activeCompVerStr.length + pendingCompVerStr.length; 243 compParamTableLen -= sizeof(pldm_component_parameter_entry) + 244 activeCompVerStr.length + pendingCompVerStr.length; 245 } 246 componentInfoMap.emplace(eid, std::move(componentInfo)); 247 } 248 249 } // namespace fw_update 250 251 } // namespace pldm 252