fw-update: Implement RequestFirmwareData timeout (UA_T2)
This commit introduces the UA_T2 timeout mechanism for the
RequestFirmwareData command as specified in the Timing Specification
section of the PLDM Firmware Update Specification. The Update Agent(UA),
which orchestrates firmware updates to devices, will now enforce this
timeout to ensure reliable update processes.
The timeout has a default value of 60 seconds is set according to the
PLDM specification's minimum requirement for UA_T2.
Tests:
- Simulating a timeout by turning off the components during a FW update
```
Decoded fw request data at offset '589824' and length '4096' for endpoint ID 26 and Component index 0
Decoded fw request data at offset '663552' and length '4096' for endpoint ID 18 and Component index 0
Request firmware data timed out. No command received from FD within the expected time of 60s from endpoint ID 26, component index 0
Sending cancel update component request for endpoint ID 26
8c 05 1c
Request firmware data timed out. No command received from FD within the expected time of 60s from endpoint ID 18, component index 0
Sending cancel update component request for endpoint ID 18
8c 05 1c
```
Change-Id: I9d34bffa0a4be81d3e8564994a2ea0ef6f2aecd6
Signed-off-by: P Arun Kumar Reddy <arunpapannagari23@gmail.com>
diff --git a/fw-update/device_updater.cpp b/fw-update/device_updater.cpp
index 14d507b..f61428b 100644
--- a/fw-update/device_updater.cpp
+++ b/fw-update/device_updater.cpp
@@ -377,6 +377,15 @@
}
}
+void DeviceUpdater::createRequestFwDataTimer()
+{
+ reqFwDataTimer = std::make_unique<sdbusplus::Timer>([this]() -> void {
+ componentUpdateStatus[componentIndex] = false;
+ sendCancelUpdateComponentRequest();
+ updateManager->updateDeviceCompletion(eid, false);
+ });
+}
+
Response DeviceUpdater::requestFwData(const pldm_msg* request,
size_t payloadLength)
{
@@ -463,6 +472,27 @@
return response;
}
+ if (!reqFwDataTimer)
+ {
+ if (offset != 0)
+ {
+ warning("First data request is not at offset 0");
+ }
+ createRequestFwDataTimer();
+ }
+
+ if (reqFwDataTimer)
+ {
+ reqFwDataTimer->start(std::chrono::seconds(updateTimeoutSeconds),
+ false);
+ }
+ else
+ {
+ error(
+ "Failed to start timer for handling request firmware data for endpoint ID {EID}",
+ "EID", eid, "RC", rc);
+ }
+
return response;
}
@@ -473,6 +503,12 @@
Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
auto responseMsg = new (response.data()) pldm_msg;
+ if (reqFwDataTimer)
+ {
+ reqFwDataTimer->stop();
+ reqFwDataTimer.reset();
+ }
+
uint8_t transferResult = 0;
auto rc =
decode_transfer_complete_req(request, payloadLength, &transferResult);
diff --git a/fw-update/device_updater.hpp b/fw-update/device_updater.hpp
index 11570a1..8b15dfd 100644
--- a/fw-update/device_updater.hpp
+++ b/fw-update/device_updater.hpp
@@ -4,6 +4,7 @@
#include "requester/handler.hpp"
#include "requester/request.hpp"
+#include <sdbusplus/timer.hpp>
#include <sdeventplus/event.hpp>
#include <sdeventplus/source/event.hpp>
@@ -189,6 +190,11 @@
*/
void sendCancelUpdateComponentRequest();
+ /**
+ * @brief Create a timer to handle RequestFirmwareData timeout (UA_T2)
+ */
+ void createRequestFwDataTimer();
+
/** @brief Endpoint ID of the firmware device */
mctp_eid_t eid;
@@ -233,6 +239,19 @@
* cancelled
*/
ComponentUpdateStatusMap componentUpdateStatus;
+
+ /**
+ * @brief Timeout in seconds for the UA to cancel the component update if no
+ * command is received from the FD during component image transfer stage
+ *
+ */
+ static constexpr int updateTimeoutSeconds = UPDATE_TIMEOUT_SECONDS;
+
+ /**
+ * @brief Timer to handle RequestFirmwareData timeout(UA_T2)
+ *
+ */
+ std::unique_ptr<sdbusplus::Timer> reqFwDataTimer;
};
} // namespace fw_update
diff --git a/meson.build b/meson.build
index 3c7db76..945886f 100644
--- a/meson.build
+++ b/meson.build
@@ -137,6 +137,7 @@
get_option('default-sensor-update-interval'),
)
conf_data.set('SENSOR_POLLING_TIME', get_option('sensor-polling-time'))
+conf_data.set('UPDATE_TIMEOUT_SECONDS', get_option('update-timeout-seconds'))
configure_file(output: 'config.h', configuration: conf_data)
diff --git a/meson.options b/meson.options
index 0ada2a0..bd51f70 100644
--- a/meson.options
+++ b/meson.options
@@ -128,6 +128,17 @@
requested by the FD, via RequestFirmwareData command''',
)
+option(
+ 'update-timeout-seconds',
+ type: 'integer',
+ min: 60,
+ max: 90,
+ value: 60,
+ description: '''Timeout in seconds for the UA to cancel the component update
+ if no command is received from the FD during component image
+ transfer stage''',
+)
+
# Bios Attributes option
option(
'system-specific-bios-json',