blob: 14d507bafeb8cd441e91ed37804495c38b9d4be6 [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
380Response DeviceUpdater::requestFwData(const pldm_msg* request,
381 size_t payloadLength)
382{
383 uint8_t completionCode = PLDM_SUCCESS;
384 uint32_t offset = 0;
385 uint32_t length = 0;
386 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530387 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700388 auto rc = decode_request_firmware_data_req(request, payloadLength, &offset,
389 &length);
390 if (rc)
391 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600392 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500393 "Failed to decode request firmware date request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500394 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700395 rc = encode_request_firmware_data_resp(
396 request->hdr.instance_id, PLDM_ERROR_INVALID_DATA, responseMsg,
397 sizeof(completionCode));
398 if (rc)
399 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600400 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500401 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500402 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700403 }
404 return response;
405 }
406
407 const auto& applicableComponents =
408 std::get<ApplicableComponents>(fwDeviceIDRecord);
409 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
410 auto compOffset = std::get<5>(comp);
411 auto compSize = std::get<6>(comp);
Eric Yang91197522024-12-06 15:44:54 +0800412 debug("Decoded fw request data at offset '{OFFSET}' and length '{LENGTH}' ",
413 "OFFSET", offset, "LENGTH", length);
Tom Josephef90b0d2021-08-17 07:12:49 -0700414 if (length < PLDM_FWUP_BASELINE_TRANSFER_SIZE || length > maxTransferSize)
415 {
416 rc = encode_request_firmware_data_resp(
417 request->hdr.instance_id, PLDM_FWUP_INVALID_TRANSFER_LENGTH,
418 responseMsg, sizeof(completionCode));
419 if (rc)
420 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600421 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500422 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500423 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700424 }
425 return response;
426 }
427
428 if (offset + length > compSize + PLDM_FWUP_BASELINE_TRANSFER_SIZE)
429 {
430 rc = encode_request_firmware_data_resp(
431 request->hdr.instance_id, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg,
432 sizeof(completionCode));
433 if (rc)
434 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600435 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500436 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500437 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700438 }
439 return response;
440 }
441
442 size_t padBytes = 0;
443 if (offset + length > compSize)
444 {
445 padBytes = offset + length - compSize;
446 }
447
448 response.resize(sizeof(pldm_msg_hdr) + sizeof(completionCode) + length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530449 responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700450 package.seekg(compOffset + offset);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400451 package.read(
452 reinterpret_cast<char*>(
453 response.data() + sizeof(pldm_msg_hdr) + sizeof(completionCode)),
454 length - padBytes);
455 rc = encode_request_firmware_data_resp(
456 request->hdr.instance_id, completionCode, responseMsg,
457 sizeof(completionCode));
Tom Josephef90b0d2021-08-17 07:12:49 -0700458 if (rc)
459 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600460 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500461 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500462 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700463 return response;
464 }
465
466 return response;
467}
468
469Response DeviceUpdater::transferComplete(const pldm_msg* request,
470 size_t payloadLength)
471{
472 uint8_t completionCode = PLDM_SUCCESS;
473 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530474 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700475
476 uint8_t transferResult = 0;
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400477 auto rc =
478 decode_transfer_complete_req(request, payloadLength, &transferResult);
Tom Josephef90b0d2021-08-17 07:12:49 -0700479 if (rc)
480 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500481 error(
482 "Failed to decode TransferComplete request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500483 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700484 rc = encode_transfer_complete_resp(request->hdr.instance_id,
485 PLDM_ERROR_INVALID_DATA, responseMsg,
486 sizeof(completionCode));
487 if (rc)
488 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600489 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500490 "Failed to encode TransferComplete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500491 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700492 }
493 return response;
494 }
495
496 const auto& applicableComponents =
497 std::get<ApplicableComponents>(fwDeviceIDRecord);
498 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
499 const auto& compVersion = std::get<7>(comp);
500
501 if (transferResult == PLDM_FWUP_TRANSFER_SUCCESS)
502 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600503 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500504 "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' transfer complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500505 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700506 }
507 else
508 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600509 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500510 "Failure in transfer of the component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - {RESULT}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500511 "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT",
512 transferResult);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530513 updateManager->updateDeviceCompletion(eid, false);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530514 componentUpdateStatus[componentIndex] = false;
515 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700516 }
517
518 rc = encode_transfer_complete_resp(request->hdr.instance_id, completionCode,
519 responseMsg, sizeof(completionCode));
520 if (rc)
521 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500522 error(
523 "Failed to encode transfer complete response of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500524 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700525 return response;
526 }
527
528 return response;
529}
530
531Response DeviceUpdater::verifyComplete(const pldm_msg* request,
532 size_t payloadLength)
533{
534 uint8_t completionCode = PLDM_SUCCESS;
535 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530536 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700537
538 uint8_t verifyResult = 0;
539 auto rc = decode_verify_complete_req(request, payloadLength, &verifyResult);
540 if (rc)
541 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500542 error(
543 "Failed to decode verify complete request of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500544 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700545 rc = encode_verify_complete_resp(request->hdr.instance_id,
546 PLDM_ERROR_INVALID_DATA, responseMsg,
547 sizeof(completionCode));
548 if (rc)
549 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600550 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500551 "Failed to encode verify complete response of endpoint ID '{EID}', response code '{RC}'.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500552 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700553 }
554 return response;
555 }
556
557 const auto& applicableComponents =
558 std::get<ApplicableComponents>(fwDeviceIDRecord);
559 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
560 const auto& compVersion = std::get<7>(comp);
561
562 if (verifyResult == PLDM_FWUP_VERIFY_SUCCESS)
563 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600564 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500565 "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' verification complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500566 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700567 }
568 else
569 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600570 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500571 "Failed to verify component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - '{RESULT}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500572 "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT",
573 verifyResult);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530574 updateManager->updateDeviceCompletion(eid, false);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530575 componentUpdateStatus[componentIndex] = false;
576 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700577 }
578
579 rc = encode_verify_complete_resp(request->hdr.instance_id, completionCode,
580 responseMsg, sizeof(completionCode));
581 if (rc)
582 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500583 error(
584 "Failed to encode verify complete response for endpoint ID '{EID}', response code - {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500585 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700586 return response;
587 }
588
589 return response;
590}
591
592Response DeviceUpdater::applyComplete(const pldm_msg* request,
593 size_t payloadLength)
594{
595 uint8_t completionCode = PLDM_SUCCESS;
596 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530597 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700598
599 uint8_t applyResult = 0;
600 bitfield16_t compActivationModification{};
601 auto rc = decode_apply_complete_req(request, payloadLength, &applyResult,
602 &compActivationModification);
603 if (rc)
604 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500605 error(
606 "Failed to decode apply complete request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500607 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700608 rc = encode_apply_complete_resp(request->hdr.instance_id,
609 PLDM_ERROR_INVALID_DATA, responseMsg,
610 sizeof(completionCode));
611 if (rc)
612 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600613 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500614 "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500615 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700616 }
617 return response;
618 }
619
620 const auto& applicableComponents =
621 std::get<ApplicableComponents>(fwDeviceIDRecord);
622 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
623 const auto& compVersion = std::get<7>(comp);
624
625 if (applyResult == PLDM_FWUP_APPLY_SUCCESS ||
626 applyResult == PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD)
627 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600628 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500629 "Component endpoint ID '{EID}' with '{COMPONENT_VERSION}' apply complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500630 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Joseph4d8d5772021-08-17 07:35:05 -0700631 updateManager->updateActivationProgress();
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530632 if (componentIndex == applicableComponents.size() - 1)
633 {
634 componentIndex = 0;
635 componentUpdateStatus.clear();
636 componentUpdateStatus[componentIndex] = true;
637 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
638 updateManager->event,
639 std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this));
640 }
641 else
642 {
643 componentIndex++;
644 componentUpdateStatus[componentIndex] = true;
645 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
646 updateManager->event,
647 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
648 componentIndex));
649 }
Tom Josephef90b0d2021-08-17 07:12:49 -0700650 }
651 else
652 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600653 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500654 "Failed to apply component endpoint ID '{EID}' and version '{COMPONENT_VERSION}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500655 "EID", eid, "COMPONENT_VERSION", compVersion, "ERROR", applyResult);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530656 updateManager->updateDeviceCompletion(eid, false);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530657 componentUpdateStatus[componentIndex] = false;
658 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700659 }
660
661 rc = encode_apply_complete_resp(request->hdr.instance_id, completionCode,
662 responseMsg, sizeof(completionCode));
663 if (rc)
664 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500665 error(
666 "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500667 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700668 return response;
669 }
670
Tom Josephef90b0d2021-08-17 07:12:49 -0700671 return response;
672}
673
674void DeviceUpdater::sendActivateFirmwareRequest()
675{
676 pldmRequest.reset();
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930677 auto instanceId = updateManager->instanceIdDb.next(eid);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400678 Request request(
679 sizeof(pldm_msg_hdr) + sizeof(struct pldm_activate_firmware_req));
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530680 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700681
682 auto rc = encode_activate_firmware_req(
683 instanceId, PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
684 sizeof(pldm_activate_firmware_req));
685 if (rc)
686 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930687 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit76f2c602024-03-28 07:34:12 -0500688 error(
689 "Failed to encode activate firmware req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500690 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700691 }
692
Tom Josephb7e083e2021-10-26 15:10:03 +0530693 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700694 eid, instanceId, PLDM_FWUP, PLDM_ACTIVATE_FIRMWARE, std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800695 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
696 this->activateFirmware(eid, response, respMsgLen);
697 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700698 if (rc)
699 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500700 error(
701 "Failed to send activate firmware request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500702 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700703 }
704}
705
706void DeviceUpdater::activateFirmware(mctp_eid_t eid, const pldm_msg* response,
707 size_t respMsgLen)
708{
709 if (response == nullptr || !respMsgLen)
710 {
711 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500712 error(
713 "No response received for activate firmware for endpoint ID '{EID}'",
714 "EID", eid);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530715 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700716 return;
717 }
718
719 uint8_t completionCode = 0;
720 uint16_t estimatedTimeForActivation = 0;
721
722 auto rc = decode_activate_firmware_resp(
723 response, respMsgLen, &completionCode, &estimatedTimeForActivation);
724 if (rc)
725 {
726 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500727 error(
728 "Failed to decode activate firmware response for endpoint ID '{EID}', response code '{RC}'",
729 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700730 return;
731 }
732 if (completionCode)
733 {
734 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600735 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500736 "Failed to activate firmware response for endpoint ID '{EID}', completion code '{CC}'",
737 "EID", eid, "CC", completionCode);
P Arun Kumar Reddy155128f2025-04-15 16:11:48 +0530738 updateManager->updateDeviceCompletion(eid, false);
Tom Josephef90b0d2021-08-17 07:12:49 -0700739 return;
740 }
Tom Joseph4d8d5772021-08-17 07:35:05 -0700741
742 updateManager->updateDeviceCompletion(eid, true);
Tom Josephef90b0d2021-08-17 07:12:49 -0700743}
744
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530745void DeviceUpdater::sendCancelUpdateComponentRequest()
746{
747 pldmRequest.reset();
748 auto instanceId = updateManager->instanceIdDb.next(eid);
749 Request request(sizeof(pldm_msg_hdr));
750 auto requestMsg = new (request.data()) pldm_msg;
751
752 auto rc = encode_cancel_update_component_req(
753 instanceId, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES);
754 if (rc)
755 {
756 updateManager->instanceIdDb.free(eid, instanceId);
757 error(
758 "Failed to encode cancel update component request for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', response code '{RC}'",
759 "EID", eid, "COMPONENT_INDEX", componentIndex, "RC", rc);
760 return;
761 }
762
763 rc = updateManager->handler.registerRequest(
764 eid, instanceId, PLDM_FWUP, PLDM_CANCEL_UPDATE_COMPONENT,
765 std::move(request),
766 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
767 this->cancelUpdateComponent(eid, response, respMsgLen);
768 });
769 if (rc)
770 {
771 error(
772 "Failed to send cancel update component request for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', response code '{RC}'",
773 "EID", eid, "COMPONENT_INDEX", componentIndex, "RC", rc);
774 }
775}
776
777void DeviceUpdater::cancelUpdateComponent(
778 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
779{
780 // Check if response is valid
781 if (response == nullptr || !respMsgLen)
782 {
783 error(
784 "No response received for cancel update component for endpoint ID '{EID}'",
785 "EID", eid);
786 return;
787 }
788
789 uint8_t completionCode = 0;
790 auto rc = decode_cancel_update_component_resp(response, respMsgLen,
791 &completionCode);
792 if (rc)
793 {
794 error(
795 "Failed to decode cancel update component response for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', completion code '{CC}'",
796 "EID", eid, "COMPONENT_INDEX", componentIndex, "CC",
797 completionCode);
798 return;
799 }
800 if (completionCode)
801 {
802 error(
803 "Failed to cancel update component for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', completion code '{CC}'",
804 "EID", eid, "COMPONENT_INDEX", componentIndex, "CC",
805 completionCode);
806 return;
807 }
808
809 const auto& applicableComponents =
810 std::get<ApplicableComponents>(fwDeviceIDRecord);
811 // Check if this is the last component being cancelled
812 if (componentIndex == applicableComponents.size() - 1)
813 {
814 for (auto& compStatus : componentUpdateStatus)
815 {
816 if (compStatus.second)
817 {
818 // If at least one component update succeeded, proceed with
819 // activation
820 componentIndex = 0;
821 componentUpdateStatus.clear();
822 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
823 updateManager->event,
824 std::bind(&DeviceUpdater::sendActivateFirmwareRequest,
825 this));
826 return;
827 }
828 }
829 updateManager->updateDeviceCompletion(eid, false);
830 }
831 else
832 {
833 // Move to next component and update its status
834 componentIndex++;
835 componentUpdateStatus[componentIndex] = true;
836 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
837 updateManager->event,
838 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
839 componentIndex));
840 }
841 return;
842}
843
Tom Josephef90b0d2021-08-17 07:12:49 -0700844} // namespace fw_update
845
Patrick Williams6da4f912023-05-10 07:50:53 -0500846} // namespace pldm