blob: 20bca0c2955a6375f8d8825e2a00ac58a6924f43 [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
38 Request request(sizeof(pldm_msg_hdr) +
39 sizeof(struct pldm_request_update_req) +
40 compImgSetVerStrInfo.length);
41 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
42
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 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +093051 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -060052 error("encode_request_update_req failed, EID = {EID}, RC = {RC}", "EID",
53 unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -070054 // Handle error scenario
55 }
56
Tom Josephb7e083e2021-10-26 15:10:03 +053057 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -070058 eid, instanceId, PLDM_FWUP, PLDM_REQUEST_UPDATE, std::move(request),
59 std::move(std::bind_front(&DeviceUpdater::requestUpdate, this)));
60 if (rc)
61 {
Riya Dixit49cfb132023-03-02 04:26:53 -060062 error("Failed to send RequestUpdate request, EID = {EID}, RC = {RC}",
63 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -070064 // Handle error scenario
65 }
66}
67
68void DeviceUpdater::requestUpdate(mctp_eid_t eid, const pldm_msg* response,
69 size_t respMsgLen)
70{
71 if (response == nullptr || !respMsgLen)
72 {
73 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -060074 error("No response received for RequestUpdate, EID = {EID}", "EID",
75 unsigned(eid));
Tom Josephef90b0d2021-08-17 07:12:49 -070076 return;
77 }
78
79 uint8_t completionCode = 0;
80 uint16_t fdMetaDataLen = 0;
81 uint8_t fdWillSendPkgData = 0;
82
83 auto rc = decode_request_update_resp(response, respMsgLen, &completionCode,
84 &fdMetaDataLen, &fdWillSendPkgData);
85 if (rc)
86 {
Riya Dixit49cfb132023-03-02 04:26:53 -060087 error("Decoding RequestUpdate response failed, EID = {EID}, RC = {RC}",
88 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -070089 return;
90 }
91 if (completionCode)
92 {
Riya Dixit49cfb132023-03-02 04:26:53 -060093 error(
94 "RequestUpdate response failed with error completion code, EID = {EID}, CC = {CC}",
95 "EID", unsigned(eid), "CC", unsigned(completionCode));
Tom Josephef90b0d2021-08-17 07:12:49 -070096 return;
97 }
98
99 // Optional fields DeviceMetaData and GetPackageData not handled
100 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530101 updateManager->event,
102 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
103 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700104}
105
106void DeviceUpdater::sendPassCompTableRequest(size_t offset)
107{
108 pldmRequest.reset();
109
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930110 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700111 // TransferFlag
112 const auto& applicableComponents =
113 std::get<ApplicableComponents>(fwDeviceIDRecord);
114 uint8_t transferFlag = 0;
115 if (applicableComponents.size() == 1)
116 {
117 transferFlag = PLDM_START_AND_END;
118 }
119 else if (offset == 0)
120 {
121 transferFlag = PLDM_START;
122 }
123 else if (offset == applicableComponents.size() - 1)
124 {
125 transferFlag = PLDM_END;
126 }
127 else
128 {
129 transferFlag = PLDM_MIDDLE;
130 }
131 const auto& comp = compImageInfos[applicableComponents[offset]];
132 // ComponentClassification
133 CompClassification compClassification = std::get<static_cast<size_t>(
134 ComponentImageInfoPos::CompClassificationPos)>(comp);
135 // ComponentIdentifier
136 CompIdentifier compIdentifier =
137 std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
138 comp);
139 // ComponentClassificationIndex
140 CompClassificationIndex compClassificationIndex{};
141 auto compKey = std::make_pair(compClassification, compIdentifier);
142 if (compInfo.contains(compKey))
143 {
144 auto search = compInfo.find(compKey);
145 compClassificationIndex = search->second;
146 }
147 else
148 {
149 // Handle error scenario
150 }
151 // ComponentComparisonStamp
152 CompComparisonStamp compComparisonStamp = std::get<static_cast<size_t>(
153 ComponentImageInfoPos::CompComparisonStampPos)>(comp);
154 // ComponentVersionString
155 const auto& compVersion =
156 std::get<static_cast<size_t>(ComponentImageInfoPos::CompVersionPos)>(
157 comp);
158 variable_field compVerStrInfo{};
159 compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
160 compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
161
162 Request request(sizeof(pldm_msg_hdr) +
163 sizeof(struct pldm_pass_component_table_req) +
164 compVerStrInfo.length);
165 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
166 auto rc = encode_pass_component_table_req(
167 instanceId, transferFlag, compClassification, compIdentifier,
168 compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
169 compVerStrInfo.length, &compVerStrInfo, requestMsg,
170 sizeof(pldm_pass_component_table_req) + compVerStrInfo.length);
171 if (rc)
172 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930173 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600174 error("encode_pass_component_table_req failed, EID = {EID}, RC = {RC}",
175 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700176 // Handle error scenario
177 }
178
Tom Josephb7e083e2021-10-26 15:10:03 +0530179 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700180 eid, instanceId, PLDM_FWUP, PLDM_PASS_COMPONENT_TABLE,
181 std::move(request),
182 std::move(std::bind_front(&DeviceUpdater::passCompTable, this)));
183 if (rc)
184 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600185 error(
186 "Failed to send PassComponentTable request, EID = {EID}, RC = {RC}",
187 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700188 // Handle error scenario
189 }
190}
191
192void DeviceUpdater::passCompTable(mctp_eid_t eid, const pldm_msg* response,
193 size_t respMsgLen)
194{
195 if (response == nullptr || !respMsgLen)
196 {
197 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600198 error("No response received for PassComponentTable, EID = {EID}", "EID",
199 unsigned(eid));
Tom Josephef90b0d2021-08-17 07:12:49 -0700200 return;
201 }
202
203 uint8_t completionCode = 0;
204 uint8_t compResponse = 0;
205 uint8_t compResponseCode = 0;
206
Patrick Williams6da4f912023-05-10 07:50:53 -0500207 auto rc = decode_pass_component_table_resp(response, respMsgLen,
208 &completionCode, &compResponse,
209 &compResponseCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700210 if (rc)
211 {
212 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600213 error(
214 "Decoding PassComponentTable response failed, EID={EID}, RC = {RC}",
215 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700216 return;
217 }
218 if (completionCode)
219 {
220 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600221 error(
222 "PassComponentTable response failed with error completion code, EID = {EID}, CC = {CC}",
223 "EID", unsigned(eid), "CC", unsigned(completionCode));
Tom Josephef90b0d2021-08-17 07:12:49 -0700224 return;
225 }
226 // Handle ComponentResponseCode
227
228 const auto& applicableComponents =
229 std::get<ApplicableComponents>(fwDeviceIDRecord);
230 if (componentIndex == applicableComponents.size() - 1)
231 {
232 componentIndex = 0;
233 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530234 updateManager->event,
235 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
236 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700237 }
238 else
239 {
240 componentIndex++;
241 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530242 updateManager->event,
243 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
244 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700245 }
246}
247
248void DeviceUpdater::sendUpdateComponentRequest(size_t offset)
249{
250 pldmRequest.reset();
251
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930252 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700253 const auto& applicableComponents =
254 std::get<ApplicableComponents>(fwDeviceIDRecord);
255 const auto& comp = compImageInfos[applicableComponents[offset]];
256 // ComponentClassification
257 CompClassification compClassification = std::get<static_cast<size_t>(
258 ComponentImageInfoPos::CompClassificationPos)>(comp);
259 // ComponentIdentifier
260 CompIdentifier compIdentifier =
261 std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
262 comp);
263 // ComponentClassificationIndex
264 CompClassificationIndex compClassificationIndex{};
265 auto compKey = std::make_pair(compClassification, compIdentifier);
266 if (compInfo.contains(compKey))
267 {
268 auto search = compInfo.find(compKey);
269 compClassificationIndex = search->second;
270 }
271 else
272 {
273 // Handle error scenario
274 }
275
276 // UpdateOptionFlags
277 bitfield32_t updateOptionFlags;
278 updateOptionFlags.bits.bit0 = std::get<3>(comp)[0];
279 // ComponentVersion
280 const auto& compVersion = std::get<7>(comp);
281 variable_field compVerStrInfo{};
282 compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
283 compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
284
285 Request request(sizeof(pldm_msg_hdr) +
286 sizeof(struct pldm_update_component_req) +
287 compVerStrInfo.length);
288 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
289
290 auto rc = encode_update_component_req(
291 instanceId, compClassification, compIdentifier, compClassificationIndex,
292 std::get<static_cast<size_t>(
293 ComponentImageInfoPos::CompComparisonStampPos)>(comp),
294 std::get<static_cast<size_t>(ComponentImageInfoPos::CompSizePos)>(comp),
295 updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrInfo.length,
296 &compVerStrInfo, requestMsg,
297 sizeof(pldm_update_component_req) + compVerStrInfo.length);
298 if (rc)
299 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930300 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600301 error("encode_update_component_req failed, EID={EID}, RC = {RC}", "EID",
302 unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700303 // Handle error scenario
304 }
305
Tom Josephb7e083e2021-10-26 15:10:03 +0530306 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700307 eid, instanceId, PLDM_FWUP, PLDM_UPDATE_COMPONENT, std::move(request),
308 std::move(std::bind_front(&DeviceUpdater::updateComponent, this)));
309 if (rc)
310 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600311 error("Failed to send UpdateComponent request, EID={EID}, RC = {RC}",
312 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700313 // Handle error scenario
314 }
315}
316
317void DeviceUpdater::updateComponent(mctp_eid_t eid, const pldm_msg* response,
318 size_t respMsgLen)
319{
320 if (response == nullptr || !respMsgLen)
321 {
322 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600323 error("No response received for updateComponent, EID={EID}", "EID",
324 unsigned(eid));
Tom Josephef90b0d2021-08-17 07:12:49 -0700325 return;
326 }
327
328 uint8_t completionCode = 0;
329 uint8_t compCompatibilityResp = 0;
330 uint8_t compCompatibilityRespCode = 0;
331 bitfield32_t updateOptionFlagsEnabled{};
332 uint16_t timeBeforeReqFWData = 0;
333
334 auto rc = decode_update_component_resp(
335 response, respMsgLen, &completionCode, &compCompatibilityResp,
336 &compCompatibilityRespCode, &updateOptionFlagsEnabled,
337 &timeBeforeReqFWData);
338 if (rc)
339 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600340 error("Decoding UpdateComponent response failed, EID={EID}, RC = {RC}",
341 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700342 return;
343 }
344 if (completionCode)
345 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600346 error(
347 "UpdateComponent response failed with error completion code, EID = {EID}, CC = {CC}",
348 "EID", unsigned(eid), "CC", unsigned(completionCode));
Tom Josephef90b0d2021-08-17 07:12:49 -0700349 return;
350 }
351}
352
353Response DeviceUpdater::requestFwData(const pldm_msg* request,
354 size_t payloadLength)
355{
356 uint8_t completionCode = PLDM_SUCCESS;
357 uint32_t offset = 0;
358 uint32_t length = 0;
359 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
360 auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
361 auto rc = decode_request_firmware_data_req(request, payloadLength, &offset,
362 &length);
363 if (rc)
364 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600365 error(
366 "Decoding RequestFirmwareData request failed, EID={EID}, RC = {RC}",
367 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700368 rc = encode_request_firmware_data_resp(
369 request->hdr.instance_id, PLDM_ERROR_INVALID_DATA, responseMsg,
370 sizeof(completionCode));
371 if (rc)
372 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600373 error(
374 "Encoding RequestFirmwareData response failed, EID = {EID}, RC = {RC}",
375 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700376 }
377 return response;
378 }
379
380 const auto& applicableComponents =
381 std::get<ApplicableComponents>(fwDeviceIDRecord);
382 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
383 auto compOffset = std::get<5>(comp);
384 auto compSize = std::get<6>(comp);
Riya Dixit49cfb132023-03-02 04:26:53 -0600385 error("offset = {OFFSET}, length = {LEN}", "OFFSET", unsigned(offset),
386 "LEN", unsigned(length));
Tom Josephef90b0d2021-08-17 07:12:49 -0700387 if (length < PLDM_FWUP_BASELINE_TRANSFER_SIZE || length > maxTransferSize)
388 {
389 rc = encode_request_firmware_data_resp(
390 request->hdr.instance_id, PLDM_FWUP_INVALID_TRANSFER_LENGTH,
391 responseMsg, sizeof(completionCode));
392 if (rc)
393 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600394 error(
395 "Encoding RequestFirmwareData response failed, EID={EID}, RC = {RC}",
396 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700397 }
398 return response;
399 }
400
401 if (offset + length > compSize + PLDM_FWUP_BASELINE_TRANSFER_SIZE)
402 {
403 rc = encode_request_firmware_data_resp(
404 request->hdr.instance_id, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg,
405 sizeof(completionCode));
406 if (rc)
407 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600408 error(
409 "Encoding RequestFirmwareData response failed, EID={EID}, RC = {RC}",
410 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700411 }
412 return response;
413 }
414
415 size_t padBytes = 0;
416 if (offset + length > compSize)
417 {
418 padBytes = offset + length - compSize;
419 }
420
421 response.resize(sizeof(pldm_msg_hdr) + sizeof(completionCode) + length);
422 responseMsg = reinterpret_cast<pldm_msg*>(response.data());
423 package.seekg(compOffset + offset);
424 package.read(reinterpret_cast<char*>(response.data() +
425 sizeof(pldm_msg_hdr) +
426 sizeof(completionCode)),
427 length - padBytes);
428 rc = encode_request_firmware_data_resp(request->hdr.instance_id,
429 completionCode, responseMsg,
430 sizeof(completionCode));
431 if (rc)
432 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600433 error(
434 "Encoding RequestFirmwareData response failed, EID={EID}, RC = {RC}",
435 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700436 return response;
437 }
438
439 return response;
440}
441
442Response DeviceUpdater::transferComplete(const pldm_msg* request,
443 size_t payloadLength)
444{
445 uint8_t completionCode = PLDM_SUCCESS;
446 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
447 auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
448
449 uint8_t transferResult = 0;
Patrick Williams6da4f912023-05-10 07:50:53 -0500450 auto rc = decode_transfer_complete_req(request, payloadLength,
451 &transferResult);
Tom Josephef90b0d2021-08-17 07:12:49 -0700452 if (rc)
453 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600454 error("Decoding TransferComplete request failed, EID={EID}, RC = {RC}",
455 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700456 rc = encode_transfer_complete_resp(request->hdr.instance_id,
457 PLDM_ERROR_INVALID_DATA, responseMsg,
458 sizeof(completionCode));
459 if (rc)
460 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600461 error(
462 "Encoding TransferComplete response failed, EID={EID}, RC = {RC}",
463 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700464 }
465 return response;
466 }
467
468 const auto& applicableComponents =
469 std::get<ApplicableComponents>(fwDeviceIDRecord);
470 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
471 const auto& compVersion = std::get<7>(comp);
472
473 if (transferResult == PLDM_FWUP_TRANSFER_SUCCESS)
474 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600475 info(
476 "Component Transfer complete, EID = {EID}, COMPONENT_VERSION = {COMP_VERS}",
477 "EID", unsigned(eid), "COMP_VERS", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700478 }
479 else
480 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600481 error(
482 "Transfer of the component failed, EID={EID}, COMPONENT_VERSION = {COMP_VERS}, TRANSFER_RESULT = {TRANS_RES}",
483 "EID", unsigned(eid), "COMP_VERS", compVersion, "TRANS_RES",
484 unsigned(transferResult));
Tom Josephef90b0d2021-08-17 07:12:49 -0700485 }
486
487 rc = encode_transfer_complete_resp(request->hdr.instance_id, completionCode,
488 responseMsg, sizeof(completionCode));
489 if (rc)
490 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600491 error("Encoding TransferComplete response failed, EID={EID}, RC = {RC}",
492 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700493 return response;
494 }
495
496 return response;
497}
498
499Response DeviceUpdater::verifyComplete(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);
504 auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
505
506 uint8_t verifyResult = 0;
507 auto rc = decode_verify_complete_req(request, payloadLength, &verifyResult);
508 if (rc)
509 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600510 error("Decoding VerifyComplete request failed, EID = {EID}, RC = {RC}",
511 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700512 rc = encode_verify_complete_resp(request->hdr.instance_id,
513 PLDM_ERROR_INVALID_DATA, responseMsg,
514 sizeof(completionCode));
515 if (rc)
516 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600517 error(
518 "Encoding VerifyComplete response failed, EID={EID}, RC = {RC}",
519 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700520 }
521 return response;
522 }
523
524 const auto& applicableComponents =
525 std::get<ApplicableComponents>(fwDeviceIDRecord);
526 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
527 const auto& compVersion = std::get<7>(comp);
528
529 if (verifyResult == PLDM_FWUP_VERIFY_SUCCESS)
530 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600531 info(
532 "Component verification complete, EID={EID}, COMPONENT_VERSION={COMP_VERS}",
533 "EID", unsigned(eid), "COMP_VERS", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700534 }
535 else
536 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600537 error(
538 "Component verification failed, EID={EID}, COMPONENT_VERSION={COMP_VERS}, VERIFY_RESULT={VERIFY_RES}",
539 "EID", unsigned(eid), "COMP_VERS", compVersion, "VERIFY_RES",
540 unsigned(verifyResult));
Tom Josephef90b0d2021-08-17 07:12:49 -0700541 }
542
543 rc = encode_verify_complete_resp(request->hdr.instance_id, completionCode,
544 responseMsg, sizeof(completionCode));
545 if (rc)
546 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600547 error("Encoding VerifyComplete response failed, EID={EID}, RC = {RC}",
548 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700549 return response;
550 }
551
552 return response;
553}
554
555Response DeviceUpdater::applyComplete(const pldm_msg* request,
556 size_t payloadLength)
557{
558 uint8_t completionCode = PLDM_SUCCESS;
559 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
560 auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
561
562 uint8_t applyResult = 0;
563 bitfield16_t compActivationModification{};
564 auto rc = decode_apply_complete_req(request, payloadLength, &applyResult,
565 &compActivationModification);
566 if (rc)
567 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600568 error("Decoding ApplyComplete request failed, EID={EID}, RC = {RC}",
569 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700570 rc = encode_apply_complete_resp(request->hdr.instance_id,
571 PLDM_ERROR_INVALID_DATA, responseMsg,
572 sizeof(completionCode));
573 if (rc)
574 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600575 error(
576 "Encoding ApplyComplete response failed, EID={EID}, RC = {RC}",
577 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700578 }
579 return response;
580 }
581
582 const auto& applicableComponents =
583 std::get<ApplicableComponents>(fwDeviceIDRecord);
584 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
585 const auto& compVersion = std::get<7>(comp);
586
587 if (applyResult == PLDM_FWUP_APPLY_SUCCESS ||
588 applyResult == PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD)
589 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600590 info(
591 "Component apply complete, EID = {EID}, COMPONENT_VERSION = {COMP_VERS}",
592 "EID", unsigned(eid), "COMP_VERS", compVersion);
Tom Joseph4d8d5772021-08-17 07:35:05 -0700593 updateManager->updateActivationProgress();
Tom Josephef90b0d2021-08-17 07:12:49 -0700594 }
595 else
596 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600597 error(
598 "Component apply failed, EID = {EID}, COMPONENT_VERSION = {COMP_VERS}, APPLY_RESULT = {APPLY_RES}",
599 "EID", unsigned(eid), "COMP_VERS", compVersion, "APPLY_RES",
600 unsigned(applyResult));
Tom Josephef90b0d2021-08-17 07:12:49 -0700601 }
602
603 rc = encode_apply_complete_resp(request->hdr.instance_id, completionCode,
604 responseMsg, sizeof(completionCode));
605 if (rc)
606 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600607 error("Encoding ApplyComplete response failed, EID={EID}, RC = {RC}",
608 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700609 return response;
610 }
611
612 if (componentIndex == applicableComponents.size() - 1)
613 {
614 componentIndex = 0;
615 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530616 updateManager->event,
Tom Josephef90b0d2021-08-17 07:12:49 -0700617 std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this));
618 }
619 else
620 {
621 componentIndex++;
622 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530623 updateManager->event,
624 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
625 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700626 }
627
628 return response;
629}
630
631void DeviceUpdater::sendActivateFirmwareRequest()
632{
633 pldmRequest.reset();
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930634 auto instanceId = updateManager->instanceIdDb.next(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700635 Request request(sizeof(pldm_msg_hdr) +
636 sizeof(struct pldm_activate_firmware_req));
637 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
638
639 auto rc = encode_activate_firmware_req(
640 instanceId, PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
641 sizeof(pldm_activate_firmware_req));
642 if (rc)
643 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930644 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600645 error("encode_activate_firmware_req failed, EID={EID}, RC = {RC}",
646 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700647 }
648
Tom Josephb7e083e2021-10-26 15:10:03 +0530649 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700650 eid, instanceId, PLDM_FWUP, PLDM_ACTIVATE_FIRMWARE, std::move(request),
651 std::move(std::bind_front(&DeviceUpdater::activateFirmware, this)));
652 if (rc)
653 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600654 error("Failed to send ActivateFirmware request, EID={EID}, RC = {RC}",
655 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700656 }
657}
658
659void DeviceUpdater::activateFirmware(mctp_eid_t eid, const pldm_msg* response,
660 size_t respMsgLen)
661{
662 if (response == nullptr || !respMsgLen)
663 {
664 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600665 error("No response received for ActivateFirmware, EID={EID}", "EID",
666 unsigned(eid));
Tom Josephef90b0d2021-08-17 07:12:49 -0700667 return;
668 }
669
670 uint8_t completionCode = 0;
671 uint16_t estimatedTimeForActivation = 0;
672
673 auto rc = decode_activate_firmware_resp(
674 response, respMsgLen, &completionCode, &estimatedTimeForActivation);
675 if (rc)
676 {
677 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600678 error("Decoding ActivateFirmware response failed, EID={EID}, RC = {RC}",
679 "EID", unsigned(eid), "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700680 return;
681 }
682 if (completionCode)
683 {
684 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600685 error(
686 "ActivateFirmware response failed with error completion code, EID = {EID}, CC = {CC}",
687 "EID", unsigned(eid), "CC", unsigned(completionCode));
Tom Josephef90b0d2021-08-17 07:12:49 -0700688 return;
689 }
Tom Joseph4d8d5772021-08-17 07:35:05 -0700690
691 updateManager->updateDeviceCompletion(eid, true);
Tom Josephef90b0d2021-08-17 07:12:49 -0700692}
693
694} // namespace fw_update
695
Patrick Williams6da4f912023-05-10 07:50:53 -0500696} // namespace pldm