blob: 77412b97f4305e5bef66dcf63d2d1c9651eca7d8 [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);
Tom Josephef90b0d2021-08-17 07:12:49 -0700507 }
508
509 rc = encode_transfer_complete_resp(request->hdr.instance_id, completionCode,
510 responseMsg, sizeof(completionCode));
511 if (rc)
512 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500513 error(
514 "Failed to encode transfer complete response of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500515 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700516 return response;
517 }
518
519 return response;
520}
521
522Response DeviceUpdater::verifyComplete(const pldm_msg* request,
523 size_t payloadLength)
524{
525 uint8_t completionCode = PLDM_SUCCESS;
526 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530527 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700528
529 uint8_t verifyResult = 0;
530 auto rc = decode_verify_complete_req(request, payloadLength, &verifyResult);
531 if (rc)
532 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500533 error(
534 "Failed to decode verify complete request of endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500535 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700536 rc = encode_verify_complete_resp(request->hdr.instance_id,
537 PLDM_ERROR_INVALID_DATA, responseMsg,
538 sizeof(completionCode));
539 if (rc)
540 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600541 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500542 "Failed to encode verify complete response of endpoint ID '{EID}', response code '{RC}'.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500543 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700544 }
545 return response;
546 }
547
548 const auto& applicableComponents =
549 std::get<ApplicableComponents>(fwDeviceIDRecord);
550 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
551 const auto& compVersion = std::get<7>(comp);
552
553 if (verifyResult == PLDM_FWUP_VERIFY_SUCCESS)
554 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600555 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500556 "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' verification complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500557 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Josephef90b0d2021-08-17 07:12:49 -0700558 }
559 else
560 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600561 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500562 "Failed to verify component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - '{RESULT}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500563 "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT",
564 verifyResult);
Tom Josephef90b0d2021-08-17 07:12:49 -0700565 }
566
567 rc = encode_verify_complete_resp(request->hdr.instance_id, completionCode,
568 responseMsg, sizeof(completionCode));
569 if (rc)
570 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500571 error(
572 "Failed to encode verify complete response for endpoint ID '{EID}', response code - {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500573 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700574 return response;
575 }
576
577 return response;
578}
579
580Response DeviceUpdater::applyComplete(const pldm_msg* request,
581 size_t payloadLength)
582{
583 uint8_t completionCode = PLDM_SUCCESS;
584 Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530585 auto responseMsg = new (response.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700586
587 uint8_t applyResult = 0;
588 bitfield16_t compActivationModification{};
589 auto rc = decode_apply_complete_req(request, payloadLength, &applyResult,
590 &compActivationModification);
591 if (rc)
592 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500593 error(
594 "Failed to decode apply complete request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500595 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700596 rc = encode_apply_complete_resp(request->hdr.instance_id,
597 PLDM_ERROR_INVALID_DATA, responseMsg,
598 sizeof(completionCode));
599 if (rc)
600 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600601 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500602 "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500603 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700604 }
605 return response;
606 }
607
608 const auto& applicableComponents =
609 std::get<ApplicableComponents>(fwDeviceIDRecord);
610 const auto& comp = compImageInfos[applicableComponents[componentIndex]];
611 const auto& compVersion = std::get<7>(comp);
612
613 if (applyResult == PLDM_FWUP_APPLY_SUCCESS ||
614 applyResult == PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD)
615 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600616 info(
Riya Dixit76f2c602024-03-28 07:34:12 -0500617 "Component endpoint ID '{EID}' with '{COMPONENT_VERSION}' apply complete.",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500618 "EID", eid, "COMPONENT_VERSION", compVersion);
Tom Joseph4d8d5772021-08-17 07:35:05 -0700619 updateManager->updateActivationProgress();
Tom Josephef90b0d2021-08-17 07:12:49 -0700620 }
621 else
622 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600623 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500624 "Failed to apply component endpoint ID '{EID}' and version '{COMPONENT_VERSION}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500625 "EID", eid, "COMPONENT_VERSION", compVersion, "ERROR", applyResult);
Tom Josephef90b0d2021-08-17 07:12:49 -0700626 }
627
628 rc = encode_apply_complete_resp(request->hdr.instance_id, completionCode,
629 responseMsg, sizeof(completionCode));
630 if (rc)
631 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500632 error(
633 "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500634 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700635 return response;
636 }
637
638 if (componentIndex == applicableComponents.size() - 1)
639 {
640 componentIndex = 0;
641 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530642 updateManager->event,
Tom Josephef90b0d2021-08-17 07:12:49 -0700643 std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this));
644 }
645 else
646 {
647 componentIndex++;
648 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530649 updateManager->event,
650 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
651 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700652 }
653
654 return response;
655}
656
657void DeviceUpdater::sendActivateFirmwareRequest()
658{
659 pldmRequest.reset();
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930660 auto instanceId = updateManager->instanceIdDb.next(eid);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400661 Request request(
662 sizeof(pldm_msg_hdr) + sizeof(struct pldm_activate_firmware_req));
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530663 auto requestMsg = new (request.data()) pldm_msg;
Tom Josephef90b0d2021-08-17 07:12:49 -0700664
665 auto rc = encode_activate_firmware_req(
666 instanceId, PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
667 sizeof(pldm_activate_firmware_req));
668 if (rc)
669 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930670 updateManager->instanceIdDb.free(eid, instanceId);
Riya Dixit76f2c602024-03-28 07:34:12 -0500671 error(
672 "Failed to encode activate firmware req for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500673 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700674 }
675
Tom Josephb7e083e2021-10-26 15:10:03 +0530676 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700677 eid, instanceId, PLDM_FWUP, PLDM_ACTIVATE_FIRMWARE, std::move(request),
Eric Yang70eca962025-05-11 01:48:15 +0800678 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
679 this->activateFirmware(eid, response, respMsgLen);
680 });
Tom Josephef90b0d2021-08-17 07:12:49 -0700681 if (rc)
682 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500683 error(
684 "Failed to send activate firmware request for endpoint ID '{EID}', response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500685 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700686 }
687}
688
689void DeviceUpdater::activateFirmware(mctp_eid_t eid, const pldm_msg* response,
690 size_t respMsgLen)
691{
692 if (response == nullptr || !respMsgLen)
693 {
694 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500695 error(
696 "No response received for activate firmware for endpoint ID '{EID}'",
697 "EID", eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700698 return;
699 }
700
701 uint8_t completionCode = 0;
702 uint16_t estimatedTimeForActivation = 0;
703
704 auto rc = decode_activate_firmware_resp(
705 response, respMsgLen, &completionCode, &estimatedTimeForActivation);
706 if (rc)
707 {
708 // Handle error scenario
Riya Dixit76f2c602024-03-28 07:34:12 -0500709 error(
710 "Failed to decode activate firmware response for endpoint ID '{EID}', response code '{RC}'",
711 "EID", eid, "RC", rc);
Tom Josephef90b0d2021-08-17 07:12:49 -0700712 return;
713 }
714 if (completionCode)
715 {
716 // Handle error scenario
Riya Dixit49cfb132023-03-02 04:26:53 -0600717 error(
Riya Dixit76f2c602024-03-28 07:34:12 -0500718 "Failed to activate firmware response for endpoint ID '{EID}', completion code '{CC}'",
719 "EID", eid, "CC", completionCode);
Tom Josephef90b0d2021-08-17 07:12:49 -0700720 return;
721 }
Tom Joseph4d8d5772021-08-17 07:35:05 -0700722
723 updateManager->updateDeviceCompletion(eid, true);
Tom Josephef90b0d2021-08-17 07:12:49 -0700724}
725
726} // namespace fw_update
727
Patrick Williams6da4f912023-05-10 07:50:53 -0500728} // namespace pldm