blob: 7aca3c805170dc9335693ee9fb643e8ba0a83fd2 [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"
4
5#include <assert.h>
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10306#include <libpldm/base.h>
7#include <libpldm/pldm_types.h>
8
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include <endian.h>
Andrew Jefferyd861a682024-06-03 21:43:09 +093010#include <errno.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +053011#include <stdint.h>
12#include <string.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093013
Andrew Jefferyd861a682024-06-03 21:43:09 +093014int pack_pldm_header_errno(const struct pldm_header_info *hdr,
15 struct pldm_msg_hdr *msg)
Andrew Jeffery9c766792022-08-10 23:12:49 +093016{
17 if (msg == NULL || hdr == NULL) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093018 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093019 }
20
21 if (hdr->msg_type != PLDM_RESPONSE && hdr->msg_type != PLDM_REQUEST &&
22 hdr->msg_type != PLDM_ASYNC_REQUEST_NOTIFY) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093023 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093024 }
25
26 if (hdr->instance > PLDM_INSTANCE_MAX) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093027 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093028 }
29
30 if (hdr->pldm_type > (PLDM_MAX_TYPES - 1)) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093031 return -ENOMSG;
Andrew Jeffery9c766792022-08-10 23:12:49 +093032 }
33
34 uint8_t datagram = (hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) ? 1 : 0;
35
36 if (hdr->msg_type == PLDM_RESPONSE) {
37 msg->request = PLDM_RESPONSE;
38 } else if (hdr->msg_type == PLDM_REQUEST ||
39 hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) {
40 msg->request = PLDM_REQUEST;
41 }
42 msg->datagram = datagram;
43 msg->reserved = 0;
44 msg->instance_id = hdr->instance;
45 msg->header_ver = PLDM_CURRENT_VERSION;
46 msg->type = hdr->pldm_type;
47 msg->command = hdr->command;
48
Andrew Jefferyd861a682024-06-03 21:43:09 +093049 return 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +093050}
51
Andrew Jefferyd861a682024-06-03 21:43:09 +093052int unpack_pldm_header_errno(const struct pldm_msg_hdr *msg,
53 struct pldm_header_info *hdr)
Andrew Jeffery9c766792022-08-10 23:12:49 +093054{
55 if (msg == NULL) {
Andrew Jefferyd861a682024-06-03 21:43:09 +093056 return -EINVAL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093057 }
58
59 if (msg->request == PLDM_RESPONSE) {
60 hdr->msg_type = PLDM_RESPONSE;
61 } else {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093062 hdr->msg_type = msg->datagram ? PLDM_ASYNC_REQUEST_NOTIFY :
63 PLDM_REQUEST;
Andrew Jeffery9c766792022-08-10 23:12:49 +093064 }
65
66 hdr->instance = msg->instance_id;
67 hdr->pldm_type = msg->type;
68 hdr->command = msg->command;
69
Andrew Jefferyd861a682024-06-03 21:43:09 +093070 return 0;
71}
72
73LIBPLDM_ABI_STABLE
74uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
75 struct pldm_msg_hdr *msg)
76{
77 enum pldm_completion_codes cc;
78 int rc;
79
80 rc = pack_pldm_header_errno(hdr, msg);
81 if (!rc) {
82 return PLDM_SUCCESS;
83 }
84
85 cc = pldm_xlate_errno(rc);
86 assert(cc < UINT8_MAX);
87 if (cc > UINT8_MAX) {
88 static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error");
89 return PLDM_ERROR;
90 }
91
92 return cc;
93}
94
95LIBPLDM_ABI_STABLE
96uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg,
97 struct pldm_header_info *hdr)
98{
99 enum pldm_completion_codes cc;
100 int rc;
101
102 rc = unpack_pldm_header_errno(msg, hdr);
103 if (!rc) {
104 return PLDM_SUCCESS;
105 }
106
107 cc = pldm_xlate_errno(rc);
108 assert(cc < UINT8_MAX);
109 if (cc > UINT8_MAX) {
110 static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error");
111 return PLDM_ERROR;
112 }
113
114 return cc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930115}
116
Andrew Jeffery5239d9a2023-10-16 10:51:53 +1030117LIBPLDM_ABI_STABLE
Andrew Jeffery91c06e92023-09-22 15:22:54 +0930118bool pldm_msg_hdr_correlate_response(const struct pldm_msg_hdr *req,
119 const struct pldm_msg_hdr *resp)
120{
121 return req->instance_id == resp->instance_id && req->request &&
122 !resp->request && req->type == resp->type &&
123 req->command == resp->command;
124}
125
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930126LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930127int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg)
128{
129 if (msg == NULL) {
130 return PLDM_ERROR_INVALID_DATA;
131 }
132
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930133 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930134 header.instance = instance_id;
135 header.msg_type = PLDM_REQUEST;
136 header.command = PLDM_GET_PLDM_TYPES;
137
138 return pack_pldm_header(&header, &(msg->hdr));
139}
140
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930141LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930142int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
143 struct pldm_msg *msg)
144{
145 if (msg == NULL) {
146 return PLDM_ERROR_INVALID_DATA;
147 }
148
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930149 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930150 header.instance = instance_id;
151 header.msg_type = PLDM_REQUEST;
152 header.command = PLDM_GET_PLDM_COMMANDS;
153
154 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
155 if (rc != PLDM_SUCCESS) {
156 return rc;
157 }
158
159 struct pldm_get_commands_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930160 (struct pldm_get_commands_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930161
162 request->type = type;
163 request->version = version;
164
165 return PLDM_SUCCESS;
166}
167
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930168LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930169int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
170 const bitfield8_t *types, struct pldm_msg *msg)
171{
172 if (msg == NULL) {
173 return PLDM_ERROR_INVALID_DATA;
174 }
175
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930176 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930177 header.instance = instance_id;
178 header.msg_type = PLDM_RESPONSE;
179 header.command = PLDM_GET_PLDM_TYPES;
180
181 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
182 if (rc != PLDM_SUCCESS) {
183 return rc;
184 }
185
186 struct pldm_get_types_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930187 (struct pldm_get_types_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930188 response->completion_code = completion_code;
189 if (response->completion_code == PLDM_SUCCESS) {
190 if (types == NULL) {
191 return PLDM_ERROR_INVALID_DATA;
192 }
193 memcpy(response->types, &(types->byte), PLDM_MAX_TYPES / 8);
194 }
195
196 return PLDM_SUCCESS;
197}
198
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930199LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930200int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
201 uint8_t *type, ver32_t *version)
202{
203 if (msg == NULL || type == NULL || version == NULL) {
204 return PLDM_ERROR_INVALID_DATA;
205 }
206
207 if (payload_length != PLDM_GET_COMMANDS_REQ_BYTES) {
208 return PLDM_ERROR_INVALID_LENGTH;
209 }
210
211 struct pldm_get_commands_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930212 (struct pldm_get_commands_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930213 *type = request->type;
214 *version = request->version;
215 return PLDM_SUCCESS;
216}
217
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930218LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930219int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
220 const bitfield8_t *commands, struct pldm_msg *msg)
221{
222 if (msg == NULL) {
223 return PLDM_ERROR_INVALID_DATA;
224 }
225
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930226 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930227 header.instance = instance_id;
228 header.msg_type = PLDM_RESPONSE;
229 header.command = PLDM_GET_PLDM_COMMANDS;
230 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
231 if (rc != PLDM_SUCCESS) {
232 return rc;
233 }
234
235 struct pldm_get_commands_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930236 (struct pldm_get_commands_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930237 response->completion_code = completion_code;
238 if (response->completion_code == PLDM_SUCCESS) {
239 if (commands == NULL) {
240 return PLDM_ERROR_INVALID_DATA;
241 }
242 memcpy(response->commands, &(commands->byte),
243 PLDM_MAX_CMDS_PER_TYPE / 8);
244 }
245
246 return PLDM_SUCCESS;
247}
248
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930249LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930250int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
251 uint8_t *completion_code, bitfield8_t *types)
252{
253 if (msg == NULL || types == NULL || completion_code == NULL) {
254 return PLDM_ERROR_INVALID_DATA;
255 }
256
257 *completion_code = msg->payload[0];
258 if (PLDM_SUCCESS != *completion_code) {
259 return PLDM_SUCCESS;
260 }
261
262 if (payload_length != PLDM_GET_TYPES_RESP_BYTES) {
263 return PLDM_ERROR_INVALID_LENGTH;
264 }
265
266 struct pldm_get_types_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930267 (struct pldm_get_types_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930268
269 memcpy(&(types->byte), response->types, PLDM_MAX_TYPES / 8);
270
271 return PLDM_SUCCESS;
272}
273
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930274LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930275int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
276 uint8_t *completion_code, bitfield8_t *commands)
277{
278 if (msg == NULL || commands == NULL || completion_code == NULL) {
279 return PLDM_ERROR_INVALID_DATA;
280 }
281
282 *completion_code = msg->payload[0];
283 if (PLDM_SUCCESS != *completion_code) {
284 return PLDM_SUCCESS;
285 }
286
287 if (payload_length != PLDM_GET_COMMANDS_RESP_BYTES) {
288 return PLDM_ERROR_INVALID_LENGTH;
289 }
290
291 struct pldm_get_commands_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930292 (struct pldm_get_commands_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930293
294 memcpy(&(commands->byte), response->commands,
295 PLDM_MAX_CMDS_PER_TYPE / 8);
296
297 return PLDM_SUCCESS;
298}
299
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930300LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930301int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
302 uint8_t transfer_opflag, uint8_t type,
303 struct pldm_msg *msg)
304{
305 if (NULL == msg) {
306 return PLDM_ERROR_INVALID_DATA;
307 }
308
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930309 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930310 header.msg_type = PLDM_REQUEST;
311 header.instance = instance_id;
312 header.pldm_type = PLDM_BASE;
313 header.command = PLDM_GET_PLDM_VERSION;
314
315 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
316 if (rc != PLDM_SUCCESS) {
317 return rc;
318 }
319
320 struct pldm_get_version_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930321 (struct pldm_get_version_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930322 transfer_handle = htole32(transfer_handle);
323 request->transfer_handle = transfer_handle;
324 request->transfer_opflag = transfer_opflag;
325 request->type = type;
326
327 return PLDM_SUCCESS;
328}
329
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930330LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930331int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
332 uint32_t next_transfer_handle,
333 uint8_t transfer_flag, const ver32_t *version_data,
334 size_t version_size, struct pldm_msg *msg)
335{
336 if (NULL == msg) {
337 return PLDM_ERROR_INVALID_DATA;
338 }
339
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930340 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930341 header.msg_type = PLDM_RESPONSE;
342 header.instance = instance_id;
343 header.pldm_type = PLDM_BASE;
344 header.command = PLDM_GET_PLDM_VERSION;
345
346 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
347 if (rc != PLDM_SUCCESS) {
348 return rc;
349 }
350
351 struct pldm_get_version_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930352 (struct pldm_get_version_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930353 response->completion_code = completion_code;
354 if (response->completion_code == PLDM_SUCCESS) {
355 response->next_transfer_handle = htole32(next_transfer_handle);
356 response->transfer_flag = transfer_flag;
357 memcpy(response->version_data, (uint8_t *)version_data,
358 version_size);
359 }
360 return PLDM_SUCCESS;
361}
362
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930363LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930364int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
365 uint32_t *transfer_handle, uint8_t *transfer_opflag,
366 uint8_t *type)
367{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930368 if (payload_length != PLDM_GET_VERSION_REQ_BYTES) {
369 return PLDM_ERROR_INVALID_LENGTH;
370 }
371
372 struct pldm_get_version_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930373 (struct pldm_get_version_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930374 *transfer_handle = le32toh(request->transfer_handle);
375 *transfer_opflag = request->transfer_opflag;
376 *type = request->type;
377 return PLDM_SUCCESS;
378}
379
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930380LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930381int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
382 uint8_t *completion_code,
383 uint32_t *next_transfer_handle,
384 uint8_t *transfer_flag, ver32_t *version)
385{
386 if (msg == NULL || next_transfer_handle == NULL ||
387 transfer_flag == NULL || completion_code == NULL) {
388 return PLDM_ERROR_INVALID_DATA;
389 }
390
391 *completion_code = msg->payload[0];
392 if (PLDM_SUCCESS != *completion_code) {
393 return PLDM_SUCCESS;
394 }
395
396 if (payload_length < PLDM_GET_VERSION_RESP_BYTES) {
397 return PLDM_ERROR_INVALID_LENGTH;
398 }
399
400 struct pldm_get_version_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930401 (struct pldm_get_version_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930402
403 *next_transfer_handle = le32toh(response->next_transfer_handle);
404 *transfer_flag = response->transfer_flag;
405 memcpy(version, (uint8_t *)response->version_data, sizeof(ver32_t));
406
407 return PLDM_SUCCESS;
408}
409
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930410LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930411int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg)
412{
413 if (msg == NULL) {
414 return PLDM_ERROR_INVALID_DATA;
415 }
416
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930417 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930418 header.instance = instance_id;
419 header.msg_type = PLDM_REQUEST;
420 header.command = PLDM_GET_TID;
421
422 return pack_pldm_header(&header, &(msg->hdr));
423}
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930424
425LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930426int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
427 uint8_t tid, struct pldm_msg *msg)
428{
429 if (msg == NULL) {
430 return PLDM_ERROR_INVALID_DATA;
431 }
432
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930433 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930434 header.instance = instance_id;
435 header.msg_type = PLDM_RESPONSE;
436 header.command = PLDM_GET_TID;
437
438 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
439 if (rc != PLDM_SUCCESS) {
440 return rc;
441 }
442
443 struct pldm_get_tid_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930444 (struct pldm_get_tid_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930445 response->completion_code = completion_code;
446 response->tid = tid;
447
448 return PLDM_SUCCESS;
449}
450
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930451LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930452int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
453 uint8_t *completion_code, uint8_t *tid)
454{
455 if (msg == NULL || tid == NULL || completion_code == NULL) {
456 return PLDM_ERROR_INVALID_DATA;
457 }
458
459 *completion_code = msg->payload[0];
460 if (PLDM_SUCCESS != *completion_code) {
461 return PLDM_SUCCESS;
462 }
463
464 if (payload_length != PLDM_GET_TID_RESP_BYTES) {
465 return PLDM_ERROR_INVALID_LENGTH;
466 }
467
468 struct pldm_get_tid_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930469 (struct pldm_get_tid_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930470
471 *tid = response->tid;
472
473 return PLDM_SUCCESS;
474}
475
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930476LIBPLDM_ABI_STABLE
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800477int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg)
478{
479 if (msg == NULL) {
480 return PLDM_ERROR_INVALID_DATA;
481 }
482
483 if (tid == 0x0 || tid == 0xff) {
484 return PLDM_ERROR_INVALID_DATA;
485 }
486
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930487 struct pldm_header_info header = { 0 };
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800488 header.instance = instance_id;
489 header.msg_type = PLDM_REQUEST;
490 header.command = PLDM_SET_TID;
491
492 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
493 if (rc != PLDM_SUCCESS) {
494 return rc;
495 }
496
497 struct pldm_set_tid_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930498 (struct pldm_set_tid_req *)msg->payload;
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800499 request->tid = tid;
500
501 return PLDM_SUCCESS;
502}
503
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930504LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930505int decode_multipart_receive_req(const struct pldm_msg *msg,
506 size_t payload_length, uint8_t *pldm_type,
507 uint8_t *transfer_opflag,
508 uint32_t *transfer_ctx,
509 uint32_t *transfer_handle,
510 uint32_t *section_offset,
511 uint32_t *section_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930512{
513 if (msg == NULL || pldm_type == NULL || transfer_opflag == NULL ||
514 transfer_ctx == NULL || transfer_handle == NULL ||
515 section_offset == NULL || section_length == NULL) {
516 return PLDM_ERROR_INVALID_DATA;
517 }
518
519 if (payload_length != PLDM_MULTIPART_RECEIVE_REQ_BYTES) {
520 return PLDM_ERROR_INVALID_LENGTH;
521 }
522
523 struct pldm_multipart_receive_req *request =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930524 (struct pldm_multipart_receive_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930525
526 if (request->pldm_type != PLDM_BASE) {
527 return PLDM_ERROR_INVALID_PLDM_TYPE;
528 }
529
530 // Any enum value above PLDM_XFER_CURRENT_PART is invalid.
531 if (request->transfer_opflag > PLDM_XFER_CURRENT_PART) {
532 return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
533 }
534
535 // A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers.
536 uint32_t sec_offset = le32toh(request->section_offset);
537 if (sec_offset == 0 &&
538 (request->transfer_opflag != PLDM_XFER_FIRST_PART &&
539 request->transfer_opflag != PLDM_XFER_COMPLETE)) {
540 return PLDM_ERROR_INVALID_DATA;
541 }
542
543 uint32_t handle = le32toh(request->transfer_handle);
544 if (handle == 0 && request->transfer_opflag != PLDM_XFER_COMPLETE) {
545 return PLDM_ERROR_INVALID_DATA;
546 }
547
548 *pldm_type = request->pldm_type;
549 *transfer_opflag = request->transfer_opflag;
550 *transfer_ctx = request->transfer_ctx;
551 *transfer_handle = handle;
552 *section_offset = sec_offset;
553 *section_length = le32toh(request->section_length);
554
555 return PLDM_SUCCESS;
556}
557
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930558LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930559int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
560 uint8_t cc, struct pldm_msg *msg)
561{
562 if (msg == NULL) {
563 return PLDM_ERROR_INVALID_DATA;
564 }
565
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930566 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930567 header.instance = instance_id;
568 header.msg_type = PLDM_RESPONSE;
569 header.pldm_type = type;
570 header.command = command;
571
572 uint8_t rc = pack_pldm_header(&header, &msg->hdr);
573 if (rc != PLDM_SUCCESS) {
574 return rc;
575 }
576
577 msg->payload[0] = cc;
578
579 return PLDM_SUCCESS;
580}
581
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930582LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930583int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
584 uint8_t pldm_type, uint8_t command,
585 struct pldm_msg *msg)
586{
587 if (msg == NULL) {
588 return PLDM_ERROR_INVALID_DATA;
589 }
590
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930591 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930592 header.msg_type = msg_type;
593 header.instance = instance_id;
594 header.pldm_type = pldm_type;
595 header.command = command;
596 return pack_pldm_header(&header, &(msg->hdr));
597}