148761c62SAndrew Jeffery /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2d861a681SAndrew Jeffery #include "api.h"
3d861a681SAndrew Jeffery #include "dsp/base.h"
4d861a681SAndrew Jeffery
5d861a681SAndrew Jeffery #include <assert.h>
648761c62SAndrew Jeffery #include <libpldm/base.h>
748761c62SAndrew Jeffery #include <libpldm/pldm_types.h>
848761c62SAndrew Jeffery
948761c62SAndrew Jeffery #include <endian.h>
10d861a681SAndrew Jeffery #include <errno.h>
1148761c62SAndrew Jeffery #include <stdint.h>
1248761c62SAndrew Jeffery #include <string.h>
1348761c62SAndrew Jeffery
pack_pldm_header_errno(const struct pldm_header_info * hdr,struct pldm_msg_hdr * msg)14d861a681SAndrew Jeffery int pack_pldm_header_errno(const struct pldm_header_info *hdr,
1548761c62SAndrew Jeffery struct pldm_msg_hdr *msg)
1648761c62SAndrew Jeffery {
1748761c62SAndrew Jeffery if (msg == NULL || hdr == NULL) {
18d861a681SAndrew Jeffery return -EINVAL;
1948761c62SAndrew Jeffery }
2048761c62SAndrew Jeffery
2148761c62SAndrew Jeffery if (hdr->msg_type != PLDM_RESPONSE && hdr->msg_type != PLDM_REQUEST &&
2248761c62SAndrew Jeffery hdr->msg_type != PLDM_ASYNC_REQUEST_NOTIFY) {
23d861a681SAndrew Jeffery return -EINVAL;
2448761c62SAndrew Jeffery }
2548761c62SAndrew Jeffery
2648761c62SAndrew Jeffery if (hdr->instance > PLDM_INSTANCE_MAX) {
27d861a681SAndrew Jeffery return -EINVAL;
2848761c62SAndrew Jeffery }
2948761c62SAndrew Jeffery
3048761c62SAndrew Jeffery if (hdr->pldm_type > (PLDM_MAX_TYPES - 1)) {
31d861a681SAndrew Jeffery return -ENOMSG;
3248761c62SAndrew Jeffery }
3348761c62SAndrew Jeffery
3448761c62SAndrew Jeffery uint8_t datagram = (hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) ? 1 : 0;
3548761c62SAndrew Jeffery
3648761c62SAndrew Jeffery if (hdr->msg_type == PLDM_RESPONSE) {
3748761c62SAndrew Jeffery msg->request = PLDM_RESPONSE;
3848761c62SAndrew Jeffery } else if (hdr->msg_type == PLDM_REQUEST ||
3948761c62SAndrew Jeffery hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) {
4048761c62SAndrew Jeffery msg->request = PLDM_REQUEST;
4148761c62SAndrew Jeffery }
4248761c62SAndrew Jeffery msg->datagram = datagram;
4348761c62SAndrew Jeffery msg->reserved = 0;
4448761c62SAndrew Jeffery msg->instance_id = hdr->instance;
4548761c62SAndrew Jeffery msg->header_ver = PLDM_CURRENT_VERSION;
4648761c62SAndrew Jeffery msg->type = hdr->pldm_type;
4748761c62SAndrew Jeffery msg->command = hdr->command;
4848761c62SAndrew Jeffery
49d861a681SAndrew Jeffery return 0;
5048761c62SAndrew Jeffery }
5148761c62SAndrew Jeffery
unpack_pldm_header_errno(const struct pldm_msg_hdr * msg,struct pldm_header_info * hdr)52d861a681SAndrew Jeffery int unpack_pldm_header_errno(const struct pldm_msg_hdr *msg,
5348761c62SAndrew Jeffery struct pldm_header_info *hdr)
5448761c62SAndrew Jeffery {
5548761c62SAndrew Jeffery if (msg == NULL) {
56d861a681SAndrew Jeffery return -EINVAL;
5748761c62SAndrew Jeffery }
5848761c62SAndrew Jeffery
5948761c62SAndrew Jeffery if (msg->request == PLDM_RESPONSE) {
6048761c62SAndrew Jeffery hdr->msg_type = PLDM_RESPONSE;
6148761c62SAndrew Jeffery } else {
6248761c62SAndrew Jeffery hdr->msg_type = msg->datagram ? PLDM_ASYNC_REQUEST_NOTIFY :
6348761c62SAndrew Jeffery PLDM_REQUEST;
6448761c62SAndrew Jeffery }
6548761c62SAndrew Jeffery
6648761c62SAndrew Jeffery hdr->instance = msg->instance_id;
6748761c62SAndrew Jeffery hdr->pldm_type = msg->type;
6848761c62SAndrew Jeffery hdr->command = msg->command;
6948761c62SAndrew Jeffery
70d861a681SAndrew Jeffery return 0;
71d861a681SAndrew Jeffery }
72d861a681SAndrew Jeffery
73d861a681SAndrew Jeffery LIBPLDM_ABI_STABLE
pack_pldm_header(const struct pldm_header_info * hdr,struct pldm_msg_hdr * msg)74d861a681SAndrew Jeffery uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
75d861a681SAndrew Jeffery struct pldm_msg_hdr *msg)
76d861a681SAndrew Jeffery {
77d861a681SAndrew Jeffery enum pldm_completion_codes cc;
78d861a681SAndrew Jeffery int rc;
79d861a681SAndrew Jeffery
80d861a681SAndrew Jeffery rc = pack_pldm_header_errno(hdr, msg);
81d861a681SAndrew Jeffery if (!rc) {
8248761c62SAndrew Jeffery return PLDM_SUCCESS;
8348761c62SAndrew Jeffery }
8448761c62SAndrew Jeffery
85d861a681SAndrew Jeffery cc = pldm_xlate_errno(rc);
86d861a681SAndrew Jeffery assert(cc < UINT8_MAX);
87d861a681SAndrew Jeffery if (cc > UINT8_MAX) {
88d861a681SAndrew Jeffery static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error");
89d861a681SAndrew Jeffery return PLDM_ERROR;
90d861a681SAndrew Jeffery }
91d861a681SAndrew Jeffery
92d861a681SAndrew Jeffery return cc;
93d861a681SAndrew Jeffery }
94d861a681SAndrew Jeffery
95d861a681SAndrew Jeffery LIBPLDM_ABI_STABLE
unpack_pldm_header(const struct pldm_msg_hdr * msg,struct pldm_header_info * hdr)96d861a681SAndrew Jeffery uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg,
97d861a681SAndrew Jeffery struct pldm_header_info *hdr)
98d861a681SAndrew Jeffery {
99d861a681SAndrew Jeffery enum pldm_completion_codes cc;
100d861a681SAndrew Jeffery int rc;
101d861a681SAndrew Jeffery
102d861a681SAndrew Jeffery rc = unpack_pldm_header_errno(msg, hdr);
103d861a681SAndrew Jeffery if (!rc) {
104d861a681SAndrew Jeffery return PLDM_SUCCESS;
105d861a681SAndrew Jeffery }
106d861a681SAndrew Jeffery
107d861a681SAndrew Jeffery cc = pldm_xlate_errno(rc);
108d861a681SAndrew Jeffery assert(cc < UINT8_MAX);
109d861a681SAndrew Jeffery if (cc > UINT8_MAX) {
110d861a681SAndrew Jeffery static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error");
111d861a681SAndrew Jeffery return PLDM_ERROR;
112d861a681SAndrew Jeffery }
113d861a681SAndrew Jeffery
114d861a681SAndrew Jeffery return cc;
115d861a681SAndrew Jeffery }
116d861a681SAndrew Jeffery
11748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
pldm_msg_hdr_correlate_response(const struct pldm_msg_hdr * req,const struct pldm_msg_hdr * resp)11848761c62SAndrew Jeffery bool pldm_msg_hdr_correlate_response(const struct pldm_msg_hdr *req,
11948761c62SAndrew Jeffery const struct pldm_msg_hdr *resp)
12048761c62SAndrew Jeffery {
12148761c62SAndrew Jeffery return req->instance_id == resp->instance_id && req->request &&
12248761c62SAndrew Jeffery !resp->request && req->type == resp->type &&
12348761c62SAndrew Jeffery req->command == resp->command;
12448761c62SAndrew Jeffery }
12548761c62SAndrew Jeffery
12648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_types_req(uint8_t instance_id,struct pldm_msg * msg)12748761c62SAndrew Jeffery int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg)
12848761c62SAndrew Jeffery {
12948761c62SAndrew Jeffery if (msg == NULL) {
13048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
13148761c62SAndrew Jeffery }
13248761c62SAndrew Jeffery
13348761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
13448761c62SAndrew Jeffery header.instance = instance_id;
13548761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
13648761c62SAndrew Jeffery header.command = PLDM_GET_PLDM_TYPES;
13748761c62SAndrew Jeffery
13848761c62SAndrew Jeffery return pack_pldm_header(&header, &(msg->hdr));
13948761c62SAndrew Jeffery }
14048761c62SAndrew Jeffery
14148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_commands_req(uint8_t instance_id,uint8_t type,ver32_t version,struct pldm_msg * msg)14248761c62SAndrew Jeffery int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
14348761c62SAndrew Jeffery struct pldm_msg *msg)
14448761c62SAndrew Jeffery {
14548761c62SAndrew Jeffery if (msg == NULL) {
14648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
14748761c62SAndrew Jeffery }
14848761c62SAndrew Jeffery
14948761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
15048761c62SAndrew Jeffery header.instance = instance_id;
15148761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
15248761c62SAndrew Jeffery header.command = PLDM_GET_PLDM_COMMANDS;
15348761c62SAndrew Jeffery
15448761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
15548761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
15648761c62SAndrew Jeffery return rc;
15748761c62SAndrew Jeffery }
15848761c62SAndrew Jeffery
15948761c62SAndrew Jeffery struct pldm_get_commands_req *request =
16048761c62SAndrew Jeffery (struct pldm_get_commands_req *)msg->payload;
16148761c62SAndrew Jeffery
16248761c62SAndrew Jeffery request->type = type;
16348761c62SAndrew Jeffery request->version = version;
16448761c62SAndrew Jeffery
16548761c62SAndrew Jeffery return PLDM_SUCCESS;
16648761c62SAndrew Jeffery }
16748761c62SAndrew Jeffery
16848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_types_resp(uint8_t instance_id,uint8_t completion_code,const bitfield8_t * types,struct pldm_msg * msg)16948761c62SAndrew Jeffery int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
17048761c62SAndrew Jeffery const bitfield8_t *types, struct pldm_msg *msg)
17148761c62SAndrew Jeffery {
17248761c62SAndrew Jeffery if (msg == NULL) {
17348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
17448761c62SAndrew Jeffery }
17548761c62SAndrew Jeffery
17648761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
17748761c62SAndrew Jeffery header.instance = instance_id;
17848761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
17948761c62SAndrew Jeffery header.command = PLDM_GET_PLDM_TYPES;
18048761c62SAndrew Jeffery
18148761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
18248761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
18348761c62SAndrew Jeffery return rc;
18448761c62SAndrew Jeffery }
18548761c62SAndrew Jeffery
18648761c62SAndrew Jeffery struct pldm_get_types_resp *response =
18748761c62SAndrew Jeffery (struct pldm_get_types_resp *)msg->payload;
18848761c62SAndrew Jeffery response->completion_code = completion_code;
18948761c62SAndrew Jeffery if (response->completion_code == PLDM_SUCCESS) {
19048761c62SAndrew Jeffery if (types == NULL) {
19148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
19248761c62SAndrew Jeffery }
19348761c62SAndrew Jeffery memcpy(response->types, &(types->byte), PLDM_MAX_TYPES / 8);
19448761c62SAndrew Jeffery }
19548761c62SAndrew Jeffery
19648761c62SAndrew Jeffery return PLDM_SUCCESS;
19748761c62SAndrew Jeffery }
19848761c62SAndrew Jeffery
19948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_get_commands_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * type,ver32_t * version)20048761c62SAndrew Jeffery int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
20148761c62SAndrew Jeffery uint8_t *type, ver32_t *version)
20248761c62SAndrew Jeffery {
20348761c62SAndrew Jeffery if (msg == NULL || type == NULL || version == NULL) {
20448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
20548761c62SAndrew Jeffery }
20648761c62SAndrew Jeffery
20748761c62SAndrew Jeffery if (payload_length != PLDM_GET_COMMANDS_REQ_BYTES) {
20848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
20948761c62SAndrew Jeffery }
21048761c62SAndrew Jeffery
21148761c62SAndrew Jeffery struct pldm_get_commands_req *request =
21248761c62SAndrew Jeffery (struct pldm_get_commands_req *)msg->payload;
21348761c62SAndrew Jeffery *type = request->type;
21448761c62SAndrew Jeffery *version = request->version;
21548761c62SAndrew Jeffery return PLDM_SUCCESS;
21648761c62SAndrew Jeffery }
21748761c62SAndrew Jeffery
21848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_commands_resp(uint8_t instance_id,uint8_t completion_code,const bitfield8_t * commands,struct pldm_msg * msg)21948761c62SAndrew Jeffery int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
22048761c62SAndrew Jeffery const bitfield8_t *commands, struct pldm_msg *msg)
22148761c62SAndrew Jeffery {
22248761c62SAndrew Jeffery if (msg == NULL) {
22348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
22448761c62SAndrew Jeffery }
22548761c62SAndrew Jeffery
22648761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
22748761c62SAndrew Jeffery header.instance = instance_id;
22848761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
22948761c62SAndrew Jeffery header.command = PLDM_GET_PLDM_COMMANDS;
23048761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
23148761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
23248761c62SAndrew Jeffery return rc;
23348761c62SAndrew Jeffery }
23448761c62SAndrew Jeffery
23548761c62SAndrew Jeffery struct pldm_get_commands_resp *response =
23648761c62SAndrew Jeffery (struct pldm_get_commands_resp *)msg->payload;
23748761c62SAndrew Jeffery response->completion_code = completion_code;
23848761c62SAndrew Jeffery if (response->completion_code == PLDM_SUCCESS) {
23948761c62SAndrew Jeffery if (commands == NULL) {
24048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
24148761c62SAndrew Jeffery }
24248761c62SAndrew Jeffery memcpy(response->commands, &(commands->byte),
24348761c62SAndrew Jeffery PLDM_MAX_CMDS_PER_TYPE / 8);
24448761c62SAndrew Jeffery }
24548761c62SAndrew Jeffery
24648761c62SAndrew Jeffery return PLDM_SUCCESS;
24748761c62SAndrew Jeffery }
24848761c62SAndrew Jeffery
24948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_get_types_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,bitfield8_t * types)25048761c62SAndrew Jeffery int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
25148761c62SAndrew Jeffery uint8_t *completion_code, bitfield8_t *types)
25248761c62SAndrew Jeffery {
25348761c62SAndrew Jeffery if (msg == NULL || types == NULL || completion_code == NULL) {
25448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
25548761c62SAndrew Jeffery }
25648761c62SAndrew Jeffery
25748761c62SAndrew Jeffery *completion_code = msg->payload[0];
25848761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
25948761c62SAndrew Jeffery return PLDM_SUCCESS;
26048761c62SAndrew Jeffery }
26148761c62SAndrew Jeffery
26248761c62SAndrew Jeffery if (payload_length != PLDM_GET_TYPES_RESP_BYTES) {
26348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
26448761c62SAndrew Jeffery }
26548761c62SAndrew Jeffery
26648761c62SAndrew Jeffery struct pldm_get_types_resp *response =
26748761c62SAndrew Jeffery (struct pldm_get_types_resp *)msg->payload;
26848761c62SAndrew Jeffery
26948761c62SAndrew Jeffery memcpy(&(types->byte), response->types, PLDM_MAX_TYPES / 8);
27048761c62SAndrew Jeffery
27148761c62SAndrew Jeffery return PLDM_SUCCESS;
27248761c62SAndrew Jeffery }
27348761c62SAndrew Jeffery
27448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_get_commands_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,bitfield8_t * commands)27548761c62SAndrew Jeffery int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
27648761c62SAndrew Jeffery uint8_t *completion_code, bitfield8_t *commands)
27748761c62SAndrew Jeffery {
27848761c62SAndrew Jeffery if (msg == NULL || commands == NULL || completion_code == NULL) {
27948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
28048761c62SAndrew Jeffery }
28148761c62SAndrew Jeffery
28248761c62SAndrew Jeffery *completion_code = msg->payload[0];
28348761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
28448761c62SAndrew Jeffery return PLDM_SUCCESS;
28548761c62SAndrew Jeffery }
28648761c62SAndrew Jeffery
28748761c62SAndrew Jeffery if (payload_length != PLDM_GET_COMMANDS_RESP_BYTES) {
28848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
28948761c62SAndrew Jeffery }
29048761c62SAndrew Jeffery
29148761c62SAndrew Jeffery struct pldm_get_commands_resp *response =
29248761c62SAndrew Jeffery (struct pldm_get_commands_resp *)msg->payload;
29348761c62SAndrew Jeffery
29448761c62SAndrew Jeffery memcpy(&(commands->byte), response->commands,
29548761c62SAndrew Jeffery PLDM_MAX_CMDS_PER_TYPE / 8);
29648761c62SAndrew Jeffery
29748761c62SAndrew Jeffery return PLDM_SUCCESS;
29848761c62SAndrew Jeffery }
29948761c62SAndrew Jeffery
30048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_version_req(uint8_t instance_id,uint32_t transfer_handle,uint8_t transfer_opflag,uint8_t type,struct pldm_msg * msg)30148761c62SAndrew Jeffery int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
30248761c62SAndrew Jeffery uint8_t transfer_opflag, uint8_t type,
30348761c62SAndrew Jeffery struct pldm_msg *msg)
30448761c62SAndrew Jeffery {
30548761c62SAndrew Jeffery if (NULL == msg) {
30648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
30748761c62SAndrew Jeffery }
30848761c62SAndrew Jeffery
30948761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
31048761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
31148761c62SAndrew Jeffery header.instance = instance_id;
31248761c62SAndrew Jeffery header.pldm_type = PLDM_BASE;
31348761c62SAndrew Jeffery header.command = PLDM_GET_PLDM_VERSION;
31448761c62SAndrew Jeffery
31548761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
31648761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
31748761c62SAndrew Jeffery return rc;
31848761c62SAndrew Jeffery }
31948761c62SAndrew Jeffery
32048761c62SAndrew Jeffery struct pldm_get_version_req *request =
32148761c62SAndrew Jeffery (struct pldm_get_version_req *)msg->payload;
32248761c62SAndrew Jeffery transfer_handle = htole32(transfer_handle);
32348761c62SAndrew Jeffery request->transfer_handle = transfer_handle;
32448761c62SAndrew Jeffery request->transfer_opflag = transfer_opflag;
32548761c62SAndrew Jeffery request->type = type;
32648761c62SAndrew Jeffery
32748761c62SAndrew Jeffery return PLDM_SUCCESS;
32848761c62SAndrew Jeffery }
32948761c62SAndrew Jeffery
33036324f6bSAndrew Jeffery LIBPLDM_ABI_DEPRECATED_UNSAFE
encode_get_version_resp(uint8_t instance_id,uint8_t completion_code,uint32_t next_transfer_handle,uint8_t transfer_flag,const ver32_t * version_data,size_t version_size,struct pldm_msg * msg)33148761c62SAndrew Jeffery int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
33248761c62SAndrew Jeffery uint32_t next_transfer_handle,
33348761c62SAndrew Jeffery uint8_t transfer_flag, const ver32_t *version_data,
33448761c62SAndrew Jeffery size_t version_size, struct pldm_msg *msg)
33548761c62SAndrew Jeffery {
33636324f6bSAndrew Jeffery if (NULL == msg || NULL == version_data) {
33748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
33848761c62SAndrew Jeffery }
33948761c62SAndrew Jeffery
34048761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
34148761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
34248761c62SAndrew Jeffery header.instance = instance_id;
34348761c62SAndrew Jeffery header.pldm_type = PLDM_BASE;
34448761c62SAndrew Jeffery header.command = PLDM_GET_PLDM_VERSION;
34548761c62SAndrew Jeffery
34648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
34748761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
34848761c62SAndrew Jeffery return rc;
34948761c62SAndrew Jeffery }
35048761c62SAndrew Jeffery
35148761c62SAndrew Jeffery struct pldm_get_version_resp *response =
35248761c62SAndrew Jeffery (struct pldm_get_version_resp *)msg->payload;
35348761c62SAndrew Jeffery response->completion_code = completion_code;
35448761c62SAndrew Jeffery if (response->completion_code == PLDM_SUCCESS) {
35548761c62SAndrew Jeffery response->next_transfer_handle = htole32(next_transfer_handle);
35648761c62SAndrew Jeffery response->transfer_flag = transfer_flag;
35748761c62SAndrew Jeffery memcpy(response->version_data, (uint8_t *)version_data,
35848761c62SAndrew Jeffery version_size);
35948761c62SAndrew Jeffery }
36048761c62SAndrew Jeffery return PLDM_SUCCESS;
36148761c62SAndrew Jeffery }
36248761c62SAndrew Jeffery
36348761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_get_version_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * transfer_handle,uint8_t * transfer_opflag,uint8_t * type)36448761c62SAndrew Jeffery int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
36548761c62SAndrew Jeffery uint32_t *transfer_handle, uint8_t *transfer_opflag,
36648761c62SAndrew Jeffery uint8_t *type)
36748761c62SAndrew Jeffery {
36848761c62SAndrew Jeffery if (payload_length != PLDM_GET_VERSION_REQ_BYTES) {
36948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
37048761c62SAndrew Jeffery }
37148761c62SAndrew Jeffery
37248761c62SAndrew Jeffery struct pldm_get_version_req *request =
37348761c62SAndrew Jeffery (struct pldm_get_version_req *)msg->payload;
37448761c62SAndrew Jeffery *transfer_handle = le32toh(request->transfer_handle);
37548761c62SAndrew Jeffery *transfer_opflag = request->transfer_opflag;
37648761c62SAndrew Jeffery *type = request->type;
37748761c62SAndrew Jeffery return PLDM_SUCCESS;
37848761c62SAndrew Jeffery }
37948761c62SAndrew Jeffery
38048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_get_version_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * next_transfer_handle,uint8_t * transfer_flag,ver32_t * version)38148761c62SAndrew Jeffery int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
38248761c62SAndrew Jeffery uint8_t *completion_code,
38348761c62SAndrew Jeffery uint32_t *next_transfer_handle,
38448761c62SAndrew Jeffery uint8_t *transfer_flag, ver32_t *version)
38548761c62SAndrew Jeffery {
38648761c62SAndrew Jeffery if (msg == NULL || next_transfer_handle == NULL ||
38748761c62SAndrew Jeffery transfer_flag == NULL || completion_code == NULL) {
38848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
38948761c62SAndrew Jeffery }
39048761c62SAndrew Jeffery
39148761c62SAndrew Jeffery *completion_code = msg->payload[0];
39248761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
39348761c62SAndrew Jeffery return PLDM_SUCCESS;
39448761c62SAndrew Jeffery }
39548761c62SAndrew Jeffery
39648761c62SAndrew Jeffery if (payload_length < PLDM_GET_VERSION_RESP_BYTES) {
39748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
39848761c62SAndrew Jeffery }
39948761c62SAndrew Jeffery
40048761c62SAndrew Jeffery struct pldm_get_version_resp *response =
40148761c62SAndrew Jeffery (struct pldm_get_version_resp *)msg->payload;
40248761c62SAndrew Jeffery
40348761c62SAndrew Jeffery *next_transfer_handle = le32toh(response->next_transfer_handle);
40448761c62SAndrew Jeffery *transfer_flag = response->transfer_flag;
40548761c62SAndrew Jeffery memcpy(version, (uint8_t *)response->version_data, sizeof(ver32_t));
40648761c62SAndrew Jeffery
40748761c62SAndrew Jeffery return PLDM_SUCCESS;
40848761c62SAndrew Jeffery }
40948761c62SAndrew Jeffery
41048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_tid_req(uint8_t instance_id,struct pldm_msg * msg)41148761c62SAndrew Jeffery int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg)
41248761c62SAndrew Jeffery {
41348761c62SAndrew Jeffery if (msg == NULL) {
41448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
41548761c62SAndrew Jeffery }
41648761c62SAndrew Jeffery
41748761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
41848761c62SAndrew Jeffery header.instance = instance_id;
41948761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
42048761c62SAndrew Jeffery header.command = PLDM_GET_TID;
42148761c62SAndrew Jeffery
42248761c62SAndrew Jeffery return pack_pldm_header(&header, &(msg->hdr));
42348761c62SAndrew Jeffery }
42448761c62SAndrew Jeffery
42548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_tid_resp(uint8_t instance_id,uint8_t completion_code,uint8_t tid,struct pldm_msg * msg)42648761c62SAndrew Jeffery int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
42748761c62SAndrew Jeffery uint8_t tid, struct pldm_msg *msg)
42848761c62SAndrew Jeffery {
42948761c62SAndrew Jeffery if (msg == NULL) {
43048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
43148761c62SAndrew Jeffery }
43248761c62SAndrew Jeffery
43348761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
43448761c62SAndrew Jeffery header.instance = instance_id;
43548761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
43648761c62SAndrew Jeffery header.command = PLDM_GET_TID;
43748761c62SAndrew Jeffery
43848761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
43948761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
44048761c62SAndrew Jeffery return rc;
44148761c62SAndrew Jeffery }
44248761c62SAndrew Jeffery
44348761c62SAndrew Jeffery struct pldm_get_tid_resp *response =
44448761c62SAndrew Jeffery (struct pldm_get_tid_resp *)msg->payload;
44548761c62SAndrew Jeffery response->completion_code = completion_code;
44648761c62SAndrew Jeffery response->tid = tid;
44748761c62SAndrew Jeffery
44848761c62SAndrew Jeffery return PLDM_SUCCESS;
44948761c62SAndrew Jeffery }
45048761c62SAndrew Jeffery
45148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_get_tid_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * tid)45248761c62SAndrew Jeffery int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
45348761c62SAndrew Jeffery uint8_t *completion_code, uint8_t *tid)
45448761c62SAndrew Jeffery {
45548761c62SAndrew Jeffery if (msg == NULL || tid == NULL || completion_code == NULL) {
45648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
45748761c62SAndrew Jeffery }
45848761c62SAndrew Jeffery
45948761c62SAndrew Jeffery *completion_code = msg->payload[0];
46048761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
46148761c62SAndrew Jeffery return PLDM_SUCCESS;
46248761c62SAndrew Jeffery }
46348761c62SAndrew Jeffery
46448761c62SAndrew Jeffery if (payload_length != PLDM_GET_TID_RESP_BYTES) {
46548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
46648761c62SAndrew Jeffery }
46748761c62SAndrew Jeffery
46848761c62SAndrew Jeffery struct pldm_get_tid_resp *response =
46948761c62SAndrew Jeffery (struct pldm_get_tid_resp *)msg->payload;
47048761c62SAndrew Jeffery
47148761c62SAndrew Jeffery *tid = response->tid;
47248761c62SAndrew Jeffery
47348761c62SAndrew Jeffery return PLDM_SUCCESS;
47448761c62SAndrew Jeffery }
47548761c62SAndrew Jeffery
47648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_set_tid_req(uint8_t instance_id,uint8_t tid,struct pldm_msg * msg)47748761c62SAndrew Jeffery int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg)
47848761c62SAndrew Jeffery {
47948761c62SAndrew Jeffery if (msg == NULL) {
48048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
48148761c62SAndrew Jeffery }
48248761c62SAndrew Jeffery
48348761c62SAndrew Jeffery if (tid == 0x0 || tid == 0xff) {
48448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
48548761c62SAndrew Jeffery }
48648761c62SAndrew Jeffery
48748761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
48848761c62SAndrew Jeffery header.instance = instance_id;
48948761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
49048761c62SAndrew Jeffery header.command = PLDM_SET_TID;
49148761c62SAndrew Jeffery
49248761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
49348761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
49448761c62SAndrew Jeffery return rc;
49548761c62SAndrew Jeffery }
49648761c62SAndrew Jeffery
49748761c62SAndrew Jeffery struct pldm_set_tid_req *request =
49848761c62SAndrew Jeffery (struct pldm_set_tid_req *)msg->payload;
49948761c62SAndrew Jeffery request->tid = tid;
50048761c62SAndrew Jeffery
50148761c62SAndrew Jeffery return PLDM_SUCCESS;
50248761c62SAndrew Jeffery }
50348761c62SAndrew Jeffery
50448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
decode_multipart_receive_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * pldm_type,uint8_t * transfer_opflag,uint32_t * transfer_ctx,uint32_t * transfer_handle,uint32_t * section_offset,uint32_t * section_length)50548761c62SAndrew Jeffery int decode_multipart_receive_req(const struct pldm_msg *msg,
50648761c62SAndrew Jeffery size_t payload_length, uint8_t *pldm_type,
50748761c62SAndrew Jeffery uint8_t *transfer_opflag,
50848761c62SAndrew Jeffery uint32_t *transfer_ctx,
50948761c62SAndrew Jeffery uint32_t *transfer_handle,
51048761c62SAndrew Jeffery uint32_t *section_offset,
51148761c62SAndrew Jeffery uint32_t *section_length)
51248761c62SAndrew Jeffery {
51348761c62SAndrew Jeffery if (msg == NULL || pldm_type == NULL || transfer_opflag == NULL ||
51448761c62SAndrew Jeffery transfer_ctx == NULL || transfer_handle == NULL ||
51548761c62SAndrew Jeffery section_offset == NULL || section_length == NULL) {
51648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
51748761c62SAndrew Jeffery }
51848761c62SAndrew Jeffery
51948761c62SAndrew Jeffery if (payload_length != PLDM_MULTIPART_RECEIVE_REQ_BYTES) {
52048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
52148761c62SAndrew Jeffery }
52248761c62SAndrew Jeffery
52348761c62SAndrew Jeffery struct pldm_multipart_receive_req *request =
52448761c62SAndrew Jeffery (struct pldm_multipart_receive_req *)msg->payload;
52548761c62SAndrew Jeffery
52648761c62SAndrew Jeffery if (request->pldm_type != PLDM_BASE) {
52748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_PLDM_TYPE;
52848761c62SAndrew Jeffery }
52948761c62SAndrew Jeffery
53048761c62SAndrew Jeffery // Any enum value above PLDM_XFER_CURRENT_PART is invalid.
53148761c62SAndrew Jeffery if (request->transfer_opflag > PLDM_XFER_CURRENT_PART) {
53248761c62SAndrew Jeffery return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
53348761c62SAndrew Jeffery }
53448761c62SAndrew Jeffery
53548761c62SAndrew Jeffery // A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers.
53648761c62SAndrew Jeffery uint32_t sec_offset = le32toh(request->section_offset);
53748761c62SAndrew Jeffery if (sec_offset == 0 &&
53848761c62SAndrew Jeffery (request->transfer_opflag != PLDM_XFER_FIRST_PART &&
53948761c62SAndrew Jeffery request->transfer_opflag != PLDM_XFER_COMPLETE)) {
54048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
54148761c62SAndrew Jeffery }
54248761c62SAndrew Jeffery
54348761c62SAndrew Jeffery uint32_t handle = le32toh(request->transfer_handle);
54448761c62SAndrew Jeffery if (handle == 0 && request->transfer_opflag != PLDM_XFER_COMPLETE) {
54548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
54648761c62SAndrew Jeffery }
54748761c62SAndrew Jeffery
54848761c62SAndrew Jeffery *pldm_type = request->pldm_type;
54948761c62SAndrew Jeffery *transfer_opflag = request->transfer_opflag;
55048761c62SAndrew Jeffery *transfer_ctx = request->transfer_ctx;
55148761c62SAndrew Jeffery *transfer_handle = handle;
55248761c62SAndrew Jeffery *section_offset = sec_offset;
55348761c62SAndrew Jeffery *section_length = le32toh(request->section_length);
55448761c62SAndrew Jeffery
55548761c62SAndrew Jeffery return PLDM_SUCCESS;
55648761c62SAndrew Jeffery }
55748761c62SAndrew Jeffery
55848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_cc_only_resp(uint8_t instance_id,uint8_t type,uint8_t command,uint8_t cc,struct pldm_msg * msg)55948761c62SAndrew Jeffery int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
56048761c62SAndrew Jeffery uint8_t cc, struct pldm_msg *msg)
56148761c62SAndrew Jeffery {
56248761c62SAndrew Jeffery if (msg == NULL) {
56348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
56448761c62SAndrew Jeffery }
56548761c62SAndrew Jeffery
56648761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
56748761c62SAndrew Jeffery header.instance = instance_id;
56848761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
56948761c62SAndrew Jeffery header.pldm_type = type;
57048761c62SAndrew Jeffery header.command = command;
57148761c62SAndrew Jeffery
57248761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &msg->hdr);
57348761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
57448761c62SAndrew Jeffery return rc;
57548761c62SAndrew Jeffery }
57648761c62SAndrew Jeffery
57748761c62SAndrew Jeffery msg->payload[0] = cc;
57848761c62SAndrew Jeffery
57948761c62SAndrew Jeffery return PLDM_SUCCESS;
58048761c62SAndrew Jeffery }
58148761c62SAndrew Jeffery
encode_pldm_header_only_errno(uint8_t msg_type,uint8_t instance_id,uint8_t pldm_type,uint8_t command,struct pldm_msg * msg)582*eb8bb17fSUnive Tien int encode_pldm_header_only_errno(uint8_t msg_type, uint8_t instance_id,
58348761c62SAndrew Jeffery uint8_t pldm_type, uint8_t command,
58448761c62SAndrew Jeffery struct pldm_msg *msg)
58548761c62SAndrew Jeffery {
58648761c62SAndrew Jeffery if (msg == NULL) {
587*eb8bb17fSUnive Tien return -EINVAL;
58848761c62SAndrew Jeffery }
58948761c62SAndrew Jeffery
59048761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
59148761c62SAndrew Jeffery header.msg_type = msg_type;
59248761c62SAndrew Jeffery header.instance = instance_id;
59348761c62SAndrew Jeffery header.pldm_type = pldm_type;
59448761c62SAndrew Jeffery header.command = command;
595*eb8bb17fSUnive Tien return pack_pldm_header_errno(&header, &(msg->hdr));
596*eb8bb17fSUnive Tien }
597*eb8bb17fSUnive Tien
598*eb8bb17fSUnive Tien LIBPLDM_ABI_STABLE
encode_pldm_header_only(uint8_t msg_type,uint8_t instance_id,uint8_t pldm_type,uint8_t command,struct pldm_msg * msg)599*eb8bb17fSUnive Tien int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
600*eb8bb17fSUnive Tien uint8_t pldm_type, uint8_t command,
601*eb8bb17fSUnive Tien struct pldm_msg *msg)
602*eb8bb17fSUnive Tien {
603*eb8bb17fSUnive Tien int rc = encode_pldm_header_only_errno(msg_type, instance_id, pldm_type,
604*eb8bb17fSUnive Tien command, msg);
605*eb8bb17fSUnive Tien if (rc) {
606*eb8bb17fSUnive Tien return pldm_xlate_errno(rc);
607*eb8bb17fSUnive Tien }
608*eb8bb17fSUnive Tien return PLDM_SUCCESS;
60948761c62SAndrew Jeffery }
610