blob: a879b23eb20f05990730ae3710a666b7660fafe9 [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);
Tom Josephef90b0d2021-08-17 07:12:49 -070080 return;
81 }
82
83 uint8_t completionCode = 0;
84 uint16_t fdMetaDataLen = 0;
85 uint8_t fdWillSendPkgData = 0;
86
87 auto rc = decode_request_update_resp(response, respMsgLen, &completionCode,
88 &fdMetaDataLen, &fdWillSendPkgData);
89 if (rc)
90 {
Riya Dixit76f2c602024-03-28 07:34:12 -050091 error(
92 "Failed to decode request update response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050093 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -070094 return;
95 }
96 if (completionCode)
97 {
Riya Dixit49cfb132023-03-02 04:26:53 -060098 error(
Riya Dixit76f2c602024-03-28 07:34:12 -050099 "Failure in request update response for endpoint ID '{EID}', completion code '{CC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500100 "EID", eid, "CC", completionCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700101 return;
102 }
103
104 // Optional fields DeviceMetaData and GetPackageData not handled
105 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530106 updateManager->event,
107 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
108 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700109}
110
111void DeviceUpdater::sendPassCompTableRequest(size_t offset)
112{
113 pldmRequest.reset();
114
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930115 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700116 // TransferFlag
117 const auto& applicableComponents =
118 std::get<ApplicableComponents>(fwDeviceIDRecord);
119 uint8_t transferFlag = 0;
120 if (applicableComponents.size() == 1)
121 {
122 transferFlag = PLDM_START_AND_END;
123 }
124 else if (offset == 0)
125 {
126 transferFlag = PLDM_START;
127 }
128 else if (offset == applicableComponents.size() - 1)
129 {
130 transferFlag = PLDM_END;
131 }
132 else
133 {
134 transferFlag = PLDM_MIDDLE;
135 }
136 const auto& comp = compImageInfos[applicableComponents[offset]];
137 // ComponentClassification
138 CompClassification compClassification = std::get<static_cast<size_t>(
139 ComponentImageInfoPos::CompClassificationPos)>(comp);
140 // ComponentIdentifier
141 CompIdentifier compIdentifier =
142 std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
143 comp);
144 // ComponentClassificationIndex
145 CompClassificationIndex compClassificationIndex{};
146 auto compKey = std::make_pair(compClassification, compIdentifier);
147 if (compInfo.contains(compKey))
148 {
149 auto search = compInfo.find(compKey);
150 compClassificationIndex = search->second;
151 }
152 else
153 {
154 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500155 error(
156 "Failed to find component classification '{CLASSIFICATION}' and identifier '{IDENTIFIER}'",
157 "CLASSIFICATION", compClassification, "IDENTIFIER", compIdentifier);
Tom Josephef90b0d2021-08-17 07:12:49 -0700158 }
159 // ComponentComparisonStamp
160 CompComparisonStamp compComparisonStamp = std::get<static_cast<size_t>(
161 ComponentImageInfoPos::CompComparisonStampPos)>(comp);
162 // ComponentVersionString
163 const auto& compVersion =
164 std::get<static_cast<size_t>(ComponentImageInfoPos::CompVersionPos)>(
165 comp);
166 variable_field compVerStrInfo{};
167 compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
168 compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
169
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400170 Request request(
171 sizeof(pldm_msg_hdr) + sizeof(struct pldm_pass_component_table_req) +
172 compVerStrInfo.length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530173 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700174 auto rc = encode_pass_component_table_req(
175 instanceId, transferFlag, compClassification, compIdentifier,
176 compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
177 compVerStrInfo.length, &compVerStrInfo, requestMsg,
178 sizeof(pldm_pass_component_table_req) + compVerStrInfo.length);
179 if (rc)
180 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700181 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500182 updateManager->instanceIdDb.free(eid, instanceId);
183 error(
184 "Failed to encode pass component table req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500185 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700186 }
187
Tom Josephb7e083e2021-10-26 15:10:03 +0530188 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700189 eid, instanceId, PLDM_FWUP, PLDM_PASS_COMPONENT_TABLE,
190 std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800191 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
192 this->passCompTable(eid, response, respMsgLen);
193 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700194 if (rc)
195 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700196 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500197 error(
198 "Failed to send pass component table request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500199 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700200 }
201}
202
203void DeviceUpdater::passCompTable(mctp_eid_t eid, const pldm_msg* response,
204 size_t respMsgLen)
205{
206 if (response == nullptr || !respMsgLen)
207 {
208 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500209 error(
210 "No response received for pass component table for endpoint ID '{EID}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500211 "EID", eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700212 return;
213 }
214
215 uint8_t completionCode = 0;
216 uint8_t compResponse = 0;
217 uint8_t compResponseCode = 0;
218
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400219 auto rc =
220 decode_pass_component_table_resp(response, respMsgLen, &completionCode,
221 &compResponse, &compResponseCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700222 if (rc)
223 {
224 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600225 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500226 "Failed to decode pass component table response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500227 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700228 return;
229 }
230 if (completionCode)
231 {
232 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600233 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500234 "Failed to pass component table response for endpoint ID '{EID}', completion code '{CC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500235 "EID", eid, "CC", completionCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700236 return;
237 }
238 // Handle ComponentResponseCode
239
240 const auto& applicableComponents =
241 std::get<ApplicableComponents>(fwDeviceIDRecord);
242 if (componentIndex == applicableComponents.size() - 1)
243 {
244 componentIndex = 0;
245 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530246 updateManager->event,
247 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
248 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700249 }
250 else
251 {
252 componentIndex++;
253 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530254 updateManager->event,
255 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
256 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700257 }
258}
259
260void DeviceUpdater::sendUpdateComponentRequest(size_t offset)
261{
262 pldmRequest.reset();
263
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930264 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700265 const auto& applicableComponents =
266 std::get<ApplicableComponents>(fwDeviceIDRecord);
267 const auto& comp = compImageInfos[applicableComponents[offset]];
268 // ComponentClassification
269 CompClassification compClassification = std::get<static_cast<size_t>(
270 ComponentImageInfoPos::CompClassificationPos)>(comp);
271 // ComponentIdentifier
272 CompIdentifier compIdentifier =
273 std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
274 comp);
275 // ComponentClassificationIndex
276 CompClassificationIndex compClassificationIndex{};
277 auto compKey = std::make_pair(compClassification, compIdentifier);
278 if (compInfo.contains(compKey))
279 {
280 auto search = compInfo.find(compKey);
281 compClassificationIndex = search->second;
282 }
283 else
284 {
285 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500286 error(
287 "Failed to find component classification '{CLASSIFICATION}' and identifier '{IDENTIFIER}'",
288 "CLASSIFICATION", compClassification, "IDENTIFIER", compIdentifier);
Tom Josephef90b0d2021-08-17 07:12:49 -0700289 }
290
291 // UpdateOptionFlags
292 bitfield32_t updateOptionFlags;
293 updateOptionFlags.bits.bit0 = std::get<3>(comp)[0];
294 // ComponentVersion
295 const auto& compVersion = std::get<7>(comp);
296 variable_field compVerStrInfo{};
297 compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
298 compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
299
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400300 Request request(
301 sizeof(pldm_msg_hdr) + sizeof(struct pldm_update_component_req) +
302 compVerStrInfo.length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530303 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700304
305 auto rc = encode_update_component_req(
306 instanceId, compClassification, compIdentifier, compClassificationIndex,
307 std::get<static_cast<size_t>(
308 ComponentImageInfoPos::CompComparisonStampPos)>(comp),
309 std::get<static_cast<size_t>(ComponentImageInfoPos::CompSizePos)>(comp),
310 updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrInfo.length,
311 &compVerStrInfo, requestMsg,
312 sizeof(pldm_update_component_req) + compVerStrInfo.length);
313 if (rc)
314 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700315 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500316 updateManager->instanceIdDb.free(eid, instanceId);
317 error(
318 "Failed to encode update component req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500319 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700320 }
321
Tom Josephb7e083e2021-10-26 15:10:03 +0530322 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700323 eid, instanceId, PLDM_FWUP, PLDM_UPDATE_COMPONENT, std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800324 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
325 this->updateComponent(eid, response, respMsgLen);
326 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700327 if (rc)
328 {
Tom Josephef90b0d2021-08-17 07:12:49 -0700329 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500330 error(
331 "Failed to send update request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500332 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700333 }
334}
335
336void DeviceUpdater::updateComponent(mctp_eid_t eid, const pldm_msg* response,
337 size_t respMsgLen)
338{
339 if (response == nullptr || !respMsgLen)
340 {
341 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500342 error(
343 "No response received for update component with endpoint ID {EID}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500344 "EID", eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700345 return;
346 }
347
348 uint8_t completionCode = 0;
349 uint8_t compCompatibilityResp = 0;
350 uint8_t compCompatibilityRespCode = 0;
351 bitfield32_t updateOptionFlagsEnabled{};
352 uint16_t timeBeforeReqFWData = 0;
353
354 auto rc = decode_update_component_resp(
355 response, respMsgLen, &completionCode, &compCompatibilityResp,
356 &compCompatibilityRespCode, &updateOptionFlagsEnabled,
357 &timeBeforeReqFWData);
358 if (rc)
359 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500360 error(
361 "Failed to decode update request response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500362 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700363 return;
364 }
365 if (completionCode)
366 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600367 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500368 "Failed to update request response for endpoint ID '{EID}', completion code '{CC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500369 "EID", eid, "CC", completionCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700370 return;
371 }
372}
373
374Response DeviceUpdater::requestFwData(const pldm_msg* request,
375 size_t payloadLength)
376{
377 uint8_t completionCode = PLDM_SUCCESS;
378 uint32_t offset = 0;
379 uint32_t length = 0;
380 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530381 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700382 auto rc = decode_request_firmware_data_req(request, payloadLength, &offset,
383 &length);
384 if (rc)
385 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600386 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500387 "Failed to decode request firmware date request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500388 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700389 rc = encode_request_firmware_data_resp(
390 request->hdr.instance_id, PLDM_ERROR_INVALID_DATA, responseMsg,
391 sizeof(completionCode));
392 if (rc)
393 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600394 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500395 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500396 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700397 }
398 return response;
399 }
400
401 const auto& applicableComponents =
402 std::get<ApplicableComponents>(fwDeviceIDRecord);
403 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
404 auto compOffset = std::get<5>(comp);
405 auto compSize = std::get<6>(comp);
Eric Yang91197522024-12-06 15:44:54 +0800406 debug("Decoded fw request data at offset '{OFFSET}' and length '{LENGTH}' ",
407 "OFFSET", offset, "LENGTH", length);
Tom Josephef90b0d2021-08-17 07:12:49 -0700408 if (length < PLDM_FWUP_BASELINE_TRANSFER_SIZE || length > maxTransferSize)
409 {
410 rc = encode_request_firmware_data_resp(
411 request->hdr.instance_id, PLDM_FWUP_INVALID_TRANSFER_LENGTH,
412 responseMsg, sizeof(completionCode));
413 if (rc)
414 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600415 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500416 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500417 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700418 }
419 return response;
420 }
421
422 if (offset + length > compSize + PLDM_FWUP_BASELINE_TRANSFER_SIZE)
423 {
424 rc = encode_request_firmware_data_resp(
425 request->hdr.instance_id, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg,
426 sizeof(completionCode));
427 if (rc)
428 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600429 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500430 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500431 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700432 }
433 return response;
434 }
435
436 size_t padBytes = 0;
437 if (offset + length > compSize)
438 {
439 padBytes = offset + length - compSize;
440 }
441
442 response.resize(sizeof(pldm_msg_hdr) + sizeof(completionCode) + length);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530443 responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700444 package.seekg(compOffset + offset);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400445 package.read(
446 reinterpret_cast<char*>(
447 response.data() + sizeof(pldm_msg_hdr) + sizeof(completionCode)),
448 length - padBytes);
449 rc = encode_request_firmware_data_resp(
450 request->hdr.instance_id, completionCode, responseMsg,
451 sizeof(completionCode));
Tom Josephef90b0d2021-08-17 07:12:49 -0700452 if (rc)
453 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600454 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500455 "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500456 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700457 return response;
458 }
459
460 return response;
461}
462
463Response DeviceUpdater::transferComplete(const pldm_msg* request,
464 size_t payloadLength)
465{
466 uint8_t completionCode = PLDM_SUCCESS;
467 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530468 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700469
470 uint8_t transferResult = 0;
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400471 auto rc =
472 decode_transfer_complete_req(request, payloadLength, &transferResult);
Tom Josephef90b0d2021-08-17 07:12:49 -0700473 if (rc)
474 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500475 error(
476 "Failed to decode TransferComplete request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500477 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700478 rc = encode_transfer_complete_resp(request->hdr.instance_id,
479 PLDM_ERROR_INVALID_DATA, responseMsg,
480 sizeof(completionCode));
481 if (rc)
482 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600483 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500484 "Failed to encode TransferComplete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500485 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700486 }
487 return response;
488 }
489
490 const auto& applicableComponents =
491 std::get<ApplicableComponents>(fwDeviceIDRecord);
492 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
493 const auto& compVersion = std::get<7>(comp);
494
495 if (transferResult == PLDM_FWUP_TRANSFER_SUCCESS)
496 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600497 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500498 "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' transfer complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500499 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700500 }
501 else
502 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600503 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500504 "Failure in transfer of the component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - {RESULT}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500505 "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT",
506 transferResult);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530507 componentUpdateStatus[componentIndex] = false;
508 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700509 }
510
511 rc = encode_transfer_complete_resp(request->hdr.instance_id, completionCode,
512 responseMsg, sizeof(completionCode));
513 if (rc)
514 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500515 error(
516 "Failed to encode transfer complete response of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500517 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700518 return response;
519 }
520
521 return response;
522}
523
524Response DeviceUpdater::verifyComplete(const pldm_msg* request,
525 size_t payloadLength)
526{
527 uint8_t completionCode = PLDM_SUCCESS;
528 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530529 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700530
531 uint8_t verifyResult = 0;
532 auto rc = decode_verify_complete_req(request, payloadLength, &verifyResult);
533 if (rc)
534 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500535 error(
536 "Failed to decode verify complete request of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500537 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700538 rc = encode_verify_complete_resp(request->hdr.instance_id,
539 PLDM_ERROR_INVALID_DATA, responseMsg,
540 sizeof(completionCode));
541 if (rc)
542 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600543 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500544 "Failed to encode verify complete response of endpoint ID '{EID}', response code '{RC}'.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500545 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700546 }
547 return response;
548 }
549
550 const auto& applicableComponents =
551 std::get<ApplicableComponents>(fwDeviceIDRecord);
552 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
553 const auto& compVersion = std::get<7>(comp);
554
555 if (verifyResult == PLDM_FWUP_VERIFY_SUCCESS)
556 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600557 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500558 "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' verification complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500559 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700560 }
561 else
562 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600563 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500564 "Failed to verify component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - '{RESULT}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500565 "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT",
566 verifyResult);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530567 componentUpdateStatus[componentIndex] = false;
568 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700569 }
570
571 rc = encode_verify_complete_resp(request->hdr.instance_id, completionCode,
572 responseMsg, sizeof(completionCode));
573 if (rc)
574 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500575 error(
576 "Failed to encode verify complete response for endpoint ID '{EID}', response code - {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500577 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700578 return response;
579 }
580
581 return response;
582}
583
584Response DeviceUpdater::applyComplete(const pldm_msg* request,
585 size_t payloadLength)
586{
587 uint8_t completionCode = PLDM_SUCCESS;
588 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530589 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700590
591 uint8_t applyResult = 0;
592 bitfield16_t compActivationModification{};
593 auto rc = decode_apply_complete_req(request, payloadLength, &applyResult,
594 &compActivationModification);
595 if (rc)
596 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500597 error(
598 "Failed to decode apply complete request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500599 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700600 rc = encode_apply_complete_resp(request->hdr.instance_id,
601 PLDM_ERROR_INVALID_DATA, responseMsg,
602 sizeof(completionCode));
603 if (rc)
604 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600605 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500606 "Failed to encode apply complete response 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 }
609 return response;
610 }
611
612 const auto& applicableComponents =
613 std::get<ApplicableComponents>(fwDeviceIDRecord);
614 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
615 const auto& compVersion = std::get<7>(comp);
616
617 if (applyResult == PLDM_FWUP_APPLY_SUCCESS ||
618 applyResult == PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD)
619 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600620 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500621 "Component endpoint ID '{EID}' with '{COMPONENT_VERSION}' apply complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500622 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Joseph4d8d5772021-08-17 07:35:05 -0700623 updateManager->updateActivationProgress();
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530624 if (componentIndex == applicableComponents.size() - 1)
625 {
626 componentIndex = 0;
627 componentUpdateStatus.clear();
628 componentUpdateStatus[componentIndex] = true;
629 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
630 updateManager->event,
631 std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this));
632 }
633 else
634 {
635 componentIndex++;
636 componentUpdateStatus[componentIndex] = true;
637 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
638 updateManager->event,
639 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
640 componentIndex));
641 }
Tom Josephef90b0d2021-08-17 07:12:49 -0700642 }
643 else
644 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600645 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500646 "Failed to apply component endpoint ID '{EID}' and version '{COMPONENT_VERSION}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500647 "EID", eid, "COMPONENT_VERSION", compVersion, "ERROR", applyResult);
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530648 componentUpdateStatus[componentIndex] = false;
649 sendCancelUpdateComponentRequest();
Tom Josephef90b0d2021-08-17 07:12:49 -0700650 }
651
652 rc = encode_apply_complete_resp(request->hdr.instance_id, completionCode,
653 responseMsg, sizeof(completionCode));
654 if (rc)
655 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500656 error(
657 "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500658 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700659 return response;
660 }
661
Tom Josephef90b0d2021-08-17 07:12:49 -0700662 return response;
663}
664
665void DeviceUpdater::sendActivateFirmwareRequest()
666{
667 pldmRequest.reset();
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930668 auto instanceId = updateManager->instanceIdDb.next(eid);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400669 Request request(
670 sizeof(pldm_msg_hdr) + sizeof(struct pldm_activate_firmware_req));
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530671 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700672
673 auto rc = encode_activate_firmware_req(
674 instanceId, PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
675 sizeof(pldm_activate_firmware_req));
676 if (rc)
677 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930678 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit76f2c602024-03-28 07:34:12 -0500679 error(
680 "Failed to encode activate firmware req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500681 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700682 }
683
Tom Josephb7e083e2021-10-26 15:10:03 +0530684 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700685 eid, instanceId, PLDM_FWUP, PLDM_ACTIVATE_FIRMWARE, std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800686 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
687 this->activateFirmware(eid, response, respMsgLen);
688 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700689 if (rc)
690 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500691 error(
692 "Failed to send activate firmware request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500693 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700694 }
695}
696
697void DeviceUpdater::activateFirmware(mctp_eid_t eid, const pldm_msg* response,
698 size_t respMsgLen)
699{
700 if (response == nullptr || !respMsgLen)
701 {
702 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500703 error(
704 "No response received for activate firmware for endpoint ID '{EID}'",
705 "EID", eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700706 return;
707 }
708
709 uint8_t completionCode = 0;
710 uint16_t estimatedTimeForActivation = 0;
711
712 auto rc = decode_activate_firmware_resp(
713 response, respMsgLen, &completionCode, &estimatedTimeForActivation);
714 if (rc)
715 {
716 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500717 error(
718 "Failed to decode activate firmware response for endpoint ID '{EID}', response code '{RC}'",
719 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700720 return;
721 }
722 if (completionCode)
723 {
724 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600725 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500726 "Failed to activate firmware response for endpoint ID '{EID}', completion code '{CC}'",
727 "EID", eid, "CC", completionCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700728 return;
729 }
Tom Joseph4d8d5772021-08-17 07:35:05 -0700730
731 updateManager->updateDeviceCompletion(eid, true);
Tom Josephef90b0d2021-08-17 07:12:49 -0700732}
733
P Arun Kumar Reddyd1c955b2025-04-15 16:06:06 +0530734void DeviceUpdater::sendCancelUpdateComponentRequest()
735{
736 pldmRequest.reset();
737 auto instanceId = updateManager->instanceIdDb.next(eid);
738 Request request(sizeof(pldm_msg_hdr));
739 auto requestMsg = new (request.data()) pldm_msg;
740
741 auto rc = encode_cancel_update_component_req(
742 instanceId, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES);
743 if (rc)
744 {
745 updateManager->instanceIdDb.free(eid, instanceId);
746 error(
747 "Failed to encode cancel update component request for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', response code '{RC}'",
748 "EID", eid, "COMPONENT_INDEX", componentIndex, "RC", rc);
749 return;
750 }
751
752 rc = updateManager->handler.registerRequest(
753 eid, instanceId, PLDM_FWUP, PLDM_CANCEL_UPDATE_COMPONENT,
754 std::move(request),
755 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
756 this->cancelUpdateComponent(eid, response, respMsgLen);
757 });
758 if (rc)
759 {
760 error(
761 "Failed to send cancel update component request for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', response code '{RC}'",
762 "EID", eid, "COMPONENT_INDEX", componentIndex, "RC", rc);
763 }
764}
765
766void DeviceUpdater::cancelUpdateComponent(
767 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
768{
769 // Check if response is valid
770 if (response == nullptr || !respMsgLen)
771 {
772 error(
773 "No response received for cancel update component for endpoint ID '{EID}'",
774 "EID", eid);
775 return;
776 }
777
778 uint8_t completionCode = 0;
779 auto rc = decode_cancel_update_component_resp(response, respMsgLen,
780 &completionCode);
781 if (rc)
782 {
783 error(
784 "Failed to decode cancel update component response for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', completion code '{CC}'",
785 "EID", eid, "COMPONENT_INDEX", componentIndex, "CC",
786 completionCode);
787 return;
788 }
789 if (completionCode)
790 {
791 error(
792 "Failed to cancel update component for endpoint ID '{EID}', component index '{COMPONENT_INDEX}', completion code '{CC}'",
793 "EID", eid, "COMPONENT_INDEX", componentIndex, "CC",
794 completionCode);
795 return;
796 }
797
798 const auto& applicableComponents =
799 std::get<ApplicableComponents>(fwDeviceIDRecord);
800 // Check if this is the last component being cancelled
801 if (componentIndex == applicableComponents.size() - 1)
802 {
803 for (auto& compStatus : componentUpdateStatus)
804 {
805 if (compStatus.second)
806 {
807 // If at least one component update succeeded, proceed with
808 // activation
809 componentIndex = 0;
810 componentUpdateStatus.clear();
811 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
812 updateManager->event,
813 std::bind(&DeviceUpdater::sendActivateFirmwareRequest,
814 this));
815 return;
816 }
817 }
818 updateManager->updateDeviceCompletion(eid, false);
819 }
820 else
821 {
822 // Move to next component and update its status
823 componentIndex++;
824 componentUpdateStatus[componentIndex] = true;
825 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
826 updateManager->event,
827 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
828 componentIndex));
829 }
830 return;
831}
832
Tom Josephef90b0d2021-08-17 07:12:49 -0700833} // namespace fw_update
834
Patrick Williams6da4f912023-05-10 07:50:53 -0500835} // namespace pldm