blob: 9a053fc1e67015401fe72ef5a5dc78d4dfbe87bd [file] [log] [blame]
Gilbert Chen6c7fed42022-02-22 15:40:17 +00001#include "platform_manager.hpp"
2
3#include "terminus_manager.hpp"
4
5#include <phosphor-logging/lg2.hpp>
6
Gilbert Chende2a1322022-05-24 15:35:21 +01007#include <ranges>
8
Gilbert Chen6c7fed42022-02-22 15:40:17 +00009PHOSPHOR_LOG2_USING;
10
11namespace pldm
12{
13namespace platform_mc
14{
15
16exec::task<int> PlatformManager::initTerminus()
17{
18 for (auto& [tid, terminus] : termini)
19 {
20 if (terminus->initialized)
21 {
22 continue;
23 }
Gilbert Chende2a1322022-05-24 15:35:21 +010024
Dung Caob6d39432024-06-05 03:46:47 +000025 /* Get Fru */
26 uint16_t totalTableRecords = 0;
27 if (terminus->doesSupportCommand(PLDM_FRU,
28 PLDM_GET_FRU_RECORD_TABLE_METADATA))
29 {
30 auto rc =
31 co_await getFRURecordTableMetadata(tid, &totalTableRecords);
32 if (rc)
33 {
34 lg2::error(
35 "Failed to get FRU Metadata for terminus {TID}, error {ERROR}",
36 "TID", tid, "ERROR", rc);
37 }
38 if (!totalTableRecords)
39 {
40 lg2::info("Fru record table meta data has 0 records");
41 }
42 }
43
44 std::vector<uint8_t> fruData{};
45 if ((totalTableRecords != 0) &&
46 terminus->doesSupportCommand(PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE))
47 {
48 auto rc =
49 co_await getFRURecordTables(tid, totalTableRecords, fruData);
50 if (rc)
51 {
52 lg2::error(
53 "Failed to get Fru Record table for terminus {TID}, error {ERROR}",
54 "TID", tid, "ERROR", rc);
55 }
56 }
57
Gilbert Chende2a1322022-05-24 15:35:21 +010058 if (terminus->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR))
59 {
60 auto rc = co_await getPDRs(terminus);
61 if (rc)
62 {
63 lg2::error(
64 "Failed to fetch PDRs for terminus with TID: {TID}, error: {ERROR}",
65 "TID", tid, "ERROR", rc);
66 continue; // Continue to next terminus
67 }
68
69 terminus->parseTerminusPDRs();
70 }
Thu Nguyen51d66b52024-08-06 09:15:55 +000071
Dung Caob6d39432024-06-05 03:46:47 +000072 /**
73 * Need terminus name from PDRs before updating Inventory object with
74 * Fru data
75 */
76 if (fruData.size())
77 {
78 updateInventoryWithFru(tid, fruData.data(), fruData.size());
79 }
80
Gilbert Chen77e6fe72024-08-06 09:23:30 +000081 uint16_t terminusMaxBufferSize = terminus->maxBufferSize;
82 if (!terminus->doesSupportCommand(PLDM_PLATFORM,
83 PLDM_EVENT_MESSAGE_BUFFER_SIZE))
84 {
85 terminusMaxBufferSize = PLDM_PLATFORM_DEFAULT_MESSAGE_BUFFER_SIZE;
86 }
87 else
88 {
89 /* Get maxBufferSize use PLDM command eventMessageBufferSize */
90 auto rc = co_await eventMessageBufferSize(
91 tid, terminus->maxBufferSize, terminusMaxBufferSize);
92 if (rc != PLDM_SUCCESS)
93 {
94 lg2::error(
95 "Failed to get message buffer size for terminus with TID: {TID}, error: {ERROR}",
96 "TID", tid, "ERROR", rc);
97 terminusMaxBufferSize =
98 PLDM_PLATFORM_DEFAULT_MESSAGE_BUFFER_SIZE;
99 }
100 }
101 terminus->maxBufferSize =
102 std::min(terminus->maxBufferSize, terminusMaxBufferSize);
103
Thu Nguyen51d66b52024-08-06 09:15:55 +0000104 auto rc = co_await configEventReceiver(tid);
105 if (rc)
106 {
107 lg2::error(
108 "Failed to config event receiver for terminus with TID: {TID}, error: {ERROR}",
109 "TID", tid, "ERROR", rc);
110 }
Eric Yangf00fd432024-10-26 16:38:21 +0800111 terminus->initialized = true;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000112 }
Thu Nguyen51d66b52024-08-06 09:15:55 +0000113
114 co_return PLDM_SUCCESS;
115}
116
117exec::task<int> PlatformManager::configEventReceiver(pldm_tid_t tid)
118{
119 if (!termini.contains(tid))
120 {
121 co_return PLDM_ERROR;
122 }
123
124 auto& terminus = termini[tid];
125 if (!terminus->doesSupportCommand(PLDM_PLATFORM,
126 PLDM_EVENT_MESSAGE_SUPPORTED))
127 {
Thu Nguyenc3ad6c62023-11-07 20:19:25 +0700128 terminus->synchronyConfigurationSupported.byte =
129 1 << PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE;
Thu Nguyen51d66b52024-08-06 09:15:55 +0000130 }
131 else
132 {
133 /**
134 * Get synchronyConfigurationSupported use PLDM command
135 * eventMessageBufferSize
136 */
137 uint8_t synchronyConfiguration = 0;
138 uint8_t numberEventClassReturned = 0;
139 std::vector<uint8_t> eventClass{};
140 auto rc = co_await eventMessageSupported(
141 tid, 1, synchronyConfiguration,
142 terminus->synchronyConfigurationSupported, numberEventClassReturned,
143 eventClass);
144 if (rc != PLDM_SUCCESS)
145 {
146 lg2::error(
147 "Failed to get event message supported for terminus with TID: {TID}, error: {ERROR}",
148 "TID", tid, "ERROR", rc);
149 terminus->synchronyConfigurationSupported.byte = 0;
150 }
151 }
152
153 if (!terminus->doesSupportCommand(PLDM_PLATFORM, PLDM_SET_EVENT_RECEIVER))
154 {
155 lg2::error("Terminus {TID} does not support Event", "TID", tid);
156 co_return PLDM_ERROR;
157 }
158
159 /**
160 * Set Event receiver base on synchronyConfigurationSupported data
161 * use PLDM command SetEventReceiver
162 */
163 pldm_event_message_global_enable eventMessageGlobalEnable =
164 PLDM_EVENT_MESSAGE_GLOBAL_DISABLE;
165 uint16_t heartbeatTimer = 0;
166
167 /* Use PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE when
168 * for eventMessageGlobalEnable when the terminus supports that type
169 */
170 if (terminus->synchronyConfigurationSupported.byte &
171 (1 << PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE))
172 {
173 heartbeatTimer = HEARTBEAT_TIMEOUT;
174 eventMessageGlobalEnable =
175 PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE;
176 }
177 /* Use PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC when
178 * for eventMessageGlobalEnable when the terminus does not support
179 * PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE
180 * and supports PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC type
181 */
182 else if (terminus->synchronyConfigurationSupported.byte &
183 (1 << PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC))
184 {
185 eventMessageGlobalEnable = PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC;
186 }
187 /* Only use PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_POLLING
188 * for eventMessageGlobalEnable when the terminus only supports
189 * this type
190 */
191 else if (terminus->synchronyConfigurationSupported.byte &
192 (1 << PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_POLLING))
193 {
194 eventMessageGlobalEnable = PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_POLLING;
195 }
196
197 if (eventMessageGlobalEnable != PLDM_EVENT_MESSAGE_GLOBAL_DISABLE)
198 {
199 auto rc = co_await setEventReceiver(tid, eventMessageGlobalEnable,
200 PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP,
201 heartbeatTimer);
202 if (rc != PLDM_SUCCESS)
203 {
204 lg2::error(
205 "Failed to set event receiver for terminus with TID: {TID}, error: {ERROR}",
206 "TID", tid, "ERROR", rc);
207 }
208 }
209
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000210 co_return PLDM_SUCCESS;
211}
212
Gilbert Chende2a1322022-05-24 15:35:21 +0100213exec::task<int> PlatformManager::getPDRs(std::shared_ptr<Terminus> terminus)
214{
215 pldm_tid_t tid = terminus->getTid();
216
217 /* Setting default values when getPDRRepositoryInfo fails or does not
218 * support */
219 uint8_t repositoryState = PLDM_AVAILABLE;
220 uint32_t recordCount = std::numeric_limits<uint32_t>::max();
221 uint32_t repositorySize = 0;
222 uint32_t largestRecordSize = std::numeric_limits<uint32_t>::max();
223 if (terminus->doesSupportCommand(PLDM_PLATFORM,
224 PLDM_GET_PDR_REPOSITORY_INFO))
225 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400226 auto rc =
227 co_await getPDRRepositoryInfo(tid, repositoryState, recordCount,
228 repositorySize, largestRecordSize);
Gilbert Chende2a1322022-05-24 15:35:21 +0100229 if (rc)
230 {
231 lg2::error(
232 "Failed to get PDR Repository Info for terminus with TID: {TID}, error: {ERROR}",
233 "TID", tid, "ERROR", rc);
234 }
235 else
236 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400237 recordCount =
238 std::min(recordCount + 1, std::numeric_limits<uint32_t>::max());
Gilbert Chende2a1322022-05-24 15:35:21 +0100239 largestRecordSize = std::min(largestRecordSize + 1,
240 std::numeric_limits<uint32_t>::max());
241 }
242 }
243
244 if (repositoryState != PLDM_AVAILABLE)
245 {
246 co_return PLDM_ERROR_NOT_READY;
247 }
248
249 uint32_t recordHndl = 0;
250 uint32_t nextRecordHndl = 0;
251 uint32_t nextDataTransferHndl = 0;
252 uint8_t transferFlag = 0;
253 uint16_t responseCnt = 0;
254 constexpr uint16_t recvBufSize = PLDM_PLATFORM_GETPDR_MAX_RECORD_BYTES;
255 std::vector<uint8_t> recvBuf(recvBufSize);
256 uint8_t transferCrc = 0;
257
258 terminus->pdrs.clear();
259 uint32_t receivedRecordCount = 0;
260
261 do
262 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400263 auto rc =
264 co_await getPDR(tid, recordHndl, 0, PLDM_GET_FIRSTPART, recvBufSize,
265 0, nextRecordHndl, nextDataTransferHndl,
266 transferFlag, responseCnt, recvBuf, transferCrc);
Gilbert Chende2a1322022-05-24 15:35:21 +0100267
268 if (rc)
269 {
270 lg2::error(
271 "Failed to get PDRs for terminus {TID}, error: {RC}, first part of record handle {RECORD}",
272 "TID", tid, "RC", rc, "RECORD", recordHndl);
273 terminus->pdrs.clear();
274 co_return rc;
275 }
276
277 if (transferFlag == PLDM_PLATFORM_TRANSFER_START_AND_END)
278 {
279 // single-part
280 terminus->pdrs.emplace_back(std::vector<uint8_t>(
281 recvBuf.begin(), recvBuf.begin() + responseCnt));
282 recordHndl = nextRecordHndl;
283 }
284 else
285 {
286 // multipart transfer
287 uint32_t receivedRecordSize = responseCnt;
288 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(recvBuf.data());
289 uint16_t recordChgNum = le16toh(pdrHdr->record_change_num);
290 std::vector<uint8_t> receivedPdr(recvBuf.begin(),
291 recvBuf.begin() + responseCnt);
292 do
293 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400294 rc = co_await getPDR(
295 tid, recordHndl, nextDataTransferHndl, PLDM_GET_NEXTPART,
296 recvBufSize, recordChgNum, nextRecordHndl,
297 nextDataTransferHndl, transferFlag, responseCnt, recvBuf,
298 transferCrc);
Gilbert Chende2a1322022-05-24 15:35:21 +0100299 if (rc)
300 {
301 lg2::error(
302 "Failed to get PDRs for terminus {TID}, error: {RC}, get middle part of record handle {RECORD}",
303 "TID", tid, "RC", rc, "RECORD", recordHndl);
304 terminus->pdrs.clear();
305 co_return rc;
306 }
307
308 receivedPdr.insert(receivedPdr.end(), recvBuf.begin(),
309 recvBuf.begin() + responseCnt);
310 receivedRecordSize += responseCnt;
311
312 if (transferFlag == PLDM_PLATFORM_TRANSFER_END)
313 {
314 terminus->pdrs.emplace_back(std::move(receivedPdr));
315 recordHndl = nextRecordHndl;
316 }
317 } while (nextDataTransferHndl != 0 &&
318 receivedRecordSize < largestRecordSize);
319 }
320 receivedRecordCount++;
321 } while (nextRecordHndl != 0 && receivedRecordCount < recordCount);
322
323 co_return PLDM_SUCCESS;
324}
325
326exec::task<int> PlatformManager::getPDR(
327 const pldm_tid_t tid, const uint32_t recordHndl,
328 const uint32_t dataTransferHndl, const uint8_t transferOpFlag,
329 const uint16_t requestCnt, const uint16_t recordChgNum,
330 uint32_t& nextRecordHndl, uint32_t& nextDataTransferHndl,
331 uint8_t& transferFlag, uint16_t& responseCnt,
332 std::vector<uint8_t>& recordData, uint8_t& transferCrc)
333{
334 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES);
335 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
336 auto rc = encode_get_pdr_req(0, recordHndl, dataTransferHndl,
337 transferOpFlag, requestCnt, recordChgNum,
338 requestMsg, PLDM_GET_PDR_REQ_BYTES);
339 if (rc)
340 {
341 lg2::error(
342 "Failed to encode request GetPDR for terminus ID {TID}, error {RC} ",
343 "TID", tid, "RC", rc);
344 co_return rc;
345 }
346
347 const pldm_msg* responseMsg = nullptr;
348 size_t responseLen = 0;
349 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
350 &responseLen);
351 if (rc)
352 {
353 lg2::error(
354 "Failed to send GetPDR message for terminus {TID}, error {RC}",
355 "TID", tid, "RC", rc);
356 co_return rc;
357 }
358
359 uint8_t completionCode;
360 rc = decode_get_pdr_resp(responseMsg, responseLen, &completionCode,
361 &nextRecordHndl, &nextDataTransferHndl,
362 &transferFlag, &responseCnt, recordData.data(),
363 recordData.size(), &transferCrc);
364 if (rc)
365 {
366 lg2::error(
367 "Failed to decode response GetPDR for terminus ID {TID}, error {RC} ",
368 "TID", tid, "RC", rc);
369 co_return rc;
370 }
371
372 if (completionCode != PLDM_SUCCESS)
373 {
374 lg2::error("Error : GetPDR for terminus ID {TID}, complete code {CC}.",
375 "TID", tid, "CC", completionCode);
376 co_return rc;
377 }
378
379 co_return completionCode;
380}
381
382exec::task<int> PlatformManager::getPDRRepositoryInfo(
383 const pldm_tid_t tid, uint8_t& repositoryState, uint32_t& recordCount,
384 uint32_t& repositorySize, uint32_t& largestRecordSize)
385{
386 Request request(sizeof(pldm_msg_hdr) + sizeof(uint8_t));
387 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
388 auto rc = encode_pldm_header_only(PLDM_REQUEST, 0, PLDM_PLATFORM,
389 PLDM_GET_PDR_REPOSITORY_INFO, requestMsg);
390 if (rc)
391 {
392 lg2::error(
393 "Failed to encode request GetPDRRepositoryInfo for terminus ID {TID}, error {RC} ",
394 "TID", tid, "RC", rc);
395 co_return rc;
396 }
397
398 const pldm_msg* responseMsg = nullptr;
399 size_t responseLen = 0;
400 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
401 &responseLen);
402 if (rc)
403 {
404 lg2::error(
405 "Failed to send GetPDRRepositoryInfo message for terminus {TID}, error {RC}",
406 "TID", tid, "RC", rc);
407 co_return rc;
408 }
409
410 uint8_t completionCode = 0;
411 std::array<uint8_t, PLDM_TIMESTAMP104_SIZE> updateTime = {};
412 std::array<uint8_t, PLDM_TIMESTAMP104_SIZE> oemUpdateTime = {};
413 uint8_t dataTransferHandleTimeout = 0;
414
415 rc = decode_get_pdr_repository_info_resp(
416 responseMsg, responseLen, &completionCode, &repositoryState,
417 updateTime.data(), oemUpdateTime.data(), &recordCount, &repositorySize,
418 &largestRecordSize, &dataTransferHandleTimeout);
419 if (rc)
420 {
421 lg2::error(
422 "Failed to decode response GetPDRRepositoryInfo for terminus ID {TID}, error {RC} ",
423 "TID", tid, "RC", rc);
424 co_return rc;
425 }
426
427 if (completionCode != PLDM_SUCCESS)
428 {
429 lg2::error(
430 "Error : GetPDRRepositoryInfo for terminus ID {TID}, complete code {CC}.",
431 "TID", tid, "CC", completionCode);
432 co_return rc;
433 }
434
435 co_return completionCode;
436}
437
Gilbert Chen77e6fe72024-08-06 09:23:30 +0000438exec::task<int> PlatformManager::eventMessageBufferSize(
439 pldm_tid_t tid, uint16_t receiverMaxBufferSize,
440 uint16_t& terminusBufferSize)
441{
442 Request request(
443 sizeof(pldm_msg_hdr) + PLDM_EVENT_MESSAGE_BUFFER_SIZE_REQ_BYTES);
444 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
445 auto rc = encode_event_message_buffer_size_req(0, receiverMaxBufferSize,
446 requestMsg);
447 if (rc)
448 {
449 lg2::error(
450 "Failed to encode request GetPDRRepositoryInfo for terminus ID {TID}, error {RC} ",
451 "TID", tid, "RC", rc);
452 co_return rc;
453 }
454
455 const pldm_msg* responseMsg = nullptr;
456 size_t responseLen = 0;
457 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
458 &responseLen);
459 if (rc)
460 {
461 lg2::error(
462 "Failed to send EventMessageBufferSize message for terminus {TID}, error {RC}",
463 "TID", tid, "RC", rc);
464 co_return rc;
465 }
466
467 uint8_t completionCode;
468 rc = decode_event_message_buffer_size_resp(
469 responseMsg, responseLen, &completionCode, &terminusBufferSize);
470 if (rc)
471 {
472 lg2::error(
473 "Failed to decode response EventMessageBufferSize for terminus ID {TID}, error {RC} ",
474 "TID", tid, "RC", rc);
475 co_return rc;
476 }
477
478 if (completionCode != PLDM_SUCCESS)
479 {
480 lg2::error(
481 "Error : EventMessageBufferSize for terminus ID {TID}, complete code {CC}.",
482 "TID", tid, "CC", completionCode);
483 co_return completionCode;
484 }
485
486 co_return completionCode;
487}
488
Thu Nguyen51d66b52024-08-06 09:15:55 +0000489exec::task<int> PlatformManager::setEventReceiver(
490 pldm_tid_t tid, pldm_event_message_global_enable eventMessageGlobalEnable,
491 pldm_transport_protocol_type protocolType, uint16_t heartbeatTimer)
492{
Manojkiran Edae188b912024-10-08 09:01:32 +0530493 size_t requestBytes = PLDM_SET_EVENT_RECEIVER_REQ_BYTES;
Thu Nguyen51d66b52024-08-06 09:15:55 +0000494 /**
495 * Ignore heartbeatTimer bytes when eventMessageGlobalEnable is not
496 * ENABLE_ASYNC_KEEP_ALIVE
497 */
498 if (eventMessageGlobalEnable !=
499 PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE)
500 {
501 requestBytes = requestBytes - sizeof(heartbeatTimer);
502 }
503 Request request(sizeof(pldm_msg_hdr) + requestBytes);
504 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
505 auto rc = encode_set_event_receiver_req(
506 0, eventMessageGlobalEnable, protocolType,
507 terminusManager.getLocalEid(), heartbeatTimer, requestMsg);
508 if (rc)
509 {
510 lg2::error(
511 "Failed to encode request SetEventReceiver for terminus ID {TID}, error {RC} ",
512 "TID", tid, "RC", rc);
513 co_return rc;
514 }
515
516 const pldm_msg* responseMsg = nullptr;
517 size_t responseLen = 0;
518 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
519 &responseLen);
520 if (rc)
521 {
522 lg2::error(
523 "Failed to send SetEventReceiver message for terminus {TID}, error {RC}",
524 "TID", tid, "RC", rc);
525 co_return rc;
526 }
527
528 uint8_t completionCode;
529 rc = decode_set_event_receiver_resp(responseMsg, responseLen,
530 &completionCode);
531 if (rc)
532 {
533 lg2::error(
534 "Failed to decode response SetEventReceiver for terminus ID {TID}, error {RC} ",
535 "TID", tid, "RC", rc);
536 co_return rc;
537 }
538
539 if (completionCode != PLDM_SUCCESS)
540 {
541 lg2::error(
542 "Error : SetEventReceiver for terminus ID {TID}, complete code {CC}.",
543 "TID", tid, "CC", completionCode);
544 co_return completionCode;
545 }
546
547 co_return completionCode;
548}
549
550exec::task<int> PlatformManager::eventMessageSupported(
551 pldm_tid_t tid, uint8_t formatVersion, uint8_t& synchronyConfiguration,
552 bitfield8_t& synchronyConfigurationSupported,
553 uint8_t& numberEventClassReturned, std::vector<uint8_t>& eventClass)
554{
555 Request request(
556 sizeof(pldm_msg_hdr) + PLDM_EVENT_MESSAGE_SUPPORTED_REQ_BYTES);
557 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
558 auto rc = encode_event_message_supported_req(0, formatVersion, requestMsg);
559 if (rc)
560 {
561 lg2::error(
562 "Failed to encode request EventMessageSupported for terminus ID {TID}, error {RC} ",
563 "TID", tid, "RC", rc);
564 co_return rc;
565 }
566
567 const pldm_msg* responseMsg = nullptr;
568 size_t responseLen = 0;
569 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
570 &responseLen);
571 if (rc)
572 {
573 lg2::error(
574 "Failed to send EventMessageSupported message for terminus {TID}, error {RC}",
575 "TID", tid, "RC", rc);
576 co_return rc;
577 }
578
579 uint8_t completionCode = 0;
580 uint8_t eventClassCount = static_cast<uint8_t>(responseLen) -
581 PLDM_EVENT_MESSAGE_SUPPORTED_MIN_RESP_BYTES;
582 eventClass.resize(eventClassCount);
583
584 rc = decode_event_message_supported_resp(
585 responseMsg, responseLen, &completionCode, &synchronyConfiguration,
586 &synchronyConfigurationSupported, &numberEventClassReturned,
587 eventClass.data(), eventClassCount);
588 if (rc)
589 {
590 lg2::error(
591 "Failed to decode response EventMessageSupported for terminus ID {TID}, error {RC} ",
592 "TID", tid, "RC", rc);
593 co_return rc;
594 }
595
596 if (completionCode != PLDM_SUCCESS)
597 {
598 lg2::error(
599 "Error : EventMessageSupported for terminus ID {TID}, complete code {CC}.",
600 "TID", tid, "CC", completionCode);
601 co_return completionCode;
602 }
603
604 co_return completionCode;
605}
Dung Caob6d39432024-06-05 03:46:47 +0000606
Patrick Williams366507c2025-02-03 14:28:01 -0500607exec::task<int> PlatformManager::getFRURecordTableMetadata(pldm_tid_t tid,
608 uint16_t* total)
Dung Caob6d39432024-06-05 03:46:47 +0000609{
610 Request request(
611 sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
612 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
613
614 auto rc = encode_get_fru_record_table_metadata_req(
615 0, requestMsg, PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
616 if (rc)
617 {
618 lg2::error(
619 "Failed to encode request GetFRURecordTableMetadata for terminus ID {TID}, error {RC} ",
620 "TID", tid, "RC", rc);
621 co_return rc;
622 }
623
624 const pldm_msg* responseMsg = nullptr;
625 size_t responseLen = 0;
626
627 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
628 &responseLen);
629 if (rc)
630 {
631 lg2::error(
632 "Failed to send GetFRURecordTableMetadata message for terminus {TID}, error {RC}",
633 "TID", tid, "RC", rc);
634 co_return rc;
635 }
636
637 uint8_t completionCode = 0;
638 if (responseMsg == nullptr || !responseLen)
639 {
640 lg2::error(
641 "No response data for GetFRURecordTableMetadata for terminus {TID}",
642 "TID", tid);
643 co_return rc;
644 }
645
646 uint8_t fru_data_major_version, fru_data_minor_version;
647 uint32_t fru_table_maximum_size, fru_table_length;
648 uint16_t total_record_set_identifiers;
649 uint32_t checksum;
650 rc = decode_get_fru_record_table_metadata_resp(
651 responseMsg, responseLen, &completionCode, &fru_data_major_version,
652 &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
653 &total_record_set_identifiers, total, &checksum);
654
655 if (rc)
656 {
657 lg2::error(
658 "Failed to decode response GetFRURecordTableMetadata for terminus ID {TID}, error {RC} ",
659 "TID", tid, "RC", rc);
660 co_return rc;
661 }
662
663 if (completionCode != PLDM_SUCCESS)
664 {
665 lg2::error(
666 "Error : GetFRURecordTableMetadata for terminus ID {TID}, complete code {CC}.",
667 "TID", tid, "CC", completionCode);
668 co_return rc;
669 }
670
671 co_return rc;
672}
673
674exec::task<int> PlatformManager::getFRURecordTable(
675 pldm_tid_t tid, const uint32_t dataTransferHndl,
676 const uint8_t transferOpFlag, uint32_t* nextDataTransferHndl,
677 uint8_t* transferFlag, size_t* responseCnt,
678 std::vector<uint8_t>& recordData)
679{
680 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES);
681 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
682
683 auto rc = encode_get_fru_record_table_req(
684 0, dataTransferHndl, transferOpFlag, requestMsg,
685 PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES);
686 if (rc != PLDM_SUCCESS)
687 {
688 lg2::error(
689 "Failed to encode request GetFRURecordTable for terminus ID {TID}, error {RC} ",
690 "TID", tid, "RC", rc);
691 co_return rc;
692 }
693
694 const pldm_msg* responseMsg = nullptr;
695 size_t responseLen = 0;
696
697 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
698 &responseLen);
699 if (rc)
700 {
701 lg2::error(
702 "Failed to send GetFRURecordTable message for terminus {TID}, error {RC}",
703 "TID", tid, "RC", rc);
704 co_return rc;
705 }
706
707 uint8_t completionCode = 0;
708 if (responseMsg == nullptr || !responseLen)
709 {
710 lg2::error("No response data for GetFRURecordTable for terminus {TID}",
711 "TID", tid);
712 co_return rc;
713 }
714
715 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(responseMsg);
716 rc = decode_get_fru_record_table_resp(
717 responsePtr, responseLen - sizeof(pldm_msg_hdr), &completionCode,
718 nextDataTransferHndl, transferFlag, recordData.data(), responseCnt);
719
720 if (rc)
721 {
722 lg2::error(
723 "Failed to decode response GetFRURecordTable for terminus ID {TID}, error {RC} ",
724 "TID", tid, "RC", rc);
725 co_return rc;
726 }
727
728 if (completionCode != PLDM_SUCCESS)
729 {
730 lg2::error(
731 "Error : GetFRURecordTable for terminus ID {TID}, complete code {CC}.",
732 "TID", tid, "CC", completionCode);
733 co_return rc;
734 }
735
736 co_return rc;
737}
738
739void PlatformManager::updateInventoryWithFru(
740 pldm_tid_t tid, const uint8_t* fruData, const size_t fruLen)
741{
742 if (tid == PLDM_TID_RESERVED || !termini.contains(tid) || !termini[tid])
743 {
744 lg2::error("Invalid terminus {TID}", "TID", tid);
745 return;
746 }
747
748 termini[tid]->updateInventoryWithFru(fruData, fruLen);
749}
750
751exec::task<int> PlatformManager::getFRURecordTables(
752 pldm_tid_t tid, const uint16_t& totalTableRecords,
753 std::vector<uint8_t>& fruData)
754{
755 if (!totalTableRecords)
756 {
757 lg2::info("Fru record table has 0 records");
758 co_return PLDM_ERROR;
759 }
760
761 uint32_t dataTransferHndl = 0;
762 uint32_t nextDataTransferHndl = 0;
763 uint8_t transferFlag = 0;
764 uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
765 size_t responseCnt = 0;
766 std::vector<uint8_t> recvBuf(PLDM_PLATFORM_GETPDR_MAX_RECORD_BYTES);
767
768 size_t fruLength = 0;
769 std::vector<uint8_t> receivedFru(0);
770 do
771 {
772 auto rc = co_await getFRURecordTable(
773 tid, dataTransferHndl, transferOpFlag, &nextDataTransferHndl,
774 &transferFlag, &responseCnt, recvBuf);
775
776 if (rc)
777 {
778 lg2::error(
779 "Failed to get Fru Record Data for terminus {TID}, error: {RC}, first part of data handle {RECORD}",
780 "TID", tid, "RC", rc, "RECORD", dataTransferHndl);
781 co_return rc;
782 }
783
784 receivedFru.insert(receivedFru.end(), recvBuf.begin(),
785 recvBuf.begin() + responseCnt);
786 fruLength += responseCnt;
787 if (transferFlag == PLDM_PLATFORM_TRANSFER_START_AND_END ||
788 transferFlag == PLDM_PLATFORM_TRANSFER_END)
789 {
790 break;
791 }
792
793 // multipart transfer
794 dataTransferHndl = nextDataTransferHndl;
795 transferOpFlag = PLDM_GET_NEXTPART;
796
797 } while (nextDataTransferHndl != 0);
798
799 if (fruLength != receivedFru.size())
800 {
801 lg2::error(
802 "Size of Fru Record Data {SIZE} for terminus {TID} is different the responded size {RSPSIZE}.",
803 "SIZE", receivedFru.size(), "RSPSIZE", fruLength);
804 co_return PLDM_ERROR_INVALID_LENGTH;
805 }
806
807 fruData = receivedFru;
808
809 co_return PLDM_SUCCESS;
810}
811
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000812} // namespace platform_mc
813} // namespace pldm