fw_update: InventoryManager: Add Downstream Devices Support
In DSP0267_1.1.0, a Firmware Device can supports one or more
Downstream Devices to perform get firmware version or firmware
update. Add discovery of Downstream Devices, query the Downstream
Devices Descriptor if the Firmware Device support it.
The code is developed based on DSP0267_1.1.0 Section 10.3
QueryDownstreamDevices command format, Section 10.4
QueryDownstreamIdentifiers command format.
Tested: Add unit tests for the new command handlers.
Change-Id: Iad28b898b5a0799b2b145d38958bba78e9719f4e
Signed-off-by: Unive Tien <unive.tien.wiwynn@gmail.com>
diff --git a/fw-update/inventory_manager.cpp b/fw-update/inventory_manager.cpp
index 43508a7..63e03af 100644
--- a/fw-update/inventory_manager.cpp
+++ b/fw-update/inventory_manager.cpp
@@ -19,31 +19,48 @@
{
for (const auto& eid : eids)
{
- auto instanceId = instanceIdDb.next(eid);
- Request requestMsg(
- sizeof(pldm_msg_hdr) + PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES);
- auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
- auto rc = encode_query_device_identifiers_req(
- instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request);
- if (rc)
+ try
{
- instanceIdDb.free(eid, instanceId);
- error(
- "Failed to encode query device identifiers req for endpoint ID '{EID}', response code '{RC}'",
- "EID", eid, "RC", rc);
- continue;
+ sendQueryDeviceIdentifiersRequest(eid);
}
+ catch (const std::exception& e)
+ {
+ error(
+ "Failed to discover file descriptors for endpoint ID {EID} with {Error}",
+ "EID", eid, "ERROR", e);
+ }
+ }
+}
- rc = handler.registerRequest(
- eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS,
- std::move(requestMsg),
- std::bind_front(&InventoryManager::queryDeviceIdentifiers, this));
- if (rc)
- {
- error(
- "Failed to send query device identifiers request for endpoint ID '{EID}', response code '{RC}'",
- "EID", eid, "RC", rc);
- }
+void InventoryManager::sendQueryDeviceIdentifiersRequest(mctp_eid_t eid)
+{
+ auto instanceId = instanceIdDb.next(eid);
+ Request requestMsg(
+ sizeof(pldm_msg_hdr) + PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES);
+ auto request = new (requestMsg.data()) pldm_msg;
+ auto rc = encode_query_device_identifiers_req(
+ instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request);
+ if (rc)
+ {
+ instanceIdDb.free(eid, instanceId);
+ error(
+ "Failed to encode query device identifiers request for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ throw std::runtime_error(
+ "Failed to encode QueryDeviceIdentifiers request");
+ }
+
+ rc = handler.registerRequest(
+ eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS,
+ std::move(requestMsg),
+ std::bind_front(&InventoryManager::queryDeviceIdentifiers, this));
+ if (rc)
+ {
+ error(
+ "Failed to send query device identifiers request for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ throw std::runtime_error(
+ "Failed to send QueryDeviceIdentifiers request");
}
}
@@ -53,7 +70,7 @@
if (response == nullptr || !respMsgLen)
{
error(
- "No response received for query device identifiers for endpoint ID '{EID}'",
+ "No response received for query device identifiers for endpoint ID {EID}",
"EID", eid);
return;
}
@@ -69,7 +86,7 @@
if (rc)
{
error(
- "Failed to decode query device identifiers response for endpoint ID '{EID}' and descriptor count '{DESCRIPTOR_COUNT}', response code '{RC}'",
+ "Failed to decode query device identifiers response for endpoint ID {EID} and descriptor count {DESCRIPTOR_COUNT}, response code {RC}",
"EID", eid, "DESCRIPTOR_COUNT", descriptorCount, "RC", rc);
return;
}
@@ -77,7 +94,7 @@
if (completionCode)
{
error(
- "Failed to query device identifiers response for endpoint ID '{EID}', completion code '{CC}'",
+ "Failed to query device identifiers response for endpoint ID {EID}, completion code {CC}",
"EID", eid, "CC", completionCode);
return;
}
@@ -94,7 +111,7 @@
if (rc)
{
error(
- "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID '{EID}', response code '{RC}'",
+ "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID {EID}, response code {RC}",
"TYPE", descriptorType, "LENGTH", deviceIdentifiersLen, "EID",
eid, "RC", rc);
return;
@@ -119,7 +136,7 @@
if (rc)
{
error(
- "Failed to decode vendor-defined descriptor value for endpoint ID '{EID}', response code '{RC}'",
+ "Failed to decode vendor-defined descriptor value for endpoint ID {EID}, response code {RC}",
"EID", eid, "RC", rc);
return;
}
@@ -148,6 +165,378 @@
sendGetFirmwareParametersRequest(eid);
}
+void InventoryManager::sendQueryDownstreamDevicesRequest(mctp_eid_t eid)
+{
+ Request requestMsg(sizeof(pldm_msg_hdr));
+ auto instanceId = instanceIdDb.next(eid);
+ auto request = new (requestMsg.data()) pldm_msg;
+ auto rc = encode_query_downstream_devices_req(instanceId, request);
+ if (rc)
+ {
+ instanceIdDb.free(eid, instanceId);
+ error(
+ "Failed to encode query downstream devices request for endpoint ID EID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ throw std::runtime_error(
+ "Failed to encode query downstream devices request");
+ }
+
+ rc = handler.registerRequest(
+ eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_DEVICES,
+ std::move(requestMsg),
+ std::bind_front(&InventoryManager::queryDownstreamDevices, this));
+ if (rc)
+ {
+ error(
+ "Failed to send QueryDownstreamDevices request for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ }
+}
+
+void InventoryManager::queryDownstreamDevices(
+ mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
+{
+ if (!response || !respMsgLen)
+ {
+ error(
+ "No response received for QueryDownstreamDevices for endpoint ID {EID}",
+ "EID", eid);
+ return;
+ }
+
+ pldm_query_downstream_devices_resp downstreamDevicesResp{};
+ auto rc = decode_query_downstream_devices_resp(response, respMsgLen,
+ &downstreamDevicesResp);
+ if (rc)
+ {
+ error(
+ "Decoding QueryDownstreamDevices response failed for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ return;
+ }
+
+ switch (downstreamDevicesResp.completion_code)
+ {
+ case PLDM_SUCCESS:
+ break;
+ case PLDM_ERROR_UNSUPPORTED_PLDM_CMD:
+ /* QueryDownstreamDevices is optional, consider the device does not
+ * support Downstream Devices.
+ */
+ info("Endpoint ID {EID} does not support QueryDownstreamDevices",
+ "EID", eid);
+ return;
+ default:
+ error(
+ "QueryDownstreamDevices response failed with error completion code for endpoint ID {EID} with completion code {CC}",
+ "EID", eid, "CC", downstreamDevicesResp.completion_code);
+ return;
+ }
+
+ switch (downstreamDevicesResp.downstream_device_update_supported)
+ {
+ case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
+ /** DataTransferHandle will be skipped when TransferOperationFlag is
+ * `GetFirstPart`. Use 0x0 as default by following example in
+ * Figure 9 in DSP0267 1.1.0
+ */
+ try
+ {
+ sendQueryDownstreamIdentifiersRequest(eid, 0x0,
+ PLDM_GET_FIRSTPART);
+ }
+ catch (const std::exception& e)
+ {
+ error(
+ "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with {ERROR}",
+ "EID", eid, "ERROR", e);
+ }
+ break;
+ case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
+ /* The FDP does not support firmware updates but may report
+ * inventory information on downstream devices.
+ * In this scenario, sends only GetDownstreamFirmwareParameters
+ * to the FDP.
+ * The definition can be found at Table 15 of DSP0267_1.1.0
+ */
+ break;
+ default:
+ error(
+ "Unknown response of DownstreamDeviceUpdateSupported from endpoint ID {EID} with value {VALUE}",
+ "EID", eid, "VALUE",
+ downstreamDevicesResp.downstream_device_update_supported);
+ return;
+ }
+}
+
+void InventoryManager::sendQueryDownstreamIdentifiersRequest(
+ mctp_eid_t eid, uint32_t dataTransferHandle,
+ enum transfer_op_flag transferOperationFlag)
+{
+ auto instanceId = instanceIdDb.next(eid);
+ Request requestMsg(
+ sizeof(pldm_msg_hdr) + PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES);
+ auto request = new (requestMsg.data()) pldm_msg;
+ pldm_query_downstream_identifiers_req requestParameters{
+ dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)};
+
+ auto rc = encode_query_downstream_identifiers_req(
+ instanceId, &requestParameters, request,
+ PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES);
+ if (rc)
+ {
+ instanceIdDb.free(eid, instanceId);
+ error(
+ "Failed to encode query downstream identifiers request for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ throw std::runtime_error(
+ "Failed to encode query downstream identifiers request");
+ }
+
+ rc = handler.registerRequest(
+ eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS,
+ std::move(requestMsg),
+ std::bind_front(&InventoryManager::queryDownstreamIdentifiers, this));
+ if (rc)
+ {
+ error(
+ "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ }
+}
+
+void InventoryManager::queryDownstreamIdentifiers(
+ mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
+{
+ if (!response || !respMsgLen)
+ {
+ error(
+ "No response received for QueryDownstreamIdentifiers for endpoint ID {EID}",
+ "EID", eid);
+ descriptorMap.erase(eid);
+ return;
+ }
+
+ pldm_query_downstream_identifiers_resp downstreamIds{};
+ pldm_downstream_device_iter devs{};
+
+ auto rc = decode_query_downstream_identifiers_resp(response, respMsgLen,
+ &downstreamIds, &devs);
+ if (rc)
+ {
+ error(
+ "Decoding QueryDownstreamIdentifiers response failed for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ return;
+ }
+
+ if (downstreamIds.completion_code)
+ {
+ error(
+ "QueryDownstreamIdentifiers response failed with error completion code for endpoint ID {EID} with completion code {CC}",
+ "EID", eid, "CC", unsigned(downstreamIds.completion_code));
+ return;
+ }
+
+ DownstreamDeviceInfo initialDownstreamDevices{};
+ DownstreamDeviceInfo* downstreamDevices;
+ if (!downstreamDescriptorMap.contains(eid) ||
+ downstreamIds.transfer_flag == PLDM_START ||
+ downstreamIds.transfer_flag == PLDM_START_AND_END)
+ {
+ downstreamDevices = &initialDownstreamDevices;
+ }
+ else
+ {
+ downstreamDevices = &downstreamDescriptorMap.at(eid);
+ }
+
+ pldm_downstream_device dev;
+ foreach_pldm_downstream_device(devs, dev, rc)
+ {
+ pldm_descriptor desc;
+ Descriptors descriptors{};
+ foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)
+ {
+ const auto descriptorData =
+ new (const_cast<void*>(desc.descriptor_data))
+ uint8_t[desc.descriptor_length];
+ if (desc.descriptor_type != PLDM_FWUP_VENDOR_DEFINED)
+ {
+ std::vector<uint8_t> descData(
+ descriptorData, descriptorData + desc.descriptor_length);
+ descriptors.emplace(desc.descriptor_type, std::move(descData));
+ }
+ else
+ {
+ uint8_t descriptorTitleStrType = 0;
+ variable_field descriptorTitleStr{};
+ variable_field vendorDefinedDescriptorData{};
+
+ rc = decode_vendor_defined_descriptor_value(
+ descriptorData, desc.descriptor_length,
+ &descriptorTitleStrType, &descriptorTitleStr,
+ &vendorDefinedDescriptorData);
+
+ if (rc)
+ {
+ error(
+ "Decoding Vendor-defined descriptor value failed for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ return;
+ }
+
+ auto vendorDefinedDescriptorTitleStr =
+ utils::toString(descriptorTitleStr);
+ std::vector<uint8_t> vendorDescData(
+ vendorDefinedDescriptorData.ptr,
+ vendorDefinedDescriptorData.ptr +
+ vendorDefinedDescriptorData.length);
+ descriptors.emplace(
+ desc.descriptor_type,
+ std::make_tuple(vendorDefinedDescriptorTitleStr,
+ vendorDescData));
+ }
+ }
+ if (rc)
+ {
+ error(
+ "Failed to decode downstream device descriptor for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ return;
+ }
+ downstreamDevices->emplace(dev.downstream_device_index, descriptors);
+ }
+ if (rc)
+ {
+ error(
+ "Failed to decode downstream devices from iterator for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ return;
+ }
+
+ switch (downstreamIds.transfer_flag)
+ {
+ case PLDM_START:
+ downstreamDescriptorMap.insert_or_assign(
+ eid, std::move(initialDownstreamDevices));
+ [[fallthrough]];
+ case PLDM_MIDDLE:
+ sendQueryDownstreamIdentifiersRequest(
+ eid, downstreamIds.next_data_transfer_handle,
+ PLDM_GET_NEXTPART);
+ break;
+ case PLDM_START_AND_END:
+ downstreamDescriptorMap.insert_or_assign(
+ eid, std::move(initialDownstreamDevices));
+ /** DataTransferHandle will be skipped when TransferOperationFlag is
+ * `GetFirstPart`. Use 0x0 as default by following example in
+ * Figure 9 in DSP0267 1.1.0
+ */
+ [[fallthrough]];
+ case PLDM_END:
+ sendGetDownstreamFirmwareParametersRequest(eid, 0x0,
+ PLDM_GET_FIRSTPART);
+ break;
+ }
+}
+
+void InventoryManager::sendGetDownstreamFirmwareParametersRequest(
+ mctp_eid_t eid, uint32_t dataTransferHandle,
+ enum transfer_op_flag transferOperationFlag)
+{
+ Request requestMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES);
+ auto instanceId = instanceIdDb.next(eid);
+ auto request = new (requestMsg.data()) pldm_msg;
+ pldm_get_downstream_firmware_parameters_req requestParameters{
+ dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)};
+ auto rc = encode_get_downstream_firmware_parameters_req(
+ instanceId, &requestParameters, request,
+ PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES);
+ if (rc)
+ {
+ instanceIdDb.free(eid, instanceId);
+ error(
+ "Failed to encode query downstream firmware parameters request for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ throw std::runtime_error(
+ "Failed to encode query downstream firmware parameters request");
+ }
+
+ rc = handler.registerRequest(
+ eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS,
+ std::move(requestMsg),
+ std::bind_front(&InventoryManager::getDownstreamFirmwareParameters,
+ this));
+ if (rc)
+ {
+ error(
+ "Failed to send QueryDownstreamFirmwareParameters request for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ }
+}
+
+void InventoryManager::getDownstreamFirmwareParameters(
+ mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
+{
+ if (!response || !respMsgLen)
+ {
+ error(
+ "No response received for QueryDownstreamFirmwareParameters for endpoint ID {EID}",
+ "EID", eid);
+ descriptorMap.erase(eid);
+ return;
+ }
+
+ pldm_get_downstream_firmware_parameters_resp resp{};
+ pldm_downstream_device_parameters_iter params{};
+ pldm_downstream_device_parameters_entry entry{};
+
+ auto rc = decode_get_downstream_firmware_parameters_resp(
+ response, respMsgLen, &resp, ¶ms);
+
+ if (rc)
+ {
+ error(
+ "Decoding QueryDownstreamFirmwareParameters response failed for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ return;
+ }
+
+ if (resp.completion_code)
+ {
+ error(
+ "QueryDownstreamFirmwareParameters response failed with error completion code for endpoint ID {EID} with completion code {CC}",
+ "EID", eid, "CC", resp.completion_code);
+ return;
+ }
+
+ foreach_pldm_downstream_device_parameters_entry(params, entry, rc)
+ {
+ // Reserved for upcoming use
+ [[maybe_unused]] variable_field activeCompVerStr{
+ reinterpret_cast<const uint8_t*>(entry.active_comp_ver_str),
+ entry.active_comp_ver_str_len};
+ }
+ if (rc)
+ {
+ error(
+ "Failed to decode downstream device parameters from iterator for endpoint ID {EID} with response code {RC}",
+ "EID", eid, "RC", rc);
+ return;
+ }
+
+ switch (resp.transfer_flag)
+ {
+ case PLDM_START:
+ case PLDM_MIDDLE:
+ sendGetDownstreamFirmwareParametersRequest(
+ eid, resp.next_data_transfer_handle, PLDM_GET_NEXTPART);
+ break;
+ }
+}
+
void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid)
{
auto instanceId = instanceIdDb.next(eid);
@@ -160,7 +549,7 @@
{
instanceIdDb.free(eid, instanceId);
error(
- "Failed to encode get firmware parameters req for endpoint ID '{EID}', response code '{RC}'",
+ "Failed to encode get firmware parameters req for endpoint ID {EID}, response code {RC}",
"EID", eid, "RC", rc);
return;
}
@@ -172,7 +561,7 @@
if (rc)
{
error(
- "Failed to send get firmware parameters request for endpoint ID '{EID}', response code '{RC}'",
+ "Failed to send get firmware parameters request for endpoint ID {EID}, response code {RC}",
"EID", eid, "RC", rc);
}
}
@@ -183,7 +572,7 @@
if (response == nullptr || !respMsgLen)
{
error(
- "No response received for get firmware parameters for endpoint ID '{EID}'",
+ "No response received for get firmware parameters for endpoint ID {EID}",
"EID", eid);
descriptorMap.erase(eid);
return;
@@ -200,7 +589,7 @@
if (rc)
{
error(
- "Failed to decode get firmware parameters response for endpoint ID '{EID}', response code '{RC}'",
+ "Failed to decode get firmware parameters response for endpoint ID {EID}, response code {RC}",
"EID", eid, "RC", rc);
return;
}
@@ -209,7 +598,7 @@
{
auto fw_param_cc = fwParams.completion_code;
error(
- "Failed to get firmware parameters response for endpoint ID '{EID}', completion code '{CC}'",
+ "Failed to get firmware parameters response for endpoint ID {EID}, completion code {CC}",
"EID", eid, "CC", fw_param_cc);
return;
}
@@ -229,7 +618,7 @@
if (rc)
{
error(
- "Failed to decode component parameter table entry for endpoint ID '{EID}', response code '{RC}'",
+ "Failed to decode component parameter table entry for endpoint ID {EID}, response code {RC}",
"EID", eid, "RC", rc);
return;
}
diff --git a/fw-update/inventory_manager.hpp b/fw-update/inventory_manager.hpp
index 953d7a4..ade1fcd 100644
--- a/fw-update/inventory_manager.hpp
+++ b/fw-update/inventory_manager.hpp
@@ -34,15 +34,21 @@
* @param[in] instanceIdDb - Managing instance ID for PLDM requests
* @param[out] descriptorMap - Populate the firmware identifiers for the
* FDs managed by the BMC.
+ * @param[out] downstreamDescriptorMap - Populate the downstream
+ * identifiers for the FDs managed
+ * by the BMC.
* @param[out] componentInfoMap - Populate the component info for the FDs
* managed by the BMC.
*/
explicit InventoryManager(
pldm::requester::Handler<pldm::requester::Request>& handler,
InstanceIdDb& instanceIdDb, DescriptorMap& descriptorMap,
+ DownstreamDescriptorMap& downstreamDescriptorMap,
ComponentInfoMap& componentInfoMap) :
handler(handler), instanceIdDb(instanceIdDb),
- descriptorMap(descriptorMap), componentInfoMap(componentInfoMap)
+ descriptorMap(descriptorMap),
+ downstreamDescriptorMap(downstreamDescriptorMap),
+ componentInfoMap(componentInfoMap)
{}
/** @brief Discover the firmware identifiers and component details of FDs
@@ -68,6 +74,33 @@
void queryDeviceIdentifiers(mctp_eid_t eid, const pldm_msg* response,
size_t respMsgLen);
+ /** @brief Handler for QueryDownstreamDevices command response
+ *
+ * @param[in] eid - Remote MCTP endpoint
+ * @param[in] response - PLDM response message
+ * @param[in] respMsgLen - Response message length
+ */
+ void queryDownstreamDevices(mctp_eid_t eid, const pldm_msg* response,
+ size_t respMsgLen);
+
+ /** @brief Handler for QueryDownstreamIdentifiers command response
+ *
+ * @param[in] eid - Remote MCTP endpoint
+ * @param[in] response - PLDM response message
+ * @param[in] respMsgLen - Response message length
+ */
+ void queryDownstreamIdentifiers(mctp_eid_t eid, const pldm_msg* response,
+ size_t respMsgLen);
+
+ /** @brief Handler for GetDownstreamFirmwareParameters command response
+ *
+ * @param[in] eid - Remote MCTP endpoint
+ * @param[in] response - PLDM response message
+ * @param[in] respMsgLen - Response message length
+ */
+ void getDownstreamFirmwareParameters(
+ mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen);
+
/** @brief Handler for GetFirmwareParameters command response
*
* Handling the response of GetFirmwareParameters command and create
@@ -81,6 +114,45 @@
size_t respMsgLen);
private:
+ /**
+ * @brief Sends QueryDeviceIdentifiers request
+ *
+ * @param[in] eid - Remote MCTP endpoint
+ */
+ void sendQueryDeviceIdentifiersRequest(mctp_eid_t eid);
+
+ /**
+ * @brief Sends QueryDownstreamDevices request
+ *
+ * @param[in] eid - Remote MCTP endpoint
+ */
+ void sendQueryDownstreamDevicesRequest(mctp_eid_t eid);
+
+ /**
+ * @brief Sends QueryDownstreamIdentifiers request
+ *
+ * The request format is defined at Table 16 – QueryDownstreamIdentifiers
+ * command format in DSP0267_1.1.0
+ *
+ * @param[in] eid - Remote MCTP endpoint
+ * @param[in] dataTransferHandle - Data transfer handle
+ * @param[in] transferOperationFlag - Transfer operation flag
+ */
+ void sendQueryDownstreamIdentifiersRequest(
+ mctp_eid_t eid, uint32_t dataTransferHandle,
+ enum transfer_op_flag transferOperationFlag);
+
+ /**
+ * @brief Sends QueryDownstreamFirmwareParameters request
+ *
+ * @param[in] eid - Remote MCTP endpoint
+ * @param[in] dataTransferHandle - Data transfer handle
+ * @param[in] transferOperationFlag - Transfer operation flag
+ */
+ void sendGetDownstreamFirmwareParametersRequest(
+ mctp_eid_t eid, uint32_t dataTransferHandle,
+ const enum transfer_op_flag transferOperationFlag);
+
/** @brief Send GetFirmwareParameters command request
*
* @param[in] eid - Remote MCTP endpoint
@@ -96,6 +168,9 @@
/** @brief Device identifiers of the managed FDs */
DescriptorMap& descriptorMap;
+ /** @brief Downstream Device identifiers of the managed FDs */
+ DownstreamDescriptorMap& downstreamDescriptorMap;
+
/** @brief Component information needed for the update of the managed FDs */
ComponentInfoMap& componentInfoMap;
};
diff --git a/fw-update/manager.hpp b/fw-update/manager.hpp
index be45eb7..4d2a976 100644
--- a/fw-update/manager.hpp
+++ b/fw-update/manager.hpp
@@ -40,7 +40,8 @@
explicit Manager(Event& event,
requester::Handler<requester::Request>& handler,
pldm::InstanceIdDb& instanceIdDb) :
- inventoryMgr(handler, instanceIdDb, descriptorMap, componentInfoMap),
+ inventoryMgr(handler, instanceIdDb, descriptorMap,
+ downstreamDescriptorMap, componentInfoMap),
updateManager(event, handler, instanceIdDb, descriptorMap,
componentInfoMap)
{}
@@ -90,6 +91,10 @@
/** Descriptor information of all the discovered MCTP endpoints */
DescriptorMap descriptorMap;
+ /** Downstream descriptor information of all the discovered MCTP endpoints
+ */
+ DownstreamDescriptorMap downstreamDescriptorMap;
+
/** Component information of all the discovered MCTP endpoints */
ComponentInfoMap componentInfoMap;
diff --git a/fw-update/test/inventory_manager_test.cpp b/fw-update/test/inventory_manager_test.cpp
index 9d80be2..a768ab2 100644
--- a/fw-update/test/inventory_manager_test.cpp
+++ b/fw-update/test/inventory_manager_test.cpp
@@ -19,7 +19,7 @@
reqHandler(nullptr, event, instanceIdDb, false, seconds(1), 2,
milliseconds(100)),
inventoryManager(reqHandler, instanceIdDb, outDescriptorMap,
- outComponentInfoMap)
+ outDownstreamDescriptorMap, outComponentInfoMap)
{}
int fd = -1;
@@ -28,6 +28,7 @@
requester::Handler<requester::Request> reqHandler;
InventoryManager inventoryManager;
DescriptorMap outDescriptorMap{};
+ DownstreamDescriptorMap outDownstreamDescriptorMap{};
ComponentInfoMap outComponentInfoMap{};
};
@@ -100,6 +101,51 @@
EXPECT_EQ(outDescriptorMap.size(), 0);
}
+TEST_F(InventoryManagerTest, handleQueryDownstreamIdentifierResponse)
+{
+ constexpr uint8_t eid = 1;
+ constexpr uint8_t downstreamDeviceCount = 1;
+ constexpr uint32_t downstreamDeviceLen = 11;
+ constexpr size_t respPayloadLength =
+ PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN + downstreamDeviceLen;
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + respPayloadLength>
+ queryDownstreamIdentifiersResp{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0x15};
+ auto responseMsg = new (queryDownstreamIdentifiersResp.data()) pldm_msg;
+
+ inventoryManager.queryDownstreamIdentifiers(eid, responseMsg,
+ respPayloadLength);
+
+ DownstreamDeviceInfo downstreamDevices = {
+ {0,
+ {{PLDM_FWUP_IANA_ENTERPRISE_ID,
+ std::vector<uint8_t>{0x00, 0x00, 0xa0, 0x15}}}}};
+ DownstreamDescriptorMap refDownstreamDescriptorMap{
+ {eid, downstreamDevices}};
+
+ ASSERT_EQ(outDownstreamDescriptorMap.size(), downstreamDeviceCount);
+ ASSERT_EQ(outDownstreamDescriptorMap.size(),
+ refDownstreamDescriptorMap.size());
+ ASSERT_EQ(outDownstreamDescriptorMap, refDownstreamDescriptorMap);
+}
+
+TEST_F(InventoryManagerTest, handleQueryDownstreamIdentifierResponseErrorCC)
+{
+ constexpr size_t respPayloadLength = 1;
+ constexpr std::array<uint8_t, sizeof(pldm_msg_hdr) + respPayloadLength>
+ queryDownstreamIdentifiersResp{0x00, 0x00, 0x00, 0x01};
+ const auto responseMsg =
+ new (const_cast<unsigned char*>(queryDownstreamIdentifiersResp.data()))
+ pldm_msg;
+ inventoryManager.queryDownstreamIdentifiers(1, responseMsg,
+ respPayloadLength);
+
+ ASSERT_EQ(outDownstreamDescriptorMap.size(), 0);
+}
+
TEST_F(InventoryManagerTest, getFirmwareParametersResponse)
{
// constexpr uint16_t compCount = 2;