blob: f6ffcc5bb6626b189e2090e42f1793c7a4d80d94 [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 }
24 terminus->initialized = true;
Gilbert Chende2a1322022-05-24 15:35:21 +010025
26 if (terminus->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR))
27 {
28 auto rc = co_await getPDRs(terminus);
29 if (rc)
30 {
31 lg2::error(
32 "Failed to fetch PDRs for terminus with TID: {TID}, error: {ERROR}",
33 "TID", tid, "ERROR", rc);
34 continue; // Continue to next terminus
35 }
36
37 terminus->parseTerminusPDRs();
38 }
Gilbert Chen6c7fed42022-02-22 15:40:17 +000039 }
40 co_return PLDM_SUCCESS;
41}
42
Gilbert Chende2a1322022-05-24 15:35:21 +010043exec::task<int> PlatformManager::getPDRs(std::shared_ptr<Terminus> terminus)
44{
45 pldm_tid_t tid = terminus->getTid();
46
47 /* Setting default values when getPDRRepositoryInfo fails or does not
48 * support */
49 uint8_t repositoryState = PLDM_AVAILABLE;
50 uint32_t recordCount = std::numeric_limits<uint32_t>::max();
51 uint32_t repositorySize = 0;
52 uint32_t largestRecordSize = std::numeric_limits<uint32_t>::max();
53 if (terminus->doesSupportCommand(PLDM_PLATFORM,
54 PLDM_GET_PDR_REPOSITORY_INFO))
55 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -040056 auto rc =
57 co_await getPDRRepositoryInfo(tid, repositoryState, recordCount,
58 repositorySize, largestRecordSize);
Gilbert Chende2a1322022-05-24 15:35:21 +010059 if (rc)
60 {
61 lg2::error(
62 "Failed to get PDR Repository Info for terminus with TID: {TID}, error: {ERROR}",
63 "TID", tid, "ERROR", rc);
64 }
65 else
66 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -040067 recordCount =
68 std::min(recordCount + 1, std::numeric_limits<uint32_t>::max());
Gilbert Chende2a1322022-05-24 15:35:21 +010069 largestRecordSize = std::min(largestRecordSize + 1,
70 std::numeric_limits<uint32_t>::max());
71 }
72 }
73
74 if (repositoryState != PLDM_AVAILABLE)
75 {
76 co_return PLDM_ERROR_NOT_READY;
77 }
78
79 uint32_t recordHndl = 0;
80 uint32_t nextRecordHndl = 0;
81 uint32_t nextDataTransferHndl = 0;
82 uint8_t transferFlag = 0;
83 uint16_t responseCnt = 0;
84 constexpr uint16_t recvBufSize = PLDM_PLATFORM_GETPDR_MAX_RECORD_BYTES;
85 std::vector<uint8_t> recvBuf(recvBufSize);
86 uint8_t transferCrc = 0;
87
88 terminus->pdrs.clear();
89 uint32_t receivedRecordCount = 0;
90
91 do
92 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -040093 auto rc =
94 co_await getPDR(tid, recordHndl, 0, PLDM_GET_FIRSTPART, recvBufSize,
95 0, nextRecordHndl, nextDataTransferHndl,
96 transferFlag, responseCnt, recvBuf, transferCrc);
Gilbert Chende2a1322022-05-24 15:35:21 +010097
98 if (rc)
99 {
100 lg2::error(
101 "Failed to get PDRs for terminus {TID}, error: {RC}, first part of record handle {RECORD}",
102 "TID", tid, "RC", rc, "RECORD", recordHndl);
103 terminus->pdrs.clear();
104 co_return rc;
105 }
106
107 if (transferFlag == PLDM_PLATFORM_TRANSFER_START_AND_END)
108 {
109 // single-part
110 terminus->pdrs.emplace_back(std::vector<uint8_t>(
111 recvBuf.begin(), recvBuf.begin() + responseCnt));
112 recordHndl = nextRecordHndl;
113 }
114 else
115 {
116 // multipart transfer
117 uint32_t receivedRecordSize = responseCnt;
118 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(recvBuf.data());
119 uint16_t recordChgNum = le16toh(pdrHdr->record_change_num);
120 std::vector<uint8_t> receivedPdr(recvBuf.begin(),
121 recvBuf.begin() + responseCnt);
122 do
123 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400124 rc = co_await getPDR(
125 tid, recordHndl, nextDataTransferHndl, PLDM_GET_NEXTPART,
126 recvBufSize, recordChgNum, nextRecordHndl,
127 nextDataTransferHndl, transferFlag, responseCnt, recvBuf,
128 transferCrc);
Gilbert Chende2a1322022-05-24 15:35:21 +0100129 if (rc)
130 {
131 lg2::error(
132 "Failed to get PDRs for terminus {TID}, error: {RC}, get middle part of record handle {RECORD}",
133 "TID", tid, "RC", rc, "RECORD", recordHndl);
134 terminus->pdrs.clear();
135 co_return rc;
136 }
137
138 receivedPdr.insert(receivedPdr.end(), recvBuf.begin(),
139 recvBuf.begin() + responseCnt);
140 receivedRecordSize += responseCnt;
141
142 if (transferFlag == PLDM_PLATFORM_TRANSFER_END)
143 {
144 terminus->pdrs.emplace_back(std::move(receivedPdr));
145 recordHndl = nextRecordHndl;
146 }
147 } while (nextDataTransferHndl != 0 &&
148 receivedRecordSize < largestRecordSize);
149 }
150 receivedRecordCount++;
151 } while (nextRecordHndl != 0 && receivedRecordCount < recordCount);
152
153 co_return PLDM_SUCCESS;
154}
155
156exec::task<int> PlatformManager::getPDR(
157 const pldm_tid_t tid, const uint32_t recordHndl,
158 const uint32_t dataTransferHndl, const uint8_t transferOpFlag,
159 const uint16_t requestCnt, const uint16_t recordChgNum,
160 uint32_t& nextRecordHndl, uint32_t& nextDataTransferHndl,
161 uint8_t& transferFlag, uint16_t& responseCnt,
162 std::vector<uint8_t>& recordData, uint8_t& transferCrc)
163{
164 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES);
165 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
166 auto rc = encode_get_pdr_req(0, recordHndl, dataTransferHndl,
167 transferOpFlag, requestCnt, recordChgNum,
168 requestMsg, PLDM_GET_PDR_REQ_BYTES);
169 if (rc)
170 {
171 lg2::error(
172 "Failed to encode request GetPDR for terminus ID {TID}, error {RC} ",
173 "TID", tid, "RC", rc);
174 co_return rc;
175 }
176
177 const pldm_msg* responseMsg = nullptr;
178 size_t responseLen = 0;
179 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
180 &responseLen);
181 if (rc)
182 {
183 lg2::error(
184 "Failed to send GetPDR message for terminus {TID}, error {RC}",
185 "TID", tid, "RC", rc);
186 co_return rc;
187 }
188
189 uint8_t completionCode;
190 rc = decode_get_pdr_resp(responseMsg, responseLen, &completionCode,
191 &nextRecordHndl, &nextDataTransferHndl,
192 &transferFlag, &responseCnt, recordData.data(),
193 recordData.size(), &transferCrc);
194 if (rc)
195 {
196 lg2::error(
197 "Failed to decode response GetPDR for terminus ID {TID}, error {RC} ",
198 "TID", tid, "RC", rc);
199 co_return rc;
200 }
201
202 if (completionCode != PLDM_SUCCESS)
203 {
204 lg2::error("Error : GetPDR for terminus ID {TID}, complete code {CC}.",
205 "TID", tid, "CC", completionCode);
206 co_return rc;
207 }
208
209 co_return completionCode;
210}
211
212exec::task<int> PlatformManager::getPDRRepositoryInfo(
213 const pldm_tid_t tid, uint8_t& repositoryState, uint32_t& recordCount,
214 uint32_t& repositorySize, uint32_t& largestRecordSize)
215{
216 Request request(sizeof(pldm_msg_hdr) + sizeof(uint8_t));
217 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
218 auto rc = encode_pldm_header_only(PLDM_REQUEST, 0, PLDM_PLATFORM,
219 PLDM_GET_PDR_REPOSITORY_INFO, requestMsg);
220 if (rc)
221 {
222 lg2::error(
223 "Failed to encode request GetPDRRepositoryInfo for terminus ID {TID}, error {RC} ",
224 "TID", tid, "RC", rc);
225 co_return rc;
226 }
227
228 const pldm_msg* responseMsg = nullptr;
229 size_t responseLen = 0;
230 rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
231 &responseLen);
232 if (rc)
233 {
234 lg2::error(
235 "Failed to send GetPDRRepositoryInfo message for terminus {TID}, error {RC}",
236 "TID", tid, "RC", rc);
237 co_return rc;
238 }
239
240 uint8_t completionCode = 0;
241 std::array<uint8_t, PLDM_TIMESTAMP104_SIZE> updateTime = {};
242 std::array<uint8_t, PLDM_TIMESTAMP104_SIZE> oemUpdateTime = {};
243 uint8_t dataTransferHandleTimeout = 0;
244
245 rc = decode_get_pdr_repository_info_resp(
246 responseMsg, responseLen, &completionCode, &repositoryState,
247 updateTime.data(), oemUpdateTime.data(), &recordCount, &repositorySize,
248 &largestRecordSize, &dataTransferHandleTimeout);
249 if (rc)
250 {
251 lg2::error(
252 "Failed to decode response GetPDRRepositoryInfo for terminus ID {TID}, error {RC} ",
253 "TID", tid, "RC", rc);
254 co_return rc;
255 }
256
257 if (completionCode != PLDM_SUCCESS)
258 {
259 lg2::error(
260 "Error : GetPDRRepositoryInfo for terminus ID {TID}, complete code {CC}.",
261 "TID", tid, "CC", completionCode);
262 co_return rc;
263 }
264
265 co_return completionCode;
266}
267
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000268} // namespace platform_mc
269} // namespace pldm