blob: 5f3b3fbe4d9cd9dd0d759feb693f3d851e1392b6 [file] [log] [blame]
Tom Joseph75356c12021-06-20 03:52:40 -07001#include "inventory_manager.hpp"
2
Tom Joseph75356c12021-06-20 03:52:40 -07003#include "common/utils.hpp"
4#include "xyz/openbmc_project/Software/Version/server.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 Joseph75356c12021-06-20 03:52:40 -070010#include <functional>
11
Riya Dixit49cfb132023-03-02 04:26:53 -060012PHOSPHOR_LOG2_USING;
13
Tom Joseph75356c12021-06-20 03:52:40 -070014namespace pldm
15{
Tom Joseph75356c12021-06-20 03:52:40 -070016namespace fw_update
17{
Tom Joseph75356c12021-06-20 03:52:40 -070018void InventoryManager::discoverFDs(const std::vector<mctp_eid_t>& eids)
19{
20 for (const auto& eid : eids)
21 {
Unive Tien8b169dc2024-11-25 09:34:39 +080022 try
Tom Joseph75356c12021-06-20 03:52:40 -070023 {
Unive Tien8b169dc2024-11-25 09:34:39 +080024 sendQueryDeviceIdentifiersRequest(eid);
Tom Joseph75356c12021-06-20 03:52:40 -070025 }
Unive Tien8b169dc2024-11-25 09:34:39 +080026 catch (const std::exception& e)
27 {
28 error(
Unive Tien863b09b2025-02-07 16:51:37 +080029 "Failed to discover file descriptors for endpoint ID {EID} with {ERROR}",
Unive Tien8b169dc2024-11-25 09:34:39 +080030 "EID", eid, "ERROR", e);
31 }
32 }
33}
Tom Joseph75356c12021-06-20 03:52:40 -070034
Unive Tien8b169dc2024-11-25 09:34:39 +080035void InventoryManager::sendQueryDeviceIdentifiersRequest(mctp_eid_t eid)
36{
Eric Yang70262ed2025-07-02 06:35:03 +000037 auto instanceIdResult = pldm::utils::getInstanceId(instanceIdDb.next(eid));
38 if (!instanceIdResult)
39 {
40 return;
41 }
42 auto instanceId = instanceIdResult.value();
Unive Tien8b169dc2024-11-25 09:34:39 +080043 Request requestMsg(
44 sizeof(pldm_msg_hdr) + PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES);
45 auto request = new (requestMsg.data()) pldm_msg;
46 auto rc = encode_query_device_identifiers_req(
47 instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request);
48 if (rc)
49 {
50 instanceIdDb.free(eid, instanceId);
51 error(
52 "Failed to encode query device identifiers request for endpoint ID {EID} with response code {RC}",
53 "EID", eid, "RC", rc);
54 throw std::runtime_error(
55 "Failed to encode QueryDeviceIdentifiers request");
56 }
57
58 rc = handler.registerRequest(
59 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS,
60 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +080061 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
62 this->queryDeviceIdentifiers(eid, response, respMsgLen);
63 });
Unive Tien8b169dc2024-11-25 09:34:39 +080064 if (rc)
65 {
66 error(
67 "Failed to send query device identifiers request for endpoint ID {EID} with response code {RC}",
68 "EID", eid, "RC", rc);
69 throw std::runtime_error(
70 "Failed to send QueryDeviceIdentifiers request");
Tom Joseph75356c12021-06-20 03:52:40 -070071 }
72}
73
Patrick Williams16c2a0a2024-08-16 15:20:59 -040074void InventoryManager::queryDeviceIdentifiers(
75 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
Tom Joseph75356c12021-06-20 03:52:40 -070076{
77 if (response == nullptr || !respMsgLen)
78 {
Riya Dixit76f2c602024-03-28 07:34:12 -050079 error(
Unive Tien8b169dc2024-11-25 09:34:39 +080080 "No response received for query device identifiers for endpoint ID {EID}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050081 "EID", eid);
Tom Joseph75356c12021-06-20 03:52:40 -070082 return;
83 }
84
85 uint8_t completionCode = PLDM_SUCCESS;
86 uint32_t deviceIdentifiersLen = 0;
87 uint8_t descriptorCount = 0;
88 uint8_t* descriptorPtr = nullptr;
89
90 auto rc = decode_query_device_identifiers_resp(
91 response, respMsgLen, &completionCode, &deviceIdentifiersLen,
92 &descriptorCount, &descriptorPtr);
93 if (rc)
94 {
Riya Dixit49cfb132023-03-02 04:26:53 -060095 error(
Unive Tien8b169dc2024-11-25 09:34:39 +080096 "Failed to decode query device identifiers response for endpoint ID {EID} and descriptor count {DESCRIPTOR_COUNT}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050097 "EID", eid, "DESCRIPTOR_COUNT", descriptorCount, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -070098 return;
99 }
100
101 if (completionCode)
102 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600103 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800104 "Failed to query device identifiers response for endpoint ID {EID}, completion code {CC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500105 "EID", eid, "CC", completionCode);
Tom Joseph75356c12021-06-20 03:52:40 -0700106 return;
107 }
108
109 Descriptors descriptors{};
110 while (descriptorCount-- && (deviceIdentifiersLen > 0))
111 {
112 uint16_t descriptorType = 0;
113 variable_field descriptorData{};
114
115 rc = decode_descriptor_type_length_value(
116 descriptorPtr, deviceIdentifiersLen, &descriptorType,
117 &descriptorData);
118 if (rc)
119 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600120 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800121 "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID {EID}, response code {RC}",
Riya Dixit76f2c602024-03-28 07:34:12 -0500122 "TYPE", descriptorType, "LENGTH", deviceIdentifiersLen, "EID",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500123 eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700124 return;
125 }
126
127 if (descriptorType != PLDM_FWUP_VENDOR_DEFINED)
128 {
129 std::vector<uint8_t> descData(
130 descriptorData.ptr, descriptorData.ptr + descriptorData.length);
131 descriptors.emplace(descriptorType, std::move(descData));
132 }
133 else
134 {
135 uint8_t descriptorTitleStrType = 0;
136 variable_field descriptorTitleStr{};
137 variable_field vendorDefinedDescriptorData{};
138
139 rc = decode_vendor_defined_descriptor_value(
140 descriptorData.ptr, descriptorData.length,
141 &descriptorTitleStrType, &descriptorTitleStr,
142 &vendorDefinedDescriptorData);
143 if (rc)
144 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600145 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800146 "Failed to decode vendor-defined descriptor value for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500147 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700148 return;
149 }
150
151 auto vendorDefinedDescriptorTitleStr =
152 utils::toString(descriptorTitleStr);
153 std::vector<uint8_t> vendorDescData(
154 vendorDefinedDescriptorData.ptr,
155 vendorDefinedDescriptorData.ptr +
156 vendorDefinedDescriptorData.length);
157 descriptors.emplace(descriptorType,
158 std::make_tuple(vendorDefinedDescriptorTitleStr,
159 vendorDescData));
160 }
161 auto nextDescriptorOffset =
162 sizeof(pldm_descriptor_tlv().descriptor_type) +
163 sizeof(pldm_descriptor_tlv().descriptor_length) +
164 descriptorData.length;
165 descriptorPtr += nextDescriptorOffset;
166 deviceIdentifiersLen -= nextDescriptorOffset;
167 }
168
169 descriptorMap.emplace(eid, std::move(descriptors));
170
171 // Send GetFirmwareParameters request
172 sendGetFirmwareParametersRequest(eid);
173}
174
Unive Tien8b169dc2024-11-25 09:34:39 +0800175void InventoryManager::sendQueryDownstreamDevicesRequest(mctp_eid_t eid)
176{
177 Request requestMsg(sizeof(pldm_msg_hdr));
Eric Yang70262ed2025-07-02 06:35:03 +0000178 auto instanceIdResult = pldm::utils::getInstanceId(instanceIdDb.next(eid));
179 if (!instanceIdResult)
180 {
181 return;
182 }
183 auto instanceId = instanceIdResult.value();
Unive Tien8b169dc2024-11-25 09:34:39 +0800184 auto request = new (requestMsg.data()) pldm_msg;
185 auto rc = encode_query_downstream_devices_req(instanceId, request);
186 if (rc)
187 {
188 instanceIdDb.free(eid, instanceId);
189 error(
190 "Failed to encode query downstream devices request for endpoint ID EID {EID} with response code {RC}",
191 "EID", eid, "RC", rc);
192 throw std::runtime_error(
193 "Failed to encode query downstream devices request");
194 }
195
196 rc = handler.registerRequest(
197 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_DEVICES,
198 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800199 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
200 this->queryDownstreamDevices(eid, response, respMsgLen);
201 });
Unive Tien8b169dc2024-11-25 09:34:39 +0800202 if (rc)
203 {
204 error(
205 "Failed to send QueryDownstreamDevices request for endpoint ID {EID} with response code {RC}",
206 "EID", eid, "RC", rc);
207 }
208}
209
210void InventoryManager::queryDownstreamDevices(
211 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
212{
213 if (!response || !respMsgLen)
214 {
215 error(
216 "No response received for QueryDownstreamDevices for endpoint ID {EID}",
217 "EID", eid);
218 return;
219 }
220
221 pldm_query_downstream_devices_resp downstreamDevicesResp{};
222 auto rc = decode_query_downstream_devices_resp(response, respMsgLen,
223 &downstreamDevicesResp);
224 if (rc)
225 {
226 error(
227 "Decoding QueryDownstreamDevices response failed for endpoint ID {EID} with response code {RC}",
228 "EID", eid, "RC", rc);
229 return;
230 }
231
232 switch (downstreamDevicesResp.completion_code)
233 {
234 case PLDM_SUCCESS:
235 break;
236 case PLDM_ERROR_UNSUPPORTED_PLDM_CMD:
237 /* QueryDownstreamDevices is optional, consider the device does not
238 * support Downstream Devices.
239 */
240 info("Endpoint ID {EID} does not support QueryDownstreamDevices",
241 "EID", eid);
242 return;
243 default:
244 error(
245 "QueryDownstreamDevices response failed with error completion code for endpoint ID {EID} with completion code {CC}",
246 "EID", eid, "CC", downstreamDevicesResp.completion_code);
247 return;
248 }
249
250 switch (downstreamDevicesResp.downstream_device_update_supported)
251 {
252 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
253 /** DataTransferHandle will be skipped when TransferOperationFlag is
254 * `GetFirstPart`. Use 0x0 as default by following example in
255 * Figure 9 in DSP0267 1.1.0
256 */
257 try
258 {
259 sendQueryDownstreamIdentifiersRequest(eid, 0x0,
260 PLDM_GET_FIRSTPART);
261 }
262 catch (const std::exception& e)
263 {
264 error(
265 "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with {ERROR}",
266 "EID", eid, "ERROR", e);
267 }
268 break;
269 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
270 /* The FDP does not support firmware updates but may report
271 * inventory information on downstream devices.
272 * In this scenario, sends only GetDownstreamFirmwareParameters
273 * to the FDP.
274 * The definition can be found at Table 15 of DSP0267_1.1.0
275 */
276 break;
277 default:
278 error(
279 "Unknown response of DownstreamDeviceUpdateSupported from endpoint ID {EID} with value {VALUE}",
280 "EID", eid, "VALUE",
281 downstreamDevicesResp.downstream_device_update_supported);
282 return;
283 }
284}
285
286void InventoryManager::sendQueryDownstreamIdentifiersRequest(
287 mctp_eid_t eid, uint32_t dataTransferHandle,
288 enum transfer_op_flag transferOperationFlag)
289{
Eric Yang70262ed2025-07-02 06:35:03 +0000290 auto instanceIdResult = pldm::utils::getInstanceId(instanceIdDb.next(eid));
291 if (!instanceIdResult)
292 {
293 return;
294 }
295 auto instanceId = instanceIdResult.value();
Unive Tien8b169dc2024-11-25 09:34:39 +0800296 Request requestMsg(
297 sizeof(pldm_msg_hdr) + PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES);
298 auto request = new (requestMsg.data()) pldm_msg;
299 pldm_query_downstream_identifiers_req requestParameters{
300 dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)};
301
302 auto rc = encode_query_downstream_identifiers_req(
303 instanceId, &requestParameters, request,
304 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES);
305 if (rc)
306 {
307 instanceIdDb.free(eid, instanceId);
308 error(
309 "Failed to encode query downstream identifiers request for endpoint ID {EID} with response code {RC}",
310 "EID", eid, "RC", rc);
311 throw std::runtime_error(
312 "Failed to encode query downstream identifiers request");
313 }
314
315 rc = handler.registerRequest(
316 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS,
317 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800318 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
319 this->queryDownstreamIdentifiers(eid, response, respMsgLen);
320 });
Unive Tien8b169dc2024-11-25 09:34:39 +0800321 if (rc)
322 {
323 error(
324 "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with response code {RC}",
325 "EID", eid, "RC", rc);
326 }
327}
328
329void InventoryManager::queryDownstreamIdentifiers(
330 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
331{
332 if (!response || !respMsgLen)
333 {
334 error(
335 "No response received for QueryDownstreamIdentifiers for endpoint ID {EID}",
336 "EID", eid);
337 descriptorMap.erase(eid);
338 return;
339 }
340
341 pldm_query_downstream_identifiers_resp downstreamIds{};
342 pldm_downstream_device_iter devs{};
343
344 auto rc = decode_query_downstream_identifiers_resp(response, respMsgLen,
345 &downstreamIds, &devs);
346 if (rc)
347 {
348 error(
349 "Decoding QueryDownstreamIdentifiers response failed for endpoint ID {EID} with response code {RC}",
350 "EID", eid, "RC", rc);
351 return;
352 }
353
354 if (downstreamIds.completion_code)
355 {
356 error(
357 "QueryDownstreamIdentifiers response failed with error completion code for endpoint ID {EID} with completion code {CC}",
358 "EID", eid, "CC", unsigned(downstreamIds.completion_code));
359 return;
360 }
361
362 DownstreamDeviceInfo initialDownstreamDevices{};
363 DownstreamDeviceInfo* downstreamDevices;
364 if (!downstreamDescriptorMap.contains(eid) ||
365 downstreamIds.transfer_flag == PLDM_START ||
366 downstreamIds.transfer_flag == PLDM_START_AND_END)
367 {
368 downstreamDevices = &initialDownstreamDevices;
369 }
370 else
371 {
372 downstreamDevices = &downstreamDescriptorMap.at(eid);
373 }
374
375 pldm_downstream_device dev;
376 foreach_pldm_downstream_device(devs, dev, rc)
377 {
378 pldm_descriptor desc;
379 Descriptors descriptors{};
380 foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)
381 {
382 const auto descriptorData =
383 new (const_cast<void*>(desc.descriptor_data))
384 uint8_t[desc.descriptor_length];
385 if (desc.descriptor_type != PLDM_FWUP_VENDOR_DEFINED)
386 {
387 std::vector<uint8_t> descData(
388 descriptorData, descriptorData + desc.descriptor_length);
389 descriptors.emplace(desc.descriptor_type, std::move(descData));
390 }
391 else
392 {
393 uint8_t descriptorTitleStrType = 0;
394 variable_field descriptorTitleStr{};
395 variable_field vendorDefinedDescriptorData{};
396
397 rc = decode_vendor_defined_descriptor_value(
398 descriptorData, desc.descriptor_length,
399 &descriptorTitleStrType, &descriptorTitleStr,
400 &vendorDefinedDescriptorData);
401
402 if (rc)
403 {
404 error(
405 "Decoding Vendor-defined descriptor value failed for endpoint ID {EID} with response code {RC}",
406 "EID", eid, "RC", rc);
407 return;
408 }
409
410 auto vendorDefinedDescriptorTitleStr =
411 utils::toString(descriptorTitleStr);
412 std::vector<uint8_t> vendorDescData(
413 vendorDefinedDescriptorData.ptr,
414 vendorDefinedDescriptorData.ptr +
415 vendorDefinedDescriptorData.length);
416 descriptors.emplace(
417 desc.descriptor_type,
418 std::make_tuple(vendorDefinedDescriptorTitleStr,
419 vendorDescData));
420 }
421 }
422 if (rc)
423 {
424 error(
425 "Failed to decode downstream device descriptor for endpoint ID {EID} with response code {RC}",
426 "EID", eid, "RC", rc);
427 return;
428 }
429 downstreamDevices->emplace(dev.downstream_device_index, descriptors);
430 }
431 if (rc)
432 {
433 error(
434 "Failed to decode downstream devices from iterator for endpoint ID {EID} with response code {RC}",
435 "EID", eid, "RC", rc);
436 return;
437 }
438
439 switch (downstreamIds.transfer_flag)
440 {
441 case PLDM_START:
442 downstreamDescriptorMap.insert_or_assign(
443 eid, std::move(initialDownstreamDevices));
444 [[fallthrough]];
445 case PLDM_MIDDLE:
446 sendQueryDownstreamIdentifiersRequest(
447 eid, downstreamIds.next_data_transfer_handle,
448 PLDM_GET_NEXTPART);
449 break;
450 case PLDM_START_AND_END:
451 downstreamDescriptorMap.insert_or_assign(
452 eid, std::move(initialDownstreamDevices));
453 /** DataTransferHandle will be skipped when TransferOperationFlag is
454 * `GetFirstPart`. Use 0x0 as default by following example in
455 * Figure 9 in DSP0267 1.1.0
456 */
457 [[fallthrough]];
458 case PLDM_END:
459 sendGetDownstreamFirmwareParametersRequest(eid, 0x0,
460 PLDM_GET_FIRSTPART);
461 break;
462 }
463}
464
465void InventoryManager::sendGetDownstreamFirmwareParametersRequest(
466 mctp_eid_t eid, uint32_t dataTransferHandle,
467 enum transfer_op_flag transferOperationFlag)
468{
469 Request requestMsg(sizeof(pldm_msg_hdr) +
470 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES);
Eric Yang70262ed2025-07-02 06:35:03 +0000471 auto instanceIdResult = pldm::utils::getInstanceId(instanceIdDb.next(eid));
472 if (!instanceIdResult)
473 {
474 return;
475 }
476 auto instanceId = instanceIdResult.value();
Unive Tien8b169dc2024-11-25 09:34:39 +0800477 auto request = new (requestMsg.data()) pldm_msg;
478 pldm_get_downstream_firmware_parameters_req requestParameters{
479 dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)};
480 auto rc = encode_get_downstream_firmware_parameters_req(
481 instanceId, &requestParameters, request,
482 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES);
483 if (rc)
484 {
485 instanceIdDb.free(eid, instanceId);
486 error(
487 "Failed to encode query downstream firmware parameters request for endpoint ID {EID} with response code {RC}",
488 "EID", eid, "RC", rc);
489 throw std::runtime_error(
490 "Failed to encode query downstream firmware parameters request");
491 }
492
493 rc = handler.registerRequest(
494 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS,
495 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800496 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
497 this->getDownstreamFirmwareParameters(eid, response, respMsgLen);
498 });
Unive Tien8b169dc2024-11-25 09:34:39 +0800499 if (rc)
500 {
501 error(
502 "Failed to send QueryDownstreamFirmwareParameters request for endpoint ID {EID} with response code {RC}",
503 "EID", eid, "RC", rc);
504 }
505}
506
507void InventoryManager::getDownstreamFirmwareParameters(
508 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
509{
510 if (!response || !respMsgLen)
511 {
512 error(
513 "No response received for QueryDownstreamFirmwareParameters for endpoint ID {EID}",
514 "EID", eid);
515 descriptorMap.erase(eid);
516 return;
517 }
518
519 pldm_get_downstream_firmware_parameters_resp resp{};
520 pldm_downstream_device_parameters_iter params{};
521 pldm_downstream_device_parameters_entry entry{};
522
523 auto rc = decode_get_downstream_firmware_parameters_resp(
524 response, respMsgLen, &resp, &params);
525
526 if (rc)
527 {
528 error(
529 "Decoding QueryDownstreamFirmwareParameters response failed for endpoint ID {EID} with response code {RC}",
530 "EID", eid, "RC", rc);
531 return;
532 }
533
534 if (resp.completion_code)
535 {
536 error(
537 "QueryDownstreamFirmwareParameters response failed with error completion code for endpoint ID {EID} with completion code {CC}",
538 "EID", eid, "CC", resp.completion_code);
539 return;
540 }
541
542 foreach_pldm_downstream_device_parameters_entry(params, entry, rc)
543 {
544 // Reserved for upcoming use
545 [[maybe_unused]] variable_field activeCompVerStr{
546 reinterpret_cast<const uint8_t*>(entry.active_comp_ver_str),
547 entry.active_comp_ver_str_len};
548 }
549 if (rc)
550 {
551 error(
552 "Failed to decode downstream device parameters from iterator for endpoint ID {EID} with response code {RC}",
553 "EID", eid, "RC", rc);
554 return;
555 }
556
557 switch (resp.transfer_flag)
558 {
559 case PLDM_START:
560 case PLDM_MIDDLE:
561 sendGetDownstreamFirmwareParametersRequest(
562 eid, resp.next_data_transfer_handle, PLDM_GET_NEXTPART);
563 break;
564 }
565}
566
Tom Joseph75356c12021-06-20 03:52:40 -0700567void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid)
568{
Eric Yang70262ed2025-07-02 06:35:03 +0000569 auto instanceIdResult = pldm::utils::getInstanceId(instanceIdDb.next(eid));
570 if (!instanceIdResult)
571 {
572 return;
573 }
574 auto instanceId = instanceIdResult.value();
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400575 Request requestMsg(
576 sizeof(pldm_msg_hdr) + PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530577 auto request = new (requestMsg.data()) pldm_msg;
Tom Joseph75356c12021-06-20 03:52:40 -0700578 auto rc = encode_get_firmware_parameters_req(
579 instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request);
580 if (rc)
581 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930582 instanceIdDb.free(eid, instanceId);
Riya Dixit76f2c602024-03-28 07:34:12 -0500583 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800584 "Failed to encode get firmware parameters req for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500585 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700586 return;
587 }
588
589 rc = handler.registerRequest(
590 eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS,
591 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800592 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
593 this->getFirmwareParameters(eid, response, respMsgLen);
594 });
Tom Joseph75356c12021-06-20 03:52:40 -0700595 if (rc)
596 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600597 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800598 "Failed to send get firmware parameters request for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500599 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700600 }
601}
602
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400603void InventoryManager::getFirmwareParameters(
604 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
Tom Joseph75356c12021-06-20 03:52:40 -0700605{
606 if (response == nullptr || !respMsgLen)
607 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500608 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800609 "No response received for get firmware parameters for endpoint ID {EID}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500610 "EID", eid);
Tom Joseph75356c12021-06-20 03:52:40 -0700611 descriptorMap.erase(eid);
612 return;
613 }
614
615 pldm_get_firmware_parameters_resp fwParams{};
616 variable_field activeCompImageSetVerStr{};
617 variable_field pendingCompImageSetVerStr{};
618 variable_field compParamTable{};
619
620 auto rc = decode_get_firmware_parameters_resp(
621 response, respMsgLen, &fwParams, &activeCompImageSetVerStr,
622 &pendingCompImageSetVerStr, &compParamTable);
623 if (rc)
624 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600625 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800626 "Failed to decode get firmware parameters response for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500627 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700628 return;
629 }
630
631 if (fwParams.completion_code)
632 {
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500633 auto fw_param_cc = fwParams.completion_code;
Riya Dixit49cfb132023-03-02 04:26:53 -0600634 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800635 "Failed to get firmware parameters response for endpoint ID {EID}, completion code {CC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500636 "EID", eid, "CC", fw_param_cc);
Tom Joseph75356c12021-06-20 03:52:40 -0700637 return;
638 }
639
640 auto compParamPtr = compParamTable.ptr;
641 auto compParamTableLen = compParamTable.length;
642 pldm_component_parameter_entry compEntry{};
643 variable_field activeCompVerStr{};
644 variable_field pendingCompVerStr{};
645
646 ComponentInfo componentInfo{};
647 while (fwParams.comp_count-- && (compParamTableLen > 0))
648 {
649 auto rc = decode_get_firmware_parameters_resp_comp_entry(
650 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr,
651 &pendingCompVerStr);
652 if (rc)
653 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600654 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800655 "Failed to decode component parameter table entry for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500656 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700657 return;
658 }
659
660 auto compClassification = compEntry.comp_classification;
661 auto compIdentifier = compEntry.comp_identifier;
662 componentInfo.emplace(
663 std::make_pair(compClassification, compIdentifier),
664 compEntry.comp_classification_index);
665 compParamPtr += sizeof(pldm_component_parameter_entry) +
666 activeCompVerStr.length + pendingCompVerStr.length;
667 compParamTableLen -= sizeof(pldm_component_parameter_entry) +
668 activeCompVerStr.length + pendingCompVerStr.length;
669 }
670 componentInfoMap.emplace(eid, std::move(componentInfo));
671}
672
673} // namespace fw_update
674
Riya Dixit49cfb132023-03-02 04:26:53 -0600675} // namespace pldm