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