blob: 7ca3e2bbdccdcbcf4d3456de0f8eb66d66dfaf4d [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jefferyd861a682024-06-03 21:43:09 +09302#include "api.h"
3#include "dsp/base.h"
Dung Cao88367842024-10-16 06:32:49 +00004#include "msgbuf.h"
Andrew Jefferyd861a682024-06-03 21:43:09 +09305
6#include <assert.h>
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10307#include <libpldm/base.h>
8#include <libpldm/pldm_types.h>
9
Manojkiran Eda9a8e4972022-11-28 16:38:21 +053010#include <endian.h>
Andrew Jefferyd861a682024-06-03 21:43:09 +093011#include <errno.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +053012#include <stdint.h>
13#include <string.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093014
Andrew Jefferyd861a682024-06-03 21:43:09 +093015int pack_pldm_header_errno(const struct pldm_header_info *hdr,
16 struct pldm_msg_hdr *msg)
Andrew Jeffery9c766792022-08-10 23:12:49 +093017{
18 if (msg == NULL || hdr == NULL) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093019 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093020 }
21
22 if (hdr->msg_type != PLDM_RESPONSE && hdr->msg_type != PLDM_REQUEST &&
23 hdr->msg_type != PLDM_ASYNC_REQUEST_NOTIFY) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093024 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093025 }
26
27 if (hdr->instance > PLDM_INSTANCE_MAX) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093028 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093029 }
30
31 if (hdr->pldm_type > (PLDM_MAX_TYPES - 1)) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093032 return -ENOMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +093033 }
34
35 uint8_t datagram = (hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) ? 1 : 0;
36
37 if (hdr->msg_type == PLDM_RESPONSE) {
38 msg->request = PLDM_RESPONSE;
39 } else if (hdr->msg_type == PLDM_REQUEST ||
40 hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) {
41 msg->request = PLDM_REQUEST;
42 }
43 msg->datagram = datagram;
44 msg->reserved = 0;
45 msg->instance_id = hdr->instance;
46 msg->header_ver = PLDM_CURRENT_VERSION;
47 msg->type = hdr->pldm_type;
48 msg->command = hdr->command;
49
Andrew Jefferyd861a682024-06-03 21:43:09 +093050 return 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +093051}
52
Andrew Jefferyd861a682024-06-03 21:43:09 +093053int unpack_pldm_header_errno(const struct pldm_msg_hdr *msg,
54 struct pldm_header_info *hdr)
Andrew Jeffery9c766792022-08-10 23:12:49 +093055{
56 if (msg == NULL) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093057 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093058 }
59
60 if (msg->request == PLDM_RESPONSE) {
61 hdr->msg_type = PLDM_RESPONSE;
62 } else {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093063 hdr->msg_type = msg->datagram ? PLDM_ASYNC_REQUEST_NOTIFY :
64 PLDM_REQUEST;
Andrew Jeffery9c766792022-08-10 23:12:49 +093065 }
66
67 hdr->instance = msg->instance_id;
68 hdr->pldm_type = msg->type;
69 hdr->command = msg->command;
70
Andrew Jefferyd861a682024-06-03 21:43:09 +093071 return 0;
72}
73
74LIBPLDM_ABI_STABLE
75uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
76 struct pldm_msg_hdr *msg)
77{
78 enum pldm_completion_codes cc;
79 int rc;
80
81 rc = pack_pldm_header_errno(hdr, msg);
82 if (!rc) {
83 return PLDM_SUCCESS;
84 }
85
86 cc = pldm_xlate_errno(rc);
87 assert(cc < UINT8_MAX);
88 if (cc > UINT8_MAX) {
89 static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error");
90 return PLDM_ERROR;
91 }
92
93 return cc;
94}
95
96LIBPLDM_ABI_STABLE
97uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg,
98 struct pldm_header_info *hdr)
99{
100 enum pldm_completion_codes cc;
101 int rc;
102
103 rc = unpack_pldm_header_errno(msg, hdr);
104 if (!rc) {
105 return PLDM_SUCCESS;
106 }
107
108 cc = pldm_xlate_errno(rc);
109 assert(cc < UINT8_MAX);
110 if (cc > UINT8_MAX) {
111 static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error");
112 return PLDM_ERROR;
113 }
114
115 return cc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930116}
117
Andrew Jeffery5239d9a2023-10-16 10:51:53 +1030118LIBPLDM_ABI_STABLE
Andrew Jeffery91c06e92023-09-22 15:22:54 +0930119bool pldm_msg_hdr_correlate_response(const struct pldm_msg_hdr *req,
120 const struct pldm_msg_hdr *resp)
121{
122 return req->instance_id == resp->instance_id && req->request &&
123 !resp->request && req->type == resp->type &&
124 req->command == resp->command;
125}
126
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930127LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930128int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg)
129{
130 if (msg == NULL) {
131 return PLDM_ERROR_INVALID_DATA;
132 }
133
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930134 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930135 header.instance = instance_id;
136 header.msg_type = PLDM_REQUEST;
137 header.command = PLDM_GET_PLDM_TYPES;
138
139 return pack_pldm_header(&header, &(msg->hdr));
140}
141
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930142LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930143int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
144 struct pldm_msg *msg)
145{
146 if (msg == NULL) {
147 return PLDM_ERROR_INVALID_DATA;
148 }
149
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930150 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930151 header.instance = instance_id;
152 header.msg_type = PLDM_REQUEST;
153 header.command = PLDM_GET_PLDM_COMMANDS;
154
155 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
156 if (rc != PLDM_SUCCESS) {
157 return rc;
158 }
159
160 struct pldm_get_commands_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930161 (struct pldm_get_commands_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930162
163 request->type = type;
164 request->version = version;
165
166 return PLDM_SUCCESS;
167}
168
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930169LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930170int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
171 const bitfield8_t *types, struct pldm_msg *msg)
172{
173 if (msg == NULL) {
174 return PLDM_ERROR_INVALID_DATA;
175 }
176
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930177 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930178 header.instance = instance_id;
179 header.msg_type = PLDM_RESPONSE;
180 header.command = PLDM_GET_PLDM_TYPES;
181
182 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
183 if (rc != PLDM_SUCCESS) {
184 return rc;
185 }
186
187 struct pldm_get_types_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930188 (struct pldm_get_types_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930189 response->completion_code = completion_code;
190 if (response->completion_code == PLDM_SUCCESS) {
191 if (types == NULL) {
192 return PLDM_ERROR_INVALID_DATA;
193 }
194 memcpy(response->types, &(types->byte), PLDM_MAX_TYPES / 8);
195 }
196
197 return PLDM_SUCCESS;
198}
199
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930200LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930201int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
202 uint8_t *type, ver32_t *version)
203{
204 if (msg == NULL || type == NULL || version == NULL) {
205 return PLDM_ERROR_INVALID_DATA;
206 }
207
208 if (payload_length != PLDM_GET_COMMANDS_REQ_BYTES) {
209 return PLDM_ERROR_INVALID_LENGTH;
210 }
211
212 struct pldm_get_commands_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930213 (struct pldm_get_commands_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930214 *type = request->type;
215 *version = request->version;
216 return PLDM_SUCCESS;
217}
218
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930219LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930220int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
221 const bitfield8_t *commands, struct pldm_msg *msg)
222{
223 if (msg == NULL) {
224 return PLDM_ERROR_INVALID_DATA;
225 }
226
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930227 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930228 header.instance = instance_id;
229 header.msg_type = PLDM_RESPONSE;
230 header.command = PLDM_GET_PLDM_COMMANDS;
231 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
232 if (rc != PLDM_SUCCESS) {
233 return rc;
234 }
235
236 struct pldm_get_commands_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930237 (struct pldm_get_commands_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930238 response->completion_code = completion_code;
239 if (response->completion_code == PLDM_SUCCESS) {
240 if (commands == NULL) {
241 return PLDM_ERROR_INVALID_DATA;
242 }
243 memcpy(response->commands, &(commands->byte),
244 PLDM_MAX_CMDS_PER_TYPE / 8);
245 }
246
247 return PLDM_SUCCESS;
248}
249
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930250LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930251int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
252 uint8_t *completion_code, bitfield8_t *types)
253{
254 if (msg == NULL || types == NULL || completion_code == NULL) {
255 return PLDM_ERROR_INVALID_DATA;
256 }
257
258 *completion_code = msg->payload[0];
259 if (PLDM_SUCCESS != *completion_code) {
260 return PLDM_SUCCESS;
261 }
262
263 if (payload_length != PLDM_GET_TYPES_RESP_BYTES) {
264 return PLDM_ERROR_INVALID_LENGTH;
265 }
266
267 struct pldm_get_types_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930268 (struct pldm_get_types_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930269
270 memcpy(&(types->byte), response->types, PLDM_MAX_TYPES / 8);
271
272 return PLDM_SUCCESS;
273}
274
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930275LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930276int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
277 uint8_t *completion_code, bitfield8_t *commands)
278{
279 if (msg == NULL || commands == NULL || completion_code == NULL) {
280 return PLDM_ERROR_INVALID_DATA;
281 }
282
283 *completion_code = msg->payload[0];
284 if (PLDM_SUCCESS != *completion_code) {
285 return PLDM_SUCCESS;
286 }
287
288 if (payload_length != PLDM_GET_COMMANDS_RESP_BYTES) {
289 return PLDM_ERROR_INVALID_LENGTH;
290 }
291
292 struct pldm_get_commands_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930293 (struct pldm_get_commands_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930294
295 memcpy(&(commands->byte), response->commands,
296 PLDM_MAX_CMDS_PER_TYPE / 8);
297
298 return PLDM_SUCCESS;
299}
300
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930301LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930302int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
303 uint8_t transfer_opflag, uint8_t type,
304 struct pldm_msg *msg)
305{
306 if (NULL == msg) {
307 return PLDM_ERROR_INVALID_DATA;
308 }
309
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930310 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930311 header.msg_type = PLDM_REQUEST;
312 header.instance = instance_id;
313 header.pldm_type = PLDM_BASE;
314 header.command = PLDM_GET_PLDM_VERSION;
315
316 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
317 if (rc != PLDM_SUCCESS) {
318 return rc;
319 }
320
321 struct pldm_get_version_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930322 (struct pldm_get_version_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930323 transfer_handle = htole32(transfer_handle);
324 request->transfer_handle = transfer_handle;
325 request->transfer_opflag = transfer_opflag;
326 request->type = type;
327
328 return PLDM_SUCCESS;
329}
330
Andrew Jeffery36324f62024-09-25 13:41:41 +0930331LIBPLDM_ABI_DEPRECATED_UNSAFE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930332int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
333 uint32_t next_transfer_handle,
334 uint8_t transfer_flag, const ver32_t *version_data,
335 size_t version_size, struct pldm_msg *msg)
336{
Andrew Jeffery36324f62024-09-25 13:41:41 +0930337 if (NULL == msg || NULL == version_data) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930338 return PLDM_ERROR_INVALID_DATA;
339 }
340
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930341 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930342 header.msg_type = PLDM_RESPONSE;
343 header.instance = instance_id;
344 header.pldm_type = PLDM_BASE;
345 header.command = PLDM_GET_PLDM_VERSION;
346
347 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
348 if (rc != PLDM_SUCCESS) {
349 return rc;
350 }
351
352 struct pldm_get_version_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930353 (struct pldm_get_version_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930354 response->completion_code = completion_code;
355 if (response->completion_code == PLDM_SUCCESS) {
356 response->next_transfer_handle = htole32(next_transfer_handle);
357 response->transfer_flag = transfer_flag;
358 memcpy(response->version_data, (uint8_t *)version_data,
359 version_size);
360 }
361 return PLDM_SUCCESS;
362}
363
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930364LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930365int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
366 uint32_t *transfer_handle, uint8_t *transfer_opflag,
367 uint8_t *type)
368{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930369 if (payload_length != PLDM_GET_VERSION_REQ_BYTES) {
370 return PLDM_ERROR_INVALID_LENGTH;
371 }
372
373 struct pldm_get_version_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930374 (struct pldm_get_version_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930375 *transfer_handle = le32toh(request->transfer_handle);
376 *transfer_opflag = request->transfer_opflag;
377 *type = request->type;
378 return PLDM_SUCCESS;
379}
380
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930381LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930382int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
383 uint8_t *completion_code,
384 uint32_t *next_transfer_handle,
385 uint8_t *transfer_flag, ver32_t *version)
386{
387 if (msg == NULL || next_transfer_handle == NULL ||
388 transfer_flag == NULL || completion_code == NULL) {
389 return PLDM_ERROR_INVALID_DATA;
390 }
391
392 *completion_code = msg->payload[0];
393 if (PLDM_SUCCESS != *completion_code) {
394 return PLDM_SUCCESS;
395 }
396
397 if (payload_length < PLDM_GET_VERSION_RESP_BYTES) {
398 return PLDM_ERROR_INVALID_LENGTH;
399 }
400
401 struct pldm_get_version_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930402 (struct pldm_get_version_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930403
404 *next_transfer_handle = le32toh(response->next_transfer_handle);
405 *transfer_flag = response->transfer_flag;
406 memcpy(version, (uint8_t *)response->version_data, sizeof(ver32_t));
407
408 return PLDM_SUCCESS;
409}
410
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930411LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930412int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg)
413{
414 if (msg == NULL) {
415 return PLDM_ERROR_INVALID_DATA;
416 }
417
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930418 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930419 header.instance = instance_id;
420 header.msg_type = PLDM_REQUEST;
421 header.command = PLDM_GET_TID;
422
423 return pack_pldm_header(&header, &(msg->hdr));
424}
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930425
426LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
428 uint8_t tid, struct pldm_msg *msg)
429{
430 if (msg == NULL) {
431 return PLDM_ERROR_INVALID_DATA;
432 }
433
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930434 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930435 header.instance = instance_id;
436 header.msg_type = PLDM_RESPONSE;
437 header.command = PLDM_GET_TID;
438
439 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
440 if (rc != PLDM_SUCCESS) {
441 return rc;
442 }
443
444 struct pldm_get_tid_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930445 (struct pldm_get_tid_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930446 response->completion_code = completion_code;
447 response->tid = tid;
448
449 return PLDM_SUCCESS;
450}
451
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930452LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930453int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
454 uint8_t *completion_code, uint8_t *tid)
455{
456 if (msg == NULL || tid == NULL || completion_code == NULL) {
457 return PLDM_ERROR_INVALID_DATA;
458 }
459
460 *completion_code = msg->payload[0];
461 if (PLDM_SUCCESS != *completion_code) {
462 return PLDM_SUCCESS;
463 }
464
465 if (payload_length != PLDM_GET_TID_RESP_BYTES) {
466 return PLDM_ERROR_INVALID_LENGTH;
467 }
468
469 struct pldm_get_tid_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930470 (struct pldm_get_tid_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930471
472 *tid = response->tid;
473
474 return PLDM_SUCCESS;
475}
476
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930477LIBPLDM_ABI_STABLE
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800478int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg)
479{
480 if (msg == NULL) {
481 return PLDM_ERROR_INVALID_DATA;
482 }
483
484 if (tid == 0x0 || tid == 0xff) {
485 return PLDM_ERROR_INVALID_DATA;
486 }
487
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930488 struct pldm_header_info header = { 0 };
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800489 header.instance = instance_id;
490 header.msg_type = PLDM_REQUEST;
491 header.command = PLDM_SET_TID;
492
493 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
494 if (rc != PLDM_SUCCESS) {
495 return rc;
496 }
497
498 struct pldm_set_tid_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930499 (struct pldm_set_tid_req *)msg->payload;
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800500 request->tid = tid;
501
502 return PLDM_SUCCESS;
503}
504
Vishnu Santhoshec19cbc2025-05-30 16:34:28 +0530505LIBPLDM_ABI_TESTING
506int decode_set_tid_req(const struct pldm_msg *msg, size_t payload_length,
507 uint8_t *tid)
508{
509 PLDM_MSGBUF_DEFINE_P(buf);
510 int rc;
511
512 if (!msg || !tid) {
513 return -EINVAL;
514 }
515
516 rc = pldm_msgbuf_init_errno(buf, PLDM_SET_TID_REQ_BYTES, msg->payload,
517 payload_length);
518 if (rc) {
519 return rc;
520 }
521
522 pldm_msgbuf_extract_p(buf, tid);
523
524 return pldm_msgbuf_complete_consumed(buf);
525}
526
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930527LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930528int decode_multipart_receive_req(const struct pldm_msg *msg,
529 size_t payload_length, uint8_t *pldm_type,
530 uint8_t *transfer_opflag,
531 uint32_t *transfer_ctx,
532 uint32_t *transfer_handle,
533 uint32_t *section_offset,
534 uint32_t *section_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930535{
Andrew Jefferyedb88262025-08-14 05:02:21 +0000536 PLDM_MSGBUF_DEFINE_P(buf);
537 int rc;
538
Andrew Jeffery9c766792022-08-10 23:12:49 +0930539 if (msg == NULL || pldm_type == NULL || transfer_opflag == NULL ||
540 transfer_ctx == NULL || transfer_handle == NULL ||
541 section_offset == NULL || section_length == NULL) {
542 return PLDM_ERROR_INVALID_DATA;
543 }
544
Andrew Jefferyedb88262025-08-14 05:02:21 +0000545 rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
546 msg->payload, payload_length);
547 if (rc) {
548 return pldm_xlate_errno(rc);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930549 }
550
Andrew Jefferyedb88262025-08-14 05:02:21 +0000551 pldm_msgbuf_extract_p(buf, pldm_type);
552 pldm_msgbuf_extract_p(buf, transfer_opflag);
553 pldm_msgbuf_extract_p(buf, transfer_ctx);
554 pldm_msgbuf_extract_p(buf, transfer_handle);
555 pldm_msgbuf_extract_p(buf, section_offset);
556 pldm_msgbuf_extract_p(buf, section_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930557
Andrew Jefferyedb88262025-08-14 05:02:21 +0000558 rc = pldm_msgbuf_complete_consumed(buf);
559 if (rc) {
560 return pldm_xlate_errno(rc);
561 }
562
563 if (*pldm_type != PLDM_BASE && *pldm_type != PLDM_FILE) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930564 return PLDM_ERROR_INVALID_PLDM_TYPE;
565 }
566
567 // Any enum value above PLDM_XFER_CURRENT_PART is invalid.
Andrew Jefferyedb88262025-08-14 05:02:21 +0000568 if (*transfer_opflag > PLDM_XFER_CURRENT_PART) {
Manojkiran Eda309bbe82025-05-19 14:51:45 +0530569 return PLDM_ERROR_UNEXPECTED_TRANSFER_FLAG_OPERATION;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930570 }
571
572 // A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers.
Andrew Jefferyedb88262025-08-14 05:02:21 +0000573 if (*section_offset == 0 && (*transfer_opflag != PLDM_XFER_FIRST_PART &&
574 *transfer_opflag != PLDM_XFER_COMPLETE)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930575 return PLDM_ERROR_INVALID_DATA;
576 }
577
Andrew Jefferyedb88262025-08-14 05:02:21 +0000578 if (*transfer_handle == 0 && *transfer_opflag != PLDM_XFER_COMPLETE) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930579 return PLDM_ERROR_INVALID_DATA;
580 }
581
Andrew Jeffery9c766792022-08-10 23:12:49 +0930582 return PLDM_SUCCESS;
583}
584
Chau Ly26c8eb22025-07-30 06:56:33 +0000585LIBPLDM_ABI_STABLE
Chau Ly41846232025-08-13 04:43:27 +0000586int encode_pldm_base_multipart_receive_req(
587 uint8_t instance_id, const struct pldm_base_multipart_receive_req *req,
Chau Lye98a72f2025-08-15 03:38:50 +0000588 struct pldm_msg *msg, size_t *payload_length)
Dung Cao88367842024-10-16 06:32:49 +0000589{
590 PLDM_MSGBUF_DEFINE_P(buf);
591 int rc;
592
Chau Lye98a72f2025-08-15 03:38:50 +0000593 if (req == NULL || msg == NULL || payload_length == NULL) {
Dung Cao88367842024-10-16 06:32:49 +0000594 return -EINVAL;
595 }
596
597 struct pldm_header_info header = { 0 };
598 header.instance = instance_id;
599 header.msg_type = PLDM_REQUEST;
600 header.pldm_type = PLDM_BASE;
601 header.command = PLDM_MULTIPART_RECEIVE;
602
603 rc = pack_pldm_header_errno(&header, &msg->hdr);
604 if (rc) {
605 return rc;
606 }
607
608 rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
Chau Lye98a72f2025-08-15 03:38:50 +0000609 msg->payload, *payload_length);
Dung Cao88367842024-10-16 06:32:49 +0000610 if (rc) {
611 return rc;
612 }
613
614 pldm_msgbuf_insert(buf, req->pldm_type);
615 pldm_msgbuf_insert(buf, req->transfer_opflag);
616 pldm_msgbuf_insert(buf, req->transfer_ctx);
617 pldm_msgbuf_insert(buf, req->transfer_handle);
618 pldm_msgbuf_insert(buf, req->section_offset);
619 pldm_msgbuf_insert(buf, req->section_length);
620
Chau Lye98a72f2025-08-15 03:38:50 +0000621 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Dung Cao88367842024-10-16 06:32:49 +0000622}
623
Chau Ly26c8eb22025-07-30 06:56:33 +0000624LIBPLDM_ABI_STABLE
Chau Ly41846232025-08-13 04:43:27 +0000625int decode_pldm_base_multipart_receive_resp(
626 const struct pldm_msg *msg, size_t payload_length,
627 struct pldm_base_multipart_receive_resp *resp,
628 uint32_t *data_integrity_checksum)
Dung Cao88367842024-10-16 06:32:49 +0000629{
630 PLDM_MSGBUF_DEFINE_P(buf);
631 int rc;
632
633 if (msg == NULL || resp == NULL || data_integrity_checksum == NULL) {
634 return -EINVAL;
635 }
636
637 rc = pldm_msg_has_error(msg, payload_length);
638
639 if (rc) {
640 resp->completion_code = rc;
641 return 0;
642 }
643
644 rc = pldm_msgbuf_init_errno(buf,
645 PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES,
646 msg->payload, payload_length);
647 if (rc) {
648 return rc;
649 }
650
651 pldm_msgbuf_extract(buf, resp->completion_code);
652 rc = pldm_msgbuf_extract(buf, resp->transfer_flag);
653 if (rc) {
654 return pldm_msgbuf_discard(buf, rc);
655 }
656 pldm_msgbuf_extract(buf, resp->next_transfer_handle);
657
658 rc = pldm_msgbuf_extract_uint32_to_size(buf, resp->data.length);
659 if (rc) {
660 return pldm_msgbuf_discard(buf, rc);
661 }
662
663 if (resp->data.length > 0) {
664 resp->data.ptr = NULL;
665 pldm_msgbuf_span_required(buf, resp->data.length,
666 (void **)&resp->data.ptr);
667 }
668
669 if (resp->transfer_flag ==
670 PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_END ||
671 resp->transfer_flag ==
672 PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_START_AND_END) {
673 pldm_msgbuf_extract_p(buf, data_integrity_checksum);
674 }
675
676 return pldm_msgbuf_complete_consumed(buf);
677}
678
John Chung21a639d2025-07-17 18:48:19 -0500679LIBPLDM_ABI_TESTING
680int encode_base_multipart_receive_resp(
Chau Ly41846232025-08-13 04:43:27 +0000681 uint8_t instance_id,
682 const struct pldm_base_multipart_receive_resp *resp, uint32_t checksum,
683 struct pldm_msg *msg, size_t *payload_length)
John Chung21a639d2025-07-17 18:48:19 -0500684{
685 PLDM_MSGBUF_DEFINE_P(buf);
686 int rc;
687
688 if (!msg || !resp || !payload_length || !resp->data.ptr) {
689 return -EINVAL;
690 }
691
692 struct pldm_header_info header = { 0 };
693 header.instance = instance_id;
694 header.msg_type = PLDM_RESPONSE;
695 header.pldm_type = PLDM_BASE;
696 header.command = PLDM_MULTIPART_RECEIVE;
697
698 rc = pack_pldm_header_errno(&header, &msg->hdr);
699 if (rc) {
700 return rc;
701 }
702
703 rc = pldm_msgbuf_init_errno(buf,
704 PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES,
705 msg->payload, *payload_length);
706 if (rc) {
707 return rc;
708 }
709
710 pldm_msgbuf_insert(buf, resp->completion_code);
711 if (resp->completion_code != PLDM_SUCCESS) {
712 // Return without encoding the rest of the field
713 return pldm_msgbuf_complete_used(buf, *payload_length,
714 payload_length);
715 }
716
717 pldm_msgbuf_insert(buf, resp->transfer_flag);
718 pldm_msgbuf_insert(buf, resp->next_transfer_handle);
719
720 pldm_msgbuf_insert_uint32(buf, resp->data.length);
721 if (resp->data.length == 0) {
722 // Return without encoding data payload
723 return pldm_msgbuf_complete_used(buf, *payload_length,
724 payload_length);
725 }
726
727 rc = pldm_msgbuf_insert_array(buf, resp->data.length, resp->data.ptr,
728 resp->data.length);
729 if (rc) {
730 return pldm_msgbuf_discard(buf, rc);
731 }
732
733 if (resp->transfer_flag == PLDM_END ||
734 resp->transfer_flag == PLDM_START_AND_END) {
735 pldm_msgbuf_insert(buf, checksum);
736 }
737
738 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
739}
740
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930741LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930742int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
743 uint8_t cc, struct pldm_msg *msg)
744{
745 if (msg == NULL) {
746 return PLDM_ERROR_INVALID_DATA;
747 }
748
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930749 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930750 header.instance = instance_id;
751 header.msg_type = PLDM_RESPONSE;
752 header.pldm_type = type;
753 header.command = command;
754
755 uint8_t rc = pack_pldm_header(&header, &msg->hdr);
756 if (rc != PLDM_SUCCESS) {
757 return rc;
758 }
759
760 msg->payload[0] = cc;
761
762 return PLDM_SUCCESS;
763}
764
Unive Tieneb8bb172024-11-25 16:57:42 +0800765int encode_pldm_header_only_errno(uint8_t msg_type, uint8_t instance_id,
766 uint8_t pldm_type, uint8_t command,
767 struct pldm_msg *msg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930768{
769 if (msg == NULL) {
Unive Tieneb8bb172024-11-25 16:57:42 +0800770 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930771 }
772
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930773 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930774 header.msg_type = msg_type;
775 header.instance = instance_id;
776 header.pldm_type = pldm_type;
777 header.command = command;
Unive Tieneb8bb172024-11-25 16:57:42 +0800778 return pack_pldm_header_errno(&header, &(msg->hdr));
779}
780
781LIBPLDM_ABI_STABLE
782int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
783 uint8_t pldm_type, uint8_t command,
784 struct pldm_msg *msg)
785{
786 int rc = encode_pldm_header_only_errno(msg_type, instance_id, pldm_type,
787 command, msg);
788 if (rc) {
789 return pldm_xlate_errno(rc);
790 }
791 return PLDM_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930792}
Chau Ly59dce782025-04-01 08:22:07 +0000793
Chau Ly26c8eb22025-07-30 06:56:33 +0000794LIBPLDM_ABI_STABLE
Chau Ly59dce782025-04-01 08:22:07 +0000795int encode_pldm_base_negotiate_transfer_params_req(
796 uint8_t instance_id,
797 const struct pldm_base_negotiate_transfer_params_req *req,
Chau Lye98a72f2025-08-15 03:38:50 +0000798 struct pldm_msg *msg, size_t *payload_length)
Chau Ly59dce782025-04-01 08:22:07 +0000799{
800 PLDM_MSGBUF_DEFINE_P(buf);
801 int rc;
802
Chau Lye98a72f2025-08-15 03:38:50 +0000803 if (req == NULL || msg == NULL || payload_length == NULL) {
Chau Ly59dce782025-04-01 08:22:07 +0000804 return -EINVAL;
805 }
806
807 struct pldm_header_info header = { 0 };
808 header.instance = instance_id;
809 header.msg_type = PLDM_REQUEST;
810 header.pldm_type = PLDM_BASE;
811 header.command = PLDM_NEGOTIATE_TRANSFER_PARAMETERS;
812
813 rc = pack_pldm_header_errno(&header, &msg->hdr);
814 if (rc) {
815 return rc;
816 }
817
818 rc = pldm_msgbuf_init_errno(
819 buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES,
Chau Lye98a72f2025-08-15 03:38:50 +0000820 msg->payload, *payload_length);
Chau Ly59dce782025-04-01 08:22:07 +0000821 if (rc) {
822 return rc;
823 }
824
825 pldm_msgbuf_insert(buf, req->requester_part_size);
826 rc = pldm_msgbuf_insert_array(
827 buf, sizeof(req->requester_protocol_support),
828 (uint8_t *)req->requester_protocol_support,
829 sizeof(req->requester_protocol_support));
830 if (rc) {
831 return pldm_msgbuf_discard(buf, rc);
832 }
833
Chau Lye98a72f2025-08-15 03:38:50 +0000834 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
Chau Ly59dce782025-04-01 08:22:07 +0000835}
836
Chau Ly26c8eb22025-07-30 06:56:33 +0000837LIBPLDM_ABI_STABLE
Chau Ly59dce782025-04-01 08:22:07 +0000838int decode_pldm_base_negotiate_transfer_params_resp(
839 const struct pldm_msg *msg, size_t payload_length,
840 struct pldm_base_negotiate_transfer_params_resp *resp)
841{
842 PLDM_MSGBUF_DEFINE_P(buf);
843 int rc;
844
845 if (msg == NULL || resp == NULL) {
846 return -EINVAL;
847 }
848
849 rc = pldm_msg_has_error(msg, payload_length);
850
851 if (rc) {
852 resp->completion_code = rc;
853 return 0;
854 }
855
856 rc = pldm_msgbuf_init_errno(
857 buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES,
858 msg->payload, payload_length);
859 if (rc) {
860 return rc;
861 }
862
863 pldm_msgbuf_extract(buf, resp->completion_code);
864 pldm_msgbuf_extract(buf, resp->responder_part_size);
865 rc = pldm_msgbuf_extract_array(
866 buf, sizeof(resp->responder_protocol_support),
867 (uint8_t *)resp->responder_protocol_support,
868 sizeof(resp->responder_protocol_support));
869 if (rc) {
870 return pldm_msgbuf_discard(buf, rc);
871 }
872
873 return pldm_msgbuf_complete_consumed(buf);
874}