blob: f61428b6f9a8e168f8759c770ba23466743a5e07 [file] [log] [blame]
Tom Josephef90b0d2021-08-17 07:12:49 -07001#include "device_updater.hpp"
2
Tom Joseph4d8d5772021-08-17 07:35:05 -07003#include "activation.hpp"
4#include "update_manager.hpp"
5
George Liuc453e162022-12-21 17:16:23 +08006#include <libpldm/firmware_update.h>
7
Riya Dixit49cfb132023-03-02 04:26:53 -06008#include <phosphor-logging/lg2.hpp>
9
Tom Josephef90b0d2021-08-17 07:12:49 -070010#include <functional>
11
Riya Dixit49cfb132023-03-02 04:26:53 -060012PHOSPHOR_LOG2_USING;
13
Tom Josephef90b0d2021-08-17 07:12:49 -070014namespace pldm
15{
16
17namespace fw_update
18{
19
20void DeviceUpdater::startFwUpdateFlow()
21{
Andrew Jefferya330b2f2023-05-04 14:55:37 +093022 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -070023 // NumberOfComponents
24 const auto& applicableComponents =
25 std::get<ApplicableComponents>(fwDeviceIDRecord);
26 // PackageDataLength
27 const auto& fwDevicePkgData =
28 std::get<FirmwareDevicePackageData>(fwDeviceIDRecord);
29 // ComponentImageSetVersionString
30 const auto& compImageSetVersion =
31 std::get<ComponentImageSetVersion>(fwDeviceIDRecord);
32 variable_field compImgSetVerStrInfo{};
33 compImgSetVerStrInfo.ptr =
34 reinterpret_cast<const uint8_t*>(compImageSetVersion.data());
35 compImgSetVerStrInfo.length =
36 static_cast<uint8_t>(compImageSetVersion.size());
37
Patrick Williams16c2a0a2024-08-16 15:20:59 -040038 Request request(
39 sizeof(pldm_msg_hdr) + sizeof(struct pldm_request_update_req) +
40 compImgSetVerStrInfo.length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +053041 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -070042
43 auto rc = encode_request_update_req(
44 instanceId, maxTransferSize, applicableComponents.size(),
45 PLDM_FWUP_MIN_OUTSTANDING_REQ, fwDevicePkgData.size(),
46 PLDM_STR_TYPE_ASCII, compImgSetVerStrInfo.length, &compImgSetVerStrInfo,
47 requestMsg,
48 sizeof(struct pldm_request_update_req) + compImgSetVerStrInfo.length);
49 if (rc)
50 {
Tom Josephef90b0d2021-08-17 07:12:49 -070051 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -050052 updateManager->instanceIdDb.free(eid, instanceId);
53 error(
54 "Failed to encode request update request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050055 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -070056 }
57
Tom Josephb7e083e2021-10-26 15:10:03 +053058 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -070059 eid, instanceId, PLDM_FWUP, PLDM_REQUEST_UPDATE, std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +080060 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
61 this->requestUpdate(eid, response, respMsgLen);
62 });
Tom Josephef90b0d2021-08-17 07:12:49 -070063 if (rc)
64 {
Tom Josephef90b0d2021-08-17 07:12:49 -070065 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -050066 error(
67 "Failed to send request update for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050068 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -070069 }
70}
71
72void DeviceUpdater::requestUpdate(mctp_eid_t eid, const pldm_msg* response,
73 size_t respMsgLen)
74{
75 if (response == nullptr || !respMsgLen)
76 {
77 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -050078 error("No response received for request update for endpoint ID '{EID}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050079 "EID", eid);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +053080 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -070081 return;
82 }
83
84 uint8_t completionCode = 0;
85 uint16_t fdMetaDataLen = 0;
86 uint8_t fdWillSendPkgData = 0;
87
88 auto rc = decode_request_update_resp(response, respMsgLen, &completionCode,
89 &fdMetaDataLen, &fdWillSendPkgData);
90 if (rc)
91 {
Riya Dixit76f2c602024-03-28 07:34:12 -050092 error(
93 "Failed to decode request update response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050094 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -070095 return;
96 }
97 if (completionCode)
98 {
Riya Dixit49cfb132023-03-02 04:26:53 -060099 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500100 "Failure in request update response for endpoint ID '{EID}', completion code '{CC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500101 "EID", eid, "CC", completionCode);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530102 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700103 return;
104 }
105
106 // Optional fields DeviceMetaData and GetPackageData not handled
107 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530108 updateManager->event,
109 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
110 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700111}
112
113void DeviceUpdater::sendPassCompTableRequest(size_t offset)
114{
115 pldmRequest.reset();
116
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930117 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700118 // TransferFlag
119 const auto& applicableComponents =
120 std::get<ApplicableComponents>(fwDeviceIDRecord);
121 uint8_t transferFlag = 0;
122 if (applicableComponents.size() == 1)
123 {
124 transferFlag = PLDM_START_AND_END;
125 }
126 else if (offset == 0)
127 {
128 transferFlag = PLDM_START;
129 }
130 else if (offset == applicableComponents.size() - 1)
131 {
132 transferFlag = PLDM_END;
133 }
134 else
135 {
136 transferFlag = PLDM_MIDDLE;
137 }
138 const auto& comp = compImageInfos[applicableComponents[offset]];
139 // ComponentClassification
140 CompClassification compClassification = std::get<static_cast<size_t>(
141 ComponentImageInfoPos::CompClassificationPos)>(comp);
142 // ComponentIdentifier
143 CompIdentifier compIdentifier =
144 std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
145 comp);
146 // ComponentClassificationIndex
147 CompClassificationIndex compClassificationIndex{};
148 auto compKey = std::make_pair(compClassification, compIdentifier);
149 if (compInfo.contains(compKey))
150 {
151 auto search = compInfo.find(compKey);
152 compClassificationIndex = search->second;
153 }
154 else
155 {
156 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500157 error(
158 "Failed to find component classification '{CLASSIFICATION}' and identifier '{IDENTIFIER}'",
159 "CLASSIFICATION", compClassification, "IDENTIFIER", compIdentifier);
Tom Josephef90b0d2021-08-17 07:12:49 -0700160 }
161 // ComponentComparisonStamp
162 CompComparisonStamp compComparisonStamp = std::get<static_cast<size_t>(
163 ComponentImageInfoPos::CompComparisonStampPos)>(comp);
164 // ComponentVersionString
165 const auto& compVersion =
166 std::get<static_cast<size_t>(ComponentImageInfoPos::CompVersionPos)>(
167 comp);
168 variable_field compVerStrInfo{};
169 compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
170 compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
171
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400172 Request request(
173 sizeof(pldm_msg_hdr) + sizeof(struct pldm_pass_component_table_req) +
174 compVerStrInfo.length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530175 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700176 auto rc = encode_pass_component_table_req(
177 instanceId, transferFlag, compClassification, compIdentifier,
178 compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
179 compVerStrInfo.length, &compVerStrInfo, requestMsg,
180 sizeof(pldm_pass_component_table_req) + compVerStrInfo.length);
181 if (rc)
182 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700183 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500184 updateManager->instanceIdDb.free(eid, instanceId);
185 error(
186 "Failed to encode pass component table req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500187 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700188 }
189
Tom Josephb7e083e2021-10-26 15:10:03 +0530190 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700191 eid, instanceId, PLDM_FWUP, PLDM_PASS_COMPONENT_TABLE,
192 std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800193 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
194 this->passCompTable(eid, response, respMsgLen);
195 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700196 if (rc)
197 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700198 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500199 error(
200 "Failed to send pass component table request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500201 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700202 }
203}
204
205void DeviceUpdater::passCompTable(mctp_eid_t eid, const pldm_msg* response,
206 size_t respMsgLen)
207{
208 if (response == nullptr || !respMsgLen)
209 {
210 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500211 error(
212 "No response received for pass component table for endpoint ID '{EID}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500213 "EID", eid);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530214 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700215 return;
216 }
217
218 uint8_t completionCode = 0;
219 uint8_t compResponse = 0;
220 uint8_t compResponseCode = 0;
221
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400222 auto rc =
223 decode_pass_component_table_resp(response, respMsgLen, &completionCode,
224 &compResponse, &compResponseCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700225 if (rc)
226 {
227 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600228 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500229 "Failed to decode pass component table response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500230 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700231 return;
232 }
233 if (completionCode)
234 {
235 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600236 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500237 "Failed to pass component table response for endpoint ID '{EID}', completion code '{CC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500238 "EID", eid, "CC", completionCode);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530239 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700240 return;
241 }
242 // Handle ComponentResponseCode
243
244 const auto& applicableComponents =
245 std::get<ApplicableComponents>(fwDeviceIDRecord);
246 if (componentIndex == applicableComponents.size() - 1)
247 {
248 componentIndex = 0;
249 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530250 updateManager->event,
251 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
252 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700253 }
254 else
255 {
256 componentIndex++;
257 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530258 updateManager->event,
259 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
260 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700261 }
262}
263
264void DeviceUpdater::sendUpdateComponentRequest(size_t offset)
265{
266 pldmRequest.reset();
267
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930268 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700269 const auto& applicableComponents =
270 std::get<ApplicableComponents>(fwDeviceIDRecord);
271 const auto& comp = compImageInfos[applicableComponents[offset]];
272 // ComponentClassification
273 CompClassification compClassification = std::get<static_cast<size_t>(
274 ComponentImageInfoPos::CompClassificationPos)>(comp);
275 // ComponentIdentifier
276 CompIdentifier compIdentifier =
277 std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
278 comp);
279 // ComponentClassificationIndex
280 CompClassificationIndex compClassificationIndex{};
281 auto compKey = std::make_pair(compClassification, compIdentifier);
282 if (compInfo.contains(compKey))
283 {
284 auto search = compInfo.find(compKey);
285 compClassificationIndex = search->second;
286 }
287 else
288 {
289 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500290 error(
291 "Failed to find component classification '{CLASSIFICATION}' and identifier '{IDENTIFIER}'",
292 "CLASSIFICATION", compClassification, "IDENTIFIER", compIdentifier);
Tom Josephef90b0d2021-08-17 07:12:49 -0700293 }
294
295 // UpdateOptionFlags
296 bitfield32_t updateOptionFlags;
297 updateOptionFlags.bits.bit0 = std::get<3>(comp)[0];
298 // ComponentVersion
299 const auto& compVersion = std::get<7>(comp);
300 variable_field compVerStrInfo{};
301 compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
302 compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
303
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400304 Request request(
305 sizeof(pldm_msg_hdr) + sizeof(struct pldm_update_component_req) +
306 compVerStrInfo.length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530307 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700308
309 auto rc = encode_update_component_req(
310 instanceId, compClassification, compIdentifier, compClassificationIndex,
311 std::get<static_cast<size_t>(
312 ComponentImageInfoPos::CompComparisonStampPos)>(comp),
313 std::get<static_cast<size_t>(ComponentImageInfoPos::CompSizePos)>(comp),
314 updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrInfo.length,
315 &compVerStrInfo, requestMsg,
316 sizeof(pldm_update_component_req) + compVerStrInfo.length);
317 if (rc)
318 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700319 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500320 updateManager->instanceIdDb.free(eid, instanceId);
321 error(
322 "Failed to encode update component req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500323 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700324 }
325
Tom Josephb7e083e2021-10-26 15:10:03 +0530326 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700327 eid, instanceId, PLDM_FWUP, PLDM_UPDATE_COMPONENT, std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800328 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
329 this->updateComponent(eid, response, respMsgLen);
330 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700331 if (rc)
332 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700333 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500334 error(
335 "Failed to send update request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500336 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700337 }
338}
339
340void DeviceUpdater::updateComponent(mctp_eid_t eid, const pldm_msg* response,
341 size_t respMsgLen)
342{
343 if (response == nullptr || !respMsgLen)
344 {
345 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500346 error(
347 "No response received for update component with endpoint ID {EID}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500348 "EID", eid);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530349 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700350 return;
351 }
352
353 uint8_t completionCode = 0;
354 uint8_t compCompatibilityResp = 0;
355 uint8_t compCompatibilityRespCode = 0;
356 bitfield32_t updateOptionFlagsEnabled{};
357 uint16_t timeBeforeReqFWData = 0;
358
359 auto rc = decode_update_component_resp(
360 response, respMsgLen, &completionCode, &compCompatibilityResp,
361 &compCompatibilityRespCode, &updateOptionFlagsEnabled,
362 &timeBeforeReqFWData);
363 if (rc)
364 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500365 error(
366 "Failed to decode update request response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500367 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700368 return;
369 }
370 if (completionCode)
371 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600372 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500373 "Failed to update request response for endpoint ID '{EID}', completion code '{CC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500374 "EID", eid, "CC", completionCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700375 return;
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530376 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700377 }
378}
379
P Arun Kumar Reddy6fa09e92025-04-25 11:24:06 +0530380void DeviceUpdater::createRequestFwDataTimer()
381{
382 reqFwDataTimer = std::make_unique<sdbusplus::Timer>([this]() -> void {
383 componentUpdateStatus[componentIndex] = false;
384 sendCancelUpdateComponentRequest();
385 updateManager->updateDeviceCompletion(eid, false);
386 });
387}
388
Tom Josephef90b0d2021-08-17 07:12:49 -0700389Response DeviceUpdater::requestFwData(const pldm_msg* request,
390 size_t payloadLength)
391{
392 uint8_t completionCode = PLDM_SUCCESS;
393 uint32_t offset = 0;
394 uint32_t length = 0;
395 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530396 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700397 auto rc = decode_request_firmware_data_req(request, payloadLength, &offset,
398 &length);
399 if (rc)
400 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600401 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500402 "Failed to decode request firmware date request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500403 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700404 rc = encode_request_firmware_data_resp(
405 request->hdr.instance_id, PLDM_ERROR_INVALID_DATA, responseMsg,
406 sizeof(completionCode));
407 if (rc)
408 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600409 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500410 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500411 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700412 }
413 return response;
414 }
415
416 const auto& applicableComponents =
417 std::get<ApplicableComponents>(fwDeviceIDRecord);
418 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
419 auto compOffset = std::get<5>(comp);
420 auto compSize = std::get<6>(comp);
Eric Yang91197522024-12-06 15:44:54 +0800421 debug("Decoded fw request data at offset '{OFFSET}' and length '{LENGTH}' ",
422 "OFFSET", offset, "LENGTH", length);
Tom Josephef90b0d2021-08-17 07:12:49 -0700423 if (length < PLDM_FWUP_BASELINE_TRANSFER_SIZE || length > maxTransferSize)
424 {
425 rc = encode_request_firmware_data_resp(
426 request->hdr.instance_id, PLDM_FWUP_INVALID_TRANSFER_LENGTH,
427 responseMsg, sizeof(completionCode));
428 if (rc)
429 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600430 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500431 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500432 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700433 }
434 return response;
435 }
436
437 if (offset + length > compSize + PLDM_FWUP_BASELINE_TRANSFER_SIZE)
438 {
439 rc = encode_request_firmware_data_resp(
440 request->hdr.instance_id, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg,
441 sizeof(completionCode));
442 if (rc)
443 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600444 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500445 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500446 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700447 }
448 return response;
449 }
450
451 size_t padBytes = 0;
452 if (offset + length > compSize)
453 {
454 padBytes = offset + length - compSize;
455 }
456
457 response.resize(sizeof(pldm_msg_hdr) + sizeof(completionCode) + length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530458 responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700459 package.seekg(compOffset + offset);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400460 package.read(
461 reinterpret_cast<char*>(
462 response.data() + sizeof(pldm_msg_hdr) + sizeof(completionCode)),
463 length - padBytes);
464 rc = encode_request_firmware_data_resp(
465 request->hdr.instance_id, completionCode, responseMsg,
466 sizeof(completionCode));
Tom Josephef90b0d2021-08-17 07:12:49 -0700467 if (rc)
468 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600469 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500470 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500471 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700472 return response;
473 }
474
P Arun Kumar Reddy6fa09e92025-04-25 11:24:06 +0530475 if (!reqFwDataTimer)
476 {
477 if (offset != 0)
478 {
479 warning("First data request is not at offset 0");
480 }
481 createRequestFwDataTimer();
482 }
483
484 if (reqFwDataTimer)
485 {
486 reqFwDataTimer->start(std::chrono::seconds(updateTimeoutSeconds),
487 false);
488 }
489 else
490 {
491 error(
492 "Failed to start timer for handling request firmware data for endpoint ID {EID}",
493 "EID", eid, "RC", rc);
494 }
495
Tom Josephef90b0d2021-08-17 07:12:49 -0700496 return response;
497}
498
499Response DeviceUpdater::transferComplete(const pldm_msg* request,
500 size_t payloadLength)
501{
502 uint8_t completionCode = PLDM_SUCCESS;
503 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530504 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700505
P Arun Kumar Reddy6fa09e92025-04-25 11:24:06 +0530506 if (reqFwDataTimer)
507 {
508 reqFwDataTimer->stop();
509 reqFwDataTimer.reset();
510 }
511
Tom Josephef90b0d2021-08-17 07:12:49 -0700512 uint8_t transferResult = 0;
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400513 auto rc =
514 decode_transfer_complete_req(request, payloadLength, &transferResult);
Tom Josephef90b0d2021-08-17 07:12:49 -0700515 if (rc)
516 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500517 error(
518 "Failed to decode TransferComplete request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500519 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700520 rc = encode_transfer_complete_resp(request->hdr.instance_id,
521 PLDM_ERROR_INVALID_DATA, responseMsg,
522 sizeof(completionCode));
523 if (rc)
524 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600525 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500526 "Failed to encode TransferComplete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500527 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700528 }
529 return response;
530 }
531
532 const auto& applicableComponents =
533 std::get<ApplicableComponents>(fwDeviceIDRecord);
534 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
535 const auto& compVersion = std::get<7>(comp);
536
537 if (transferResult == PLDM_FWUP_TRANSFER_SUCCESS)
538 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600539 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500540 "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' transfer complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500541 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700542 }
543 else
544 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600545 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500546 "Failure in transfer of the component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - {RESULT}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500547 "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT",
548 transferResult);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530549 updateManager->updateDeviceCompletion(eid, false);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530550 componentUpdateStatus[componentIndex] = false;
551 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700552 }
553
554 rc = encode_transfer_complete_resp(request->hdr.instance_id, completionCode,
555 responseMsg, sizeof(completionCode));
556 if (rc)
557 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500558 error(
559 "Failed to encode transfer complete response of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500560 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700561 return response;
562 }
563
564 return response;
565}
566
567Response DeviceUpdater::verifyComplete(const pldm_msg* request,
568 size_t payloadLength)
569{
570 uint8_t completionCode = PLDM_SUCCESS;
571 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530572 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700573
574 uint8_t verifyResult = 0;
575 auto rc = decode_verify_complete_req(request, payloadLength, &verifyResult);
576 if (rc)
577 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500578 error(
579 "Failed to decode verify complete request of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500580 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700581 rc = encode_verify_complete_resp(request->hdr.instance_id,
582 PLDM_ERROR_INVALID_DATA, responseMsg,
583 sizeof(completionCode));
584 if (rc)
585 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600586 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500587 "Failed to encode verify complete response of endpoint ID '{EID}', response code '{RC}'.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500588 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700589 }
590 return response;
591 }
592
593 const auto& applicableComponents =
594 std::get<ApplicableComponents>(fwDeviceIDRecord);
595 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
596 const auto& compVersion = std::get<7>(comp);
597
598 if (verifyResult == PLDM_FWUP_VERIFY_SUCCESS)
599 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600600 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500601 "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' verification complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500602 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700603 }
604 else
605 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600606 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500607 "Failed to verify component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - '{RESULT}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500608 "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT",
609 verifyResult);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530610 updateManager->updateDeviceCompletion(eid, false);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530611 componentUpdateStatus[componentIndex] = false;
612 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700613 }
614
615 rc = encode_verify_complete_resp(request->hdr.instance_id, completionCode,
616 responseMsg, sizeof(completionCode));
617 if (rc)
618 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500619 error(
620 "Failed to encode verify complete response for endpoint ID '{EID}', response code - {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500621 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700622 return response;
623 }
624
625 return response;
626}
627
628Response DeviceUpdater::applyComplete(const pldm_msg* request,
629 size_t payloadLength)
630{
631 uint8_t completionCode = PLDM_SUCCESS;
632 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530633 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700634
635 uint8_t applyResult = 0;
636 bitfield16_t compActivationModification{};
637 auto rc = decode_apply_complete_req(request, payloadLength, &applyResult,
638 &compActivationModification);
639 if (rc)
640 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500641 error(
642 "Failed to decode apply complete request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500643 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700644 rc = encode_apply_complete_resp(request->hdr.instance_id,
645 PLDM_ERROR_INVALID_DATA, responseMsg,
646 sizeof(completionCode));
647 if (rc)
648 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600649 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500650 "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500651 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700652 }
653 return response;
654 }
655
656 const auto& applicableComponents =
657 std::get<ApplicableComponents>(fwDeviceIDRecord);
658 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
659 const auto& compVersion = std::get<7>(comp);
660
661 if (applyResult == PLDM_FWUP_APPLY_SUCCESS ||
662 applyResult == PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD)
663 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600664 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500665 "Component endpoint ID '{EID}' with '{COMPONENT_VERSION}' apply complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500666 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Joseph4d8d5772021-08-17 07:35:05 -0700667 updateManager->updateActivationProgress();
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530668 if (componentIndex == applicableComponents.size() - 1)
669 {
670 componentIndex = 0;
671 componentUpdateStatus.clear();
672 componentUpdateStatus[componentIndex] = true;
673 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
674 updateManager->event,
675 std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this));
676 }
677 else
678 {
679 componentIndex++;
680 componentUpdateStatus[componentIndex] = true;
681 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
682 updateManager->event,
683 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
684 componentIndex));
685 }
Tom Josephef90b0d2021-08-17 07:12:49 -0700686 }
687 else
688 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600689 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500690 "Failed to apply component endpoint ID '{EID}' and version '{COMPONENT_VERSION}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500691 "EID", eid, "COMPONENT_VERSION", compVersion, "ERROR", applyResult);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530692 updateManager->updateDeviceCompletion(eid, false);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530693 componentUpdateStatus[componentIndex] = false;
694 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700695 }
696
697 rc = encode_apply_complete_resp(request->hdr.instance_id, completionCode,
698 responseMsg, sizeof(completionCode));
699 if (rc)
700 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500701 error(
702 "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500703 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700704 return response;
705 }
706
Tom Josephef90b0d2021-08-17 07:12:49 -0700707 return response;
708}
709
710void DeviceUpdater::sendActivateFirmwareRequest()
711{
712 pldmRequest.reset();
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930713 auto instanceId = updateManager->instanceIdDb.next(eid);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400714 Request request(
715 sizeof(pldm_msg_hdr) + sizeof(struct pldm_activate_firmware_req));
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530716 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700717
718 auto rc = encode_activate_firmware_req(
719 instanceId, PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
720 sizeof(pldm_activate_firmware_req));
721 if (rc)
722 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930723 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit76f2c602024-03-28 07:34:12 -0500724 error(
725 "Failed to encode activate firmware req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500726 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700727 }
728
Tom Josephb7e083e2021-10-26 15:10:03 +0530729 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700730 eid, instanceId, PLDM_FWUP, PLDM_ACTIVATE_FIRMWARE, std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800731 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
732 this->activateFirmware(eid, response, respMsgLen);
733 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700734 if (rc)
735 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500736 error(
737 "Failed to send activate firmware request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500738 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700739 }
740}
741
742void DeviceUpdater::activateFirmware(mctp_eid_t eid, const pldm_msg* response,
743 size_t respMsgLen)
744{
745 if (response == nullptr || !respMsgLen)
746 {
747 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500748 error(
749 "No response received for activate firmware for endpoint ID '{EID}'",
750 "EID", eid);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530751 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700752 return;
753 }
754
755 uint8_t completionCode = 0;
756 uint16_t estimatedTimeForActivation = 0;
757
758 auto rc = decode_activate_firmware_resp(
759 response, respMsgLen, &completionCode, &estimatedTimeForActivation);
760 if (rc)
761 {
762 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500763 error(
764 "Failed to decode activate firmware response for endpoint ID '{EID}', response code '{RC}'",
765 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700766 return;
767 }
768 if (completionCode)
769 {
770 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600771 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500772 "Failed to activate firmware response for endpoint ID '{EID}', completion code '{CC}'",
773 "EID", eid, "CC", completionCode);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530774 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700775 return;
776 }
Tom Joseph4d8d5772021-08-17 07:35:05 -0700777
778 updateManager->updateDeviceCompletion(eid, true);
Tom Josephef90b0d2021-08-17 07:12:49 -0700779}
780
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530781void DeviceUpdater::sendCancelUpdateComponentRequest()
782{
783 pldmRequest.reset();
784 auto instanceId = updateManager->instanceIdDb.next(eid);
785 Request request(sizeof(pldm_msg_hdr));
786 auto requestMsg = new (request.data()) pldm_msg;
787
788 auto rc = encode_cancel_update_component_req(
789 instanceId, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES);
790 if (rc)
791 {
792 updateManager->instanceIdDb.free(eid, instanceId);
793 error(
794 "Failed to encode cancel update component request for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', response code '{RC}'",
795 "EID", eid, "COMPONENT_INDEX", componentIndex, "RC", rc);
796 return;
797 }
798
799 rc = updateManager->handler.registerRequest(
800 eid, instanceId, PLDM_FWUP, PLDM_CANCEL_UPDATE_COMPONENT,
801 std::move(request),
802 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
803 this->cancelUpdateComponent(eid, response, respMsgLen);
804 });
805 if (rc)
806 {
807 error(
808 "Failed to send cancel update component request for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', response code '{RC}'",
809 "EID", eid, "COMPONENT_INDEX", componentIndex, "RC", rc);
810 }
811}
812
813void DeviceUpdater::cancelUpdateComponent(
814 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
815{
816 // Check if response is valid
817 if (response == nullptr || !respMsgLen)
818 {
819 error(
820 "No response received for cancel update component for endpoint ID '{EID}'",
821 "EID", eid);
822 return;
823 }
824
825 uint8_t completionCode = 0;
826 auto rc = decode_cancel_update_component_resp(response, respMsgLen,
827 &completionCode);
828 if (rc)
829 {
830 error(
831 "Failed to decode cancel update component response for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', completion code '{CC}'",
832 "EID", eid, "COMPONENT_INDEX", componentIndex, "CC",
833 completionCode);
834 return;
835 }
836 if (completionCode)
837 {
838 error(
839 "Failed to cancel update component for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', completion code '{CC}'",
840 "EID", eid, "COMPONENT_INDEX", componentIndex, "CC",
841 completionCode);
842 return;
843 }
844
845 const auto& applicableComponents =
846 std::get<ApplicableComponents>(fwDeviceIDRecord);
847 // Check if this is the last component being cancelled
848 if (componentIndex == applicableComponents.size() - 1)
849 {
850 for (auto& compStatus : componentUpdateStatus)
851 {
852 if (compStatus.second)
853 {
854 // If at least one component update succeeded, proceed with
855 // activation
856 componentIndex = 0;
857 componentUpdateStatus.clear();
858 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
859 updateManager->event,
860 std::bind(&DeviceUpdater::sendActivateFirmwareRequest,
861 this));
862 return;
863 }
864 }
865 updateManager->updateDeviceCompletion(eid, false);
866 }
867 else
868 {
869 // Move to next component and update its status
870 componentIndex++;
871 componentUpdateStatus[componentIndex] = true;
872 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
873 updateManager->event,
874 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
875 componentIndex));
876 }
877 return;
878}
879
Tom Josephef90b0d2021-08-17 07:12:49 -0700880} // namespace fw_update
881
Patrick Williams6da4f912023-05-10 07:50:53 -0500882} // namespace pldm