xref: /openbmc/libpldm/src/dsp/platform.c (revision 387b10f6cd37746778baef7dcc1acd84409774f8)
148761c62SAndrew Jeffery /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2f490a38fSTal Yacobi #include "dsp/base.h"
348761c62SAndrew Jeffery #include "msgbuf.h"
448761c62SAndrew Jeffery #include "msgbuf/platform.h"
548761c62SAndrew Jeffery 
648761c62SAndrew Jeffery #include <libpldm/base.h>
748761c62SAndrew Jeffery #include <libpldm/platform.h>
848761c62SAndrew Jeffery #include <libpldm/pldm_types.h>
948761c62SAndrew Jeffery 
1048761c62SAndrew Jeffery #include <endian.h>
1148761c62SAndrew Jeffery #include <stdint.h>
1248761c62SAndrew Jeffery #include <stdlib.h>
1348761c62SAndrew Jeffery #include <string.h>
14dacfa354SThu Nguyen #include <uchar.h>
1548761c62SAndrew Jeffery 
1648761c62SAndrew Jeffery static int pldm_platform_pdr_hdr_validate(struct pldm_value_pdr_hdr *ctx,
1748761c62SAndrew Jeffery 					  size_t lower, size_t upper)
1848761c62SAndrew Jeffery {
1948761c62SAndrew Jeffery 	if (ctx->length + sizeof(*ctx) < lower) {
2048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
2148761c62SAndrew Jeffery 	}
2248761c62SAndrew Jeffery 
2348761c62SAndrew Jeffery 	if (ctx->length > upper) {
2448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
2548761c62SAndrew Jeffery 	}
2648761c62SAndrew Jeffery 
2748761c62SAndrew Jeffery 	return PLDM_SUCCESS;
2848761c62SAndrew Jeffery }
2948761c62SAndrew Jeffery 
3048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
3148761c62SAndrew Jeffery int encode_state_effecter_pdr(
3248761c62SAndrew Jeffery 	struct pldm_state_effecter_pdr *const effecter,
3348761c62SAndrew Jeffery 	const size_t allocation_size,
3448761c62SAndrew Jeffery 	const struct state_effecter_possible_states *const possible_states,
3548761c62SAndrew Jeffery 	const size_t possible_states_size, size_t *const actual_size)
3648761c62SAndrew Jeffery {
3748761c62SAndrew Jeffery 	// Encode possible states
3848761c62SAndrew Jeffery 
3948761c62SAndrew Jeffery 	size_t calculated_possible_states_size = 0;
4048761c62SAndrew Jeffery 
4148761c62SAndrew Jeffery 	{
4248761c62SAndrew Jeffery 		char *states_ptr = (char *)possible_states;
4348761c62SAndrew Jeffery 		char *const begin_states_ptr = states_ptr;
4448761c62SAndrew Jeffery 
4548761c62SAndrew Jeffery 		for (int i = 0; i < effecter->composite_effecter_count; ++i) {
4648761c62SAndrew Jeffery 			struct state_effecter_possible_states *states =
4748761c62SAndrew Jeffery 				(struct state_effecter_possible_states *)
4848761c62SAndrew Jeffery 					states_ptr;
4948761c62SAndrew Jeffery 
5048761c62SAndrew Jeffery 			HTOLE16(states->state_set_id);
5148761c62SAndrew Jeffery 
5248761c62SAndrew Jeffery 			states_ptr +=
5348761c62SAndrew Jeffery 				(sizeof(*states) - sizeof(states->states) +
5448761c62SAndrew Jeffery 				 states->possible_states_size);
5548761c62SAndrew Jeffery 		}
5648761c62SAndrew Jeffery 
5748761c62SAndrew Jeffery 		calculated_possible_states_size = states_ptr - begin_states_ptr;
5848761c62SAndrew Jeffery 	}
5948761c62SAndrew Jeffery 
6048761c62SAndrew Jeffery 	// Check lengths
6148761c62SAndrew Jeffery 
6248761c62SAndrew Jeffery 	if (possible_states_size != calculated_possible_states_size) {
6348761c62SAndrew Jeffery 		*actual_size = 0;
6448761c62SAndrew Jeffery 		return PLDM_ERROR;
6548761c62SAndrew Jeffery 	}
6648761c62SAndrew Jeffery 
6748761c62SAndrew Jeffery 	*actual_size =
6848761c62SAndrew Jeffery 		(sizeof(struct pldm_state_effecter_pdr) + possible_states_size -
6948761c62SAndrew Jeffery 		 sizeof(effecter->possible_states));
7048761c62SAndrew Jeffery 
7148761c62SAndrew Jeffery 	if (allocation_size < *actual_size) {
7248761c62SAndrew Jeffery 		*actual_size = 0;
7348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
7448761c62SAndrew Jeffery 	}
7548761c62SAndrew Jeffery 
7648761c62SAndrew Jeffery 	// Encode rest of PDR
7748761c62SAndrew Jeffery 
7848761c62SAndrew Jeffery 	effecter->hdr.version = 1;
7948761c62SAndrew Jeffery 	effecter->hdr.type = PLDM_STATE_EFFECTER_PDR;
8048761c62SAndrew Jeffery 	effecter->hdr.length = *actual_size - sizeof(struct pldm_pdr_hdr);
8148761c62SAndrew Jeffery 
8248761c62SAndrew Jeffery 	memcpy(effecter->possible_states, possible_states,
8348761c62SAndrew Jeffery 	       possible_states_size);
8448761c62SAndrew Jeffery 
8548761c62SAndrew Jeffery 	// Convert effecter PDR body
8648761c62SAndrew Jeffery 	HTOLE16(effecter->terminus_handle);
8748761c62SAndrew Jeffery 	HTOLE16(effecter->effecter_id);
8848761c62SAndrew Jeffery 	HTOLE16(effecter->entity_type);
8948761c62SAndrew Jeffery 	HTOLE16(effecter->entity_instance);
9048761c62SAndrew Jeffery 	HTOLE16(effecter->container_id);
9148761c62SAndrew Jeffery 	HTOLE16(effecter->effecter_semantic_id);
9248761c62SAndrew Jeffery 
9348761c62SAndrew Jeffery 	// Convert header
9448761c62SAndrew Jeffery 	HTOLE32(effecter->hdr.record_handle);
9548761c62SAndrew Jeffery 	HTOLE16(effecter->hdr.record_change_num);
9648761c62SAndrew Jeffery 	HTOLE16(effecter->hdr.length);
9748761c62SAndrew Jeffery 
9848761c62SAndrew Jeffery 	return PLDM_SUCCESS;
9948761c62SAndrew Jeffery }
10048761c62SAndrew Jeffery 
10148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
10248761c62SAndrew Jeffery int encode_state_sensor_pdr(
10348761c62SAndrew Jeffery 	struct pldm_state_sensor_pdr *const sensor,
10448761c62SAndrew Jeffery 	const size_t allocation_size,
10548761c62SAndrew Jeffery 	const struct state_sensor_possible_states *const possible_states,
10648761c62SAndrew Jeffery 	const size_t possible_states_size, size_t *const actual_size)
10748761c62SAndrew Jeffery {
10848761c62SAndrew Jeffery 	// Encode possible states
10948761c62SAndrew Jeffery 
11048761c62SAndrew Jeffery 	size_t calculated_possible_states_size = 0;
11148761c62SAndrew Jeffery 
11248761c62SAndrew Jeffery 	{
11348761c62SAndrew Jeffery 		char *states_ptr = (char *)possible_states;
11448761c62SAndrew Jeffery 		char *const begin_states_ptr = states_ptr;
11548761c62SAndrew Jeffery 
11648761c62SAndrew Jeffery 		for (int i = 0; i < sensor->composite_sensor_count; ++i) {
11748761c62SAndrew Jeffery 			struct state_sensor_possible_states *states =
11848761c62SAndrew Jeffery 				(struct state_sensor_possible_states *)
11948761c62SAndrew Jeffery 					states_ptr;
12048761c62SAndrew Jeffery 
12148761c62SAndrew Jeffery 			HTOLE16(states->state_set_id);
12248761c62SAndrew Jeffery 
12348761c62SAndrew Jeffery 			states_ptr +=
12448761c62SAndrew Jeffery 				(sizeof(*states) - sizeof(states->states) +
12548761c62SAndrew Jeffery 				 states->possible_states_size);
12648761c62SAndrew Jeffery 		}
12748761c62SAndrew Jeffery 
12848761c62SAndrew Jeffery 		calculated_possible_states_size = states_ptr - begin_states_ptr;
12948761c62SAndrew Jeffery 	}
13048761c62SAndrew Jeffery 
13148761c62SAndrew Jeffery 	// Check lengths
13248761c62SAndrew Jeffery 
13348761c62SAndrew Jeffery 	if (possible_states_size != calculated_possible_states_size) {
13448761c62SAndrew Jeffery 		*actual_size = 0;
13548761c62SAndrew Jeffery 		return PLDM_ERROR;
13648761c62SAndrew Jeffery 	}
13748761c62SAndrew Jeffery 
13848761c62SAndrew Jeffery 	*actual_size = (sizeof(struct pldm_state_sensor_pdr) +
13948761c62SAndrew Jeffery 			possible_states_size - sizeof(sensor->possible_states));
14048761c62SAndrew Jeffery 
14148761c62SAndrew Jeffery 	if (allocation_size < *actual_size) {
14248761c62SAndrew Jeffery 		*actual_size = 0;
14348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
14448761c62SAndrew Jeffery 	}
14548761c62SAndrew Jeffery 
14648761c62SAndrew Jeffery 	// Encode rest of PDR
14748761c62SAndrew Jeffery 
14848761c62SAndrew Jeffery 	sensor->hdr.version = 1;
14948761c62SAndrew Jeffery 	sensor->hdr.type = PLDM_STATE_SENSOR_PDR;
15048761c62SAndrew Jeffery 	sensor->hdr.length = *actual_size - sizeof(struct pldm_pdr_hdr);
15148761c62SAndrew Jeffery 
15248761c62SAndrew Jeffery 	memcpy(sensor->possible_states, possible_states, possible_states_size);
15348761c62SAndrew Jeffery 
15448761c62SAndrew Jeffery 	// Convert sensor PDR body
15548761c62SAndrew Jeffery 	HTOLE16(sensor->terminus_handle);
15648761c62SAndrew Jeffery 	HTOLE16(sensor->sensor_id);
15748761c62SAndrew Jeffery 	HTOLE16(sensor->entity_type);
15848761c62SAndrew Jeffery 	HTOLE16(sensor->entity_instance);
15948761c62SAndrew Jeffery 	HTOLE16(sensor->container_id);
16048761c62SAndrew Jeffery 
16148761c62SAndrew Jeffery 	// Convert header
16248761c62SAndrew Jeffery 	HTOLE32(sensor->hdr.record_handle);
16348761c62SAndrew Jeffery 	HTOLE16(sensor->hdr.record_change_num);
16448761c62SAndrew Jeffery 	HTOLE16(sensor->hdr.length);
16548761c62SAndrew Jeffery 
16648761c62SAndrew Jeffery 	return PLDM_SUCCESS;
16748761c62SAndrew Jeffery }
16848761c62SAndrew Jeffery 
16948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
17048761c62SAndrew Jeffery int encode_set_state_effecter_states_resp(uint8_t instance_id,
17148761c62SAndrew Jeffery 					  uint8_t completion_code,
17248761c62SAndrew Jeffery 					  struct pldm_msg *msg)
17348761c62SAndrew Jeffery {
17448761c62SAndrew Jeffery 	if (msg == NULL) {
17548761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
17648761c62SAndrew Jeffery 	}
17748761c62SAndrew Jeffery 
17848761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
17948761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
18048761c62SAndrew Jeffery 	header.instance = instance_id;
18148761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
18248761c62SAndrew Jeffery 	header.command = PLDM_SET_STATE_EFFECTER_STATES;
18348761c62SAndrew Jeffery 
18448761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
18548761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
18648761c62SAndrew Jeffery 		return rc;
18748761c62SAndrew Jeffery 	}
18848761c62SAndrew Jeffery 
18948761c62SAndrew Jeffery 	msg->payload[0] = completion_code;
19048761c62SAndrew Jeffery 
19148761c62SAndrew Jeffery 	return PLDM_SUCCESS;
19248761c62SAndrew Jeffery }
19348761c62SAndrew Jeffery 
19448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
19548761c62SAndrew Jeffery int encode_set_state_effecter_states_req(uint8_t instance_id,
19648761c62SAndrew Jeffery 					 uint16_t effecter_id,
19748761c62SAndrew Jeffery 					 uint8_t comp_effecter_count,
19848761c62SAndrew Jeffery 					 set_effecter_state_field *field,
19948761c62SAndrew Jeffery 					 struct pldm_msg *msg)
20048761c62SAndrew Jeffery {
20148761c62SAndrew Jeffery 	if (msg == NULL) {
20248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
20348761c62SAndrew Jeffery 	}
20448761c62SAndrew Jeffery 
20548761c62SAndrew Jeffery 	if (comp_effecter_count < 0x1 || comp_effecter_count > 0x8 ||
20648761c62SAndrew Jeffery 	    field == NULL) {
20748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
20848761c62SAndrew Jeffery 	}
20948761c62SAndrew Jeffery 
21048761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
21148761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
21248761c62SAndrew Jeffery 	header.instance = instance_id;
21348761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
21448761c62SAndrew Jeffery 	header.command = PLDM_SET_STATE_EFFECTER_STATES;
21548761c62SAndrew Jeffery 
21648761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
21748761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
21848761c62SAndrew Jeffery 		return rc;
21948761c62SAndrew Jeffery 	}
22048761c62SAndrew Jeffery 
22148761c62SAndrew Jeffery 	struct pldm_set_state_effecter_states_req *request =
22248761c62SAndrew Jeffery 		(struct pldm_set_state_effecter_states_req *)msg->payload;
22348761c62SAndrew Jeffery 	effecter_id = htole16(effecter_id);
22448761c62SAndrew Jeffery 	request->effecter_id = effecter_id;
22548761c62SAndrew Jeffery 	request->comp_effecter_count = comp_effecter_count;
22648761c62SAndrew Jeffery 	memcpy(request->field, field,
22748761c62SAndrew Jeffery 	       (sizeof(set_effecter_state_field) * comp_effecter_count));
22848761c62SAndrew Jeffery 
22948761c62SAndrew Jeffery 	return PLDM_SUCCESS;
23048761c62SAndrew Jeffery }
23148761c62SAndrew Jeffery 
23248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
23348761c62SAndrew Jeffery int decode_set_state_effecter_states_resp(const struct pldm_msg *msg,
23448761c62SAndrew Jeffery 					  size_t payload_length,
23548761c62SAndrew Jeffery 					  uint8_t *completion_code)
23648761c62SAndrew Jeffery {
23748761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL) {
23848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
23948761c62SAndrew Jeffery 	}
24048761c62SAndrew Jeffery 
24148761c62SAndrew Jeffery 	*completion_code = msg->payload[0];
24248761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
24348761c62SAndrew Jeffery 		return PLDM_SUCCESS;
24448761c62SAndrew Jeffery 	}
24548761c62SAndrew Jeffery 
24648761c62SAndrew Jeffery 	if (payload_length > PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES) {
24748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
24848761c62SAndrew Jeffery 	}
24948761c62SAndrew Jeffery 
25048761c62SAndrew Jeffery 	return PLDM_SUCCESS;
25148761c62SAndrew Jeffery }
25248761c62SAndrew Jeffery 
25348761c62SAndrew Jeffery #define PLDM_SET_STATE_EFFECTER_STATES_MIN_SIZE 3
25448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
25548761c62SAndrew Jeffery int decode_set_state_effecter_states_req(const struct pldm_msg *msg,
25648761c62SAndrew Jeffery 					 size_t payload_length,
25748761c62SAndrew Jeffery 					 uint16_t *effecter_id,
25848761c62SAndrew Jeffery 					 uint8_t *comp_effecter_count,
25948761c62SAndrew Jeffery 					 set_effecter_state_field *field)
26048761c62SAndrew Jeffery {
26148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
26248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
26348761c62SAndrew Jeffery 	int rc;
26448761c62SAndrew Jeffery 	int i;
26548761c62SAndrew Jeffery 
26648761c62SAndrew Jeffery 	if (msg == NULL || effecter_id == NULL || comp_effecter_count == NULL ||
26748761c62SAndrew Jeffery 	    field == NULL) {
26848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
26948761c62SAndrew Jeffery 	}
27048761c62SAndrew Jeffery 
27148761c62SAndrew Jeffery 	if (payload_length > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) {
27248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
27348761c62SAndrew Jeffery 	}
27448761c62SAndrew Jeffery 
27548761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_SET_STATE_EFFECTER_STATES_MIN_SIZE,
27648761c62SAndrew Jeffery 				 msg->payload, payload_length);
27748761c62SAndrew Jeffery 	if (rc) {
27848761c62SAndrew Jeffery 		return rc;
27948761c62SAndrew Jeffery 	}
28048761c62SAndrew Jeffery 
28148761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, effecter_id);
28248761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, comp_effecter_count);
28348761c62SAndrew Jeffery 
28448761c62SAndrew Jeffery 	if (*comp_effecter_count > 8) {
28548761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
28648761c62SAndrew Jeffery 	}
28748761c62SAndrew Jeffery 
28848761c62SAndrew Jeffery 	for (i = 0; i < *comp_effecter_count; i++) {
28948761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field[i].set_request);
29048761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field[i].effecter_state);
29148761c62SAndrew Jeffery 	}
29248761c62SAndrew Jeffery 
29348761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
29448761c62SAndrew Jeffery }
29548761c62SAndrew Jeffery 
29648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
29748761c62SAndrew Jeffery int decode_get_pdr_req(const struct pldm_msg *msg, size_t payload_length,
29848761c62SAndrew Jeffery 		       uint32_t *record_hndl, uint32_t *data_transfer_hndl,
29948761c62SAndrew Jeffery 		       uint8_t *transfer_op_flag, uint16_t *request_cnt,
30048761c62SAndrew Jeffery 		       uint16_t *record_chg_num)
30148761c62SAndrew Jeffery {
30248761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
30348761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
30448761c62SAndrew Jeffery 	int rc;
30548761c62SAndrew Jeffery 
30648761c62SAndrew Jeffery 	if (msg == NULL || record_hndl == NULL || data_transfer_hndl == NULL ||
30748761c62SAndrew Jeffery 	    transfer_op_flag == NULL || request_cnt == NULL ||
30848761c62SAndrew Jeffery 	    record_chg_num == NULL) {
30948761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
31048761c62SAndrew Jeffery 	}
31148761c62SAndrew Jeffery 
31248761c62SAndrew Jeffery 	if (payload_length != PLDM_GET_PDR_REQ_BYTES) {
31348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
31448761c62SAndrew Jeffery 	}
31548761c62SAndrew Jeffery 
31648761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_GET_PDR_REQ_BYTES, msg->payload,
31748761c62SAndrew Jeffery 				 payload_length);
31848761c62SAndrew Jeffery 	if (rc) {
31948761c62SAndrew Jeffery 		return rc;
32048761c62SAndrew Jeffery 	}
32148761c62SAndrew Jeffery 
32248761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, record_hndl);
32348761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, data_transfer_hndl);
32448761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, transfer_op_flag);
32548761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, request_cnt);
32648761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, record_chg_num);
32748761c62SAndrew Jeffery 
32848761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
32948761c62SAndrew Jeffery }
33048761c62SAndrew Jeffery 
33148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
33248761c62SAndrew Jeffery int encode_get_pdr_resp(uint8_t instance_id, uint8_t completion_code,
33348761c62SAndrew Jeffery 			uint32_t next_record_hndl,
33448761c62SAndrew Jeffery 			uint32_t next_data_transfer_hndl, uint8_t transfer_flag,
33548761c62SAndrew Jeffery 			uint16_t resp_cnt, const uint8_t *record_data,
33648761c62SAndrew Jeffery 			uint8_t transfer_crc, struct pldm_msg *msg)
33748761c62SAndrew Jeffery {
33848761c62SAndrew Jeffery 	if (msg == NULL) {
33948761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
34048761c62SAndrew Jeffery 	}
34148761c62SAndrew Jeffery 
34248761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
34348761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
34448761c62SAndrew Jeffery 	header.instance = instance_id;
34548761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
34648761c62SAndrew Jeffery 	header.command = PLDM_GET_PDR;
34748761c62SAndrew Jeffery 
34848761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
34948761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
35048761c62SAndrew Jeffery 		return rc;
35148761c62SAndrew Jeffery 	}
35248761c62SAndrew Jeffery 
35348761c62SAndrew Jeffery 	struct pldm_get_pdr_resp *response =
35448761c62SAndrew Jeffery 		(struct pldm_get_pdr_resp *)msg->payload;
35548761c62SAndrew Jeffery 	response->completion_code = completion_code;
35648761c62SAndrew Jeffery 
35748761c62SAndrew Jeffery 	if (response->completion_code == PLDM_SUCCESS) {
35848761c62SAndrew Jeffery 		response->next_record_handle = htole32(next_record_hndl);
35948761c62SAndrew Jeffery 		response->next_data_transfer_handle =
36048761c62SAndrew Jeffery 			htole32(next_data_transfer_hndl);
36148761c62SAndrew Jeffery 		response->transfer_flag = transfer_flag;
36248761c62SAndrew Jeffery 		response->response_count = htole16(resp_cnt);
36348761c62SAndrew Jeffery 		if (record_data != NULL && resp_cnt > 0) {
36448761c62SAndrew Jeffery 			memcpy(response->record_data, record_data, resp_cnt);
36548761c62SAndrew Jeffery 		}
36648761c62SAndrew Jeffery 		if (transfer_flag == PLDM_END) {
36748761c62SAndrew Jeffery 			uint8_t *dst = msg->payload;
36848761c62SAndrew Jeffery 			dst += (sizeof(struct pldm_get_pdr_resp) - 1) +
36948761c62SAndrew Jeffery 			       resp_cnt;
37048761c62SAndrew Jeffery 			*dst = transfer_crc;
37148761c62SAndrew Jeffery 		}
37248761c62SAndrew Jeffery 	}
37348761c62SAndrew Jeffery 
37448761c62SAndrew Jeffery 	return PLDM_SUCCESS;
37548761c62SAndrew Jeffery }
37648761c62SAndrew Jeffery 
37748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
37848761c62SAndrew Jeffery int encode_get_pdr_repository_info_resp(
37948761c62SAndrew Jeffery 	uint8_t instance_id, uint8_t completion_code, uint8_t repository_state,
38048761c62SAndrew Jeffery 	const uint8_t *update_time, const uint8_t *oem_update_time,
38148761c62SAndrew Jeffery 	uint32_t record_count, uint32_t repository_size,
38248761c62SAndrew Jeffery 	uint32_t largest_record_size, uint8_t data_transfer_handle_timeout,
38348761c62SAndrew Jeffery 	struct pldm_msg *msg)
38448761c62SAndrew Jeffery {
38548761c62SAndrew Jeffery 	if (msg == NULL) {
38648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
38748761c62SAndrew Jeffery 	}
38848761c62SAndrew Jeffery 
38948761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
39048761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
39148761c62SAndrew Jeffery 	header.instance = instance_id;
39248761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
39348761c62SAndrew Jeffery 	header.command = PLDM_GET_PDR_REPOSITORY_INFO;
39448761c62SAndrew Jeffery 
39548761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
39648761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
39748761c62SAndrew Jeffery 		return rc;
39848761c62SAndrew Jeffery 	}
39948761c62SAndrew Jeffery 
40048761c62SAndrew Jeffery 	struct pldm_pdr_repository_info_resp *response =
40148761c62SAndrew Jeffery 		(struct pldm_pdr_repository_info_resp *)msg->payload;
40248761c62SAndrew Jeffery 	response->completion_code = completion_code;
40348761c62SAndrew Jeffery 
40448761c62SAndrew Jeffery 	if (response->completion_code == PLDM_SUCCESS) {
40548761c62SAndrew Jeffery 		response->repository_state = repository_state;
40648761c62SAndrew Jeffery 		if (update_time != NULL) {
40748761c62SAndrew Jeffery 			memcpy(response->update_time, update_time,
40848761c62SAndrew Jeffery 			       PLDM_TIMESTAMP104_SIZE);
40948761c62SAndrew Jeffery 		}
41048761c62SAndrew Jeffery 		if (oem_update_time != NULL) {
41148761c62SAndrew Jeffery 			memcpy(response->oem_update_time, oem_update_time,
41248761c62SAndrew Jeffery 			       PLDM_TIMESTAMP104_SIZE);
41348761c62SAndrew Jeffery 		}
41448761c62SAndrew Jeffery 		response->record_count = htole32(record_count);
41548761c62SAndrew Jeffery 		response->repository_size = htole32(repository_size);
41648761c62SAndrew Jeffery 		response->largest_record_size = htole32(largest_record_size);
41748761c62SAndrew Jeffery 		response->data_transfer_handle_timeout =
41848761c62SAndrew Jeffery 			data_transfer_handle_timeout;
41948761c62SAndrew Jeffery 	}
42048761c62SAndrew Jeffery 
42148761c62SAndrew Jeffery 	return PLDM_SUCCESS;
42248761c62SAndrew Jeffery }
42348761c62SAndrew Jeffery 
4240a1be3cbSAndrew Jeffery LIBPLDM_ABI_DEPRECATED
42548761c62SAndrew Jeffery int decode_get_pdr_repository_info_resp(
42648761c62SAndrew Jeffery 	const struct pldm_msg *msg, size_t payload_length,
42748761c62SAndrew Jeffery 	uint8_t *completion_code, uint8_t *repository_state,
42848761c62SAndrew Jeffery 	uint8_t *update_time, uint8_t *oem_update_time, uint32_t *record_count,
42948761c62SAndrew Jeffery 	uint32_t *repository_size, uint32_t *largest_record_size,
43048761c62SAndrew Jeffery 	uint8_t *data_transfer_handle_timeout)
43148761c62SAndrew Jeffery {
43248761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
43348761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
43448761c62SAndrew Jeffery 	int rc;
43548761c62SAndrew Jeffery 
43648761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL ||
43748761c62SAndrew Jeffery 	    repository_state == NULL || update_time == NULL ||
43848761c62SAndrew Jeffery 	    oem_update_time == NULL || record_count == NULL ||
43948761c62SAndrew Jeffery 	    repository_size == NULL || largest_record_size == NULL ||
44048761c62SAndrew Jeffery 	    data_transfer_handle_timeout == NULL) {
44148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
44248761c62SAndrew Jeffery 	}
44348761c62SAndrew Jeffery 
44448761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES,
44548761c62SAndrew Jeffery 				 msg->payload, payload_length);
44648761c62SAndrew Jeffery 	if (rc) {
44748761c62SAndrew Jeffery 		return rc;
44848761c62SAndrew Jeffery 	}
44948761c62SAndrew Jeffery 
45048761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, completion_code);
45148761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
45248761c62SAndrew Jeffery 		return PLDM_SUCCESS;
45348761c62SAndrew Jeffery 	}
45448761c62SAndrew Jeffery 
45548761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, repository_state);
45648761c62SAndrew Jeffery 	if (*repository_state > PLDM_FAILED) {
45748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
45848761c62SAndrew Jeffery 	}
45948761c62SAndrew Jeffery 
4600a1be3cbSAndrew Jeffery 	/* NOTE: Memory safety */
4610a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract_array(buf, PLDM_TIMESTAMP104_SIZE, update_time,
4620a1be3cbSAndrew Jeffery 				       PLDM_TIMESTAMP104_SIZE);
4630a1be3cbSAndrew Jeffery 	if (rc) {
4640a1be3cbSAndrew Jeffery 		return rc;
4650a1be3cbSAndrew Jeffery 	}
4660a1be3cbSAndrew Jeffery 
4670a1be3cbSAndrew Jeffery 	/* NOTE: Memory safety */
4680a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract_array(buf, PLDM_TIMESTAMP104_SIZE,
4690a1be3cbSAndrew Jeffery 				       oem_update_time, PLDM_TIMESTAMP104_SIZE);
4700a1be3cbSAndrew Jeffery 	if (rc) {
4710a1be3cbSAndrew Jeffery 		return rc;
4720a1be3cbSAndrew Jeffery 	}
4730a1be3cbSAndrew Jeffery 
47448761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, record_count);
47548761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, repository_size);
47648761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, largest_record_size);
47748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, data_transfer_handle_timeout);
47848761c62SAndrew Jeffery 
47948761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
48048761c62SAndrew Jeffery }
48148761c62SAndrew Jeffery 
4820a1be3cbSAndrew Jeffery LIBPLDM_ABI_TESTING
4830a1be3cbSAndrew Jeffery int decode_get_pdr_repository_info_resp_safe(
4840a1be3cbSAndrew Jeffery 	const struct pldm_msg *msg, size_t payload_length,
4850a1be3cbSAndrew Jeffery 	struct pldm_pdr_repository_info_resp *resp)
4860a1be3cbSAndrew Jeffery {
4870a1be3cbSAndrew Jeffery 	struct pldm_msgbuf _buf;
4880a1be3cbSAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
4890a1be3cbSAndrew Jeffery 	int rc;
4900a1be3cbSAndrew Jeffery 
4910a1be3cbSAndrew Jeffery 	if (msg == NULL || resp == NULL) {
4920a1be3cbSAndrew Jeffery 		return -EINVAL;
4930a1be3cbSAndrew Jeffery 	}
4940a1be3cbSAndrew Jeffery 
4950a1be3cbSAndrew Jeffery 	rc = pldm_msg_has_error(msg, payload_length);
4960a1be3cbSAndrew Jeffery 	if (rc) {
4970a1be3cbSAndrew Jeffery 		resp->completion_code = rc;
4980a1be3cbSAndrew Jeffery 		return 0;
4990a1be3cbSAndrew Jeffery 	}
5000a1be3cbSAndrew Jeffery 
5010a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_init_errno(buf,
5020a1be3cbSAndrew Jeffery 				    PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES,
5030a1be3cbSAndrew Jeffery 				    msg->payload, payload_length);
5040a1be3cbSAndrew Jeffery 	if (rc) {
5050a1be3cbSAndrew Jeffery 		return rc;
5060a1be3cbSAndrew Jeffery 	}
5070a1be3cbSAndrew Jeffery 
5080a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, resp->completion_code);
5090a1be3cbSAndrew Jeffery 	if (rc) {
5100a1be3cbSAndrew Jeffery 		return rc;
5110a1be3cbSAndrew Jeffery 	}
5120a1be3cbSAndrew Jeffery 
5130a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->repository_state);
5140a1be3cbSAndrew Jeffery 
5150a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract_array(buf, sizeof(resp->update_time),
5160a1be3cbSAndrew Jeffery 				       resp->update_time,
5170a1be3cbSAndrew Jeffery 				       sizeof(resp->update_time));
5180a1be3cbSAndrew Jeffery 	if (rc) {
5190a1be3cbSAndrew Jeffery 		return rc;
5200a1be3cbSAndrew Jeffery 	}
5210a1be3cbSAndrew Jeffery 
5220a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract_array(buf, sizeof(resp->oem_update_time),
5230a1be3cbSAndrew Jeffery 				       resp->oem_update_time,
5240a1be3cbSAndrew Jeffery 				       sizeof(resp->oem_update_time));
5250a1be3cbSAndrew Jeffery 	if (rc) {
5260a1be3cbSAndrew Jeffery 		return rc;
5270a1be3cbSAndrew Jeffery 	}
5280a1be3cbSAndrew Jeffery 
5290a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->record_count);
5300a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->repository_size);
5310a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->largest_record_size);
5320a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->data_transfer_handle_timeout);
5330a1be3cbSAndrew Jeffery 
5340a1be3cbSAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
5350a1be3cbSAndrew Jeffery }
5360a1be3cbSAndrew Jeffery 
53748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
53848761c62SAndrew Jeffery int encode_get_pdr_req(uint8_t instance_id, uint32_t record_hndl,
53948761c62SAndrew Jeffery 		       uint32_t data_transfer_hndl, uint8_t transfer_op_flag,
54048761c62SAndrew Jeffery 		       uint16_t request_cnt, uint16_t record_chg_num,
54148761c62SAndrew Jeffery 		       struct pldm_msg *msg, size_t payload_length)
54248761c62SAndrew Jeffery {
54348761c62SAndrew Jeffery 	if (msg == NULL) {
54448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
54548761c62SAndrew Jeffery 	}
54648761c62SAndrew Jeffery 
54748761c62SAndrew Jeffery 	if (payload_length != PLDM_GET_PDR_REQ_BYTES) {
54848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
54948761c62SAndrew Jeffery 	}
55048761c62SAndrew Jeffery 
55148761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
55248761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
55348761c62SAndrew Jeffery 	header.instance = instance_id;
55448761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
55548761c62SAndrew Jeffery 	header.command = PLDM_GET_PDR;
55648761c62SAndrew Jeffery 
55748761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
55848761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
55948761c62SAndrew Jeffery 		return rc;
56048761c62SAndrew Jeffery 	}
56148761c62SAndrew Jeffery 
56248761c62SAndrew Jeffery 	struct pldm_get_pdr_req *request =
56348761c62SAndrew Jeffery 		(struct pldm_get_pdr_req *)msg->payload;
56448761c62SAndrew Jeffery 	request->record_handle = htole32(record_hndl);
56548761c62SAndrew Jeffery 	request->data_transfer_handle = htole32(data_transfer_hndl);
56648761c62SAndrew Jeffery 	request->transfer_op_flag = transfer_op_flag;
56748761c62SAndrew Jeffery 	request->request_count = htole16(request_cnt);
56848761c62SAndrew Jeffery 	request->record_change_number = htole16(record_chg_num);
56948761c62SAndrew Jeffery 
57048761c62SAndrew Jeffery 	return PLDM_SUCCESS;
57148761c62SAndrew Jeffery }
57248761c62SAndrew Jeffery 
5730a1be3cbSAndrew Jeffery LIBPLDM_ABI_DEPRECATED
57448761c62SAndrew Jeffery int decode_get_pdr_resp(const struct pldm_msg *msg, size_t payload_length,
57548761c62SAndrew Jeffery 			uint8_t *completion_code, uint32_t *next_record_hndl,
57648761c62SAndrew Jeffery 			uint32_t *next_data_transfer_hndl,
57748761c62SAndrew Jeffery 			uint8_t *transfer_flag, uint16_t *resp_cnt,
57848761c62SAndrew Jeffery 			uint8_t *record_data, size_t record_data_length,
57948761c62SAndrew Jeffery 			uint8_t *transfer_crc)
58048761c62SAndrew Jeffery {
58148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
58248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
58348761c62SAndrew Jeffery 	int rc;
58448761c62SAndrew Jeffery 
58548761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL ||
58648761c62SAndrew Jeffery 	    next_record_hndl == NULL || next_data_transfer_hndl == NULL ||
58748761c62SAndrew Jeffery 	    transfer_flag == NULL || resp_cnt == NULL || transfer_crc == NULL) {
58848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
58948761c62SAndrew Jeffery 	}
59048761c62SAndrew Jeffery 
59148761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_GET_PDR_MIN_RESP_BYTES, msg->payload,
59248761c62SAndrew Jeffery 				 payload_length);
59348761c62SAndrew Jeffery 	if (rc) {
59448761c62SAndrew Jeffery 		return rc;
59548761c62SAndrew Jeffery 	}
59648761c62SAndrew Jeffery 
59748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, completion_code);
59848761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
59948761c62SAndrew Jeffery 		return PLDM_SUCCESS;
60048761c62SAndrew Jeffery 	}
60148761c62SAndrew Jeffery 
60248761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, next_record_hndl);
60348761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, next_data_transfer_hndl);
60448761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, transfer_flag);
60548761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, resp_cnt);
60648761c62SAndrew Jeffery 	if (rc) {
60748761c62SAndrew Jeffery 		return rc;
60848761c62SAndrew Jeffery 	}
60948761c62SAndrew Jeffery 
61048761c62SAndrew Jeffery 	if (*resp_cnt > 0 && record_data != NULL) {
61148761c62SAndrew Jeffery 		if (record_data_length < *resp_cnt) {
61248761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
61348761c62SAndrew Jeffery 		}
6140a1be3cbSAndrew Jeffery 		/* NOTE: Memory safety */
6150a1be3cbSAndrew Jeffery 		rc = pldm_msgbuf_extract_array(buf, *resp_cnt, record_data,
6160a1be3cbSAndrew Jeffery 					       *resp_cnt);
6170a1be3cbSAndrew Jeffery 		if (rc) {
6180a1be3cbSAndrew Jeffery 			return rc;
6190a1be3cbSAndrew Jeffery 		}
62048761c62SAndrew Jeffery 	}
62148761c62SAndrew Jeffery 
62248761c62SAndrew Jeffery 	if (*transfer_flag == PLDM_END) {
62348761c62SAndrew Jeffery 		pldm_msgbuf_extract_p(buf, transfer_crc);
62448761c62SAndrew Jeffery 	}
62548761c62SAndrew Jeffery 
62648761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
62748761c62SAndrew Jeffery }
62848761c62SAndrew Jeffery 
6290a1be3cbSAndrew Jeffery LIBPLDM_ABI_TESTING
6300a1be3cbSAndrew Jeffery int decode_get_pdr_resp_safe(const struct pldm_msg *msg, size_t payload_length,
6310a1be3cbSAndrew Jeffery 			     struct pldm_get_pdr_resp *resp, size_t resp_len,
6320a1be3cbSAndrew Jeffery 			     uint8_t *transfer_crc)
6330a1be3cbSAndrew Jeffery {
6340a1be3cbSAndrew Jeffery 	struct pldm_msgbuf _buf;
6350a1be3cbSAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
6360a1be3cbSAndrew Jeffery 	int rc;
6370a1be3cbSAndrew Jeffery 
6380a1be3cbSAndrew Jeffery 	if (msg == NULL || resp == NULL || transfer_crc == NULL) {
6390a1be3cbSAndrew Jeffery 		return -EINVAL;
6400a1be3cbSAndrew Jeffery 	}
6410a1be3cbSAndrew Jeffery 
6420a1be3cbSAndrew Jeffery 	rc = pldm_msg_has_error(msg, payload_length);
6430a1be3cbSAndrew Jeffery 	if (rc) {
6440a1be3cbSAndrew Jeffery 		resp->completion_code = rc;
6450a1be3cbSAndrew Jeffery 		return 0;
6460a1be3cbSAndrew Jeffery 	}
6470a1be3cbSAndrew Jeffery 
6480a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_PDR_MIN_RESP_BYTES,
6490a1be3cbSAndrew Jeffery 				    msg->payload, payload_length);
6500a1be3cbSAndrew Jeffery 	if (rc) {
6510a1be3cbSAndrew Jeffery 		return rc;
6520a1be3cbSAndrew Jeffery 	}
6530a1be3cbSAndrew Jeffery 
6540a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->completion_code);
6550a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->next_record_handle);
6560a1be3cbSAndrew Jeffery 	pldm_msgbuf_extract(buf, resp->next_data_transfer_handle);
6570a1be3cbSAndrew Jeffery 
6580a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, resp->transfer_flag);
6590a1be3cbSAndrew Jeffery 	if (rc) {
6600a1be3cbSAndrew Jeffery 		return rc;
6610a1be3cbSAndrew Jeffery 	}
6620a1be3cbSAndrew Jeffery 
6630a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, resp->response_count);
6640a1be3cbSAndrew Jeffery 	if (rc) {
6650a1be3cbSAndrew Jeffery 		return rc;
6660a1be3cbSAndrew Jeffery 	}
6670a1be3cbSAndrew Jeffery 
6680a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract_array(
6690a1be3cbSAndrew Jeffery 		buf, resp->response_count, resp->record_data,
6700a1be3cbSAndrew Jeffery 		resp_len - (sizeof(*resp) - sizeof(resp->record_data)));
6710a1be3cbSAndrew Jeffery 	if (rc) {
6720a1be3cbSAndrew Jeffery 		return rc;
6730a1be3cbSAndrew Jeffery 	}
6740a1be3cbSAndrew Jeffery 
6750a1be3cbSAndrew Jeffery 	if (resp->transfer_flag == PLDM_END) {
6760a1be3cbSAndrew Jeffery 		pldm_msgbuf_extract_p(buf, transfer_crc);
6770a1be3cbSAndrew Jeffery 	}
6780a1be3cbSAndrew Jeffery 
6790a1be3cbSAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
6800a1be3cbSAndrew Jeffery }
6810a1be3cbSAndrew Jeffery 
68248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
68348761c62SAndrew Jeffery int decode_set_numeric_effecter_value_req(const struct pldm_msg *msg,
68448761c62SAndrew Jeffery 					  size_t payload_length,
68548761c62SAndrew Jeffery 					  uint16_t *effecter_id,
68648761c62SAndrew Jeffery 					  uint8_t *effecter_data_size,
68748761c62SAndrew Jeffery 					  uint8_t effecter_value[4])
68848761c62SAndrew Jeffery {
68948761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
69048761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
69148761c62SAndrew Jeffery 	int rc;
69248761c62SAndrew Jeffery 
69348761c62SAndrew Jeffery 	if (msg == NULL || effecter_id == NULL || effecter_data_size == NULL ||
69448761c62SAndrew Jeffery 	    effecter_value == NULL) {
69548761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
69648761c62SAndrew Jeffery 	}
69748761c62SAndrew Jeffery 
69848761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf,
69948761c62SAndrew Jeffery 				 PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES,
70048761c62SAndrew Jeffery 				 msg->payload, payload_length);
70148761c62SAndrew Jeffery 	if (rc) {
70248761c62SAndrew Jeffery 		return rc;
70348761c62SAndrew Jeffery 	}
70448761c62SAndrew Jeffery 
70548761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, effecter_id);
70648761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, effecter_data_size);
70748761c62SAndrew Jeffery 	if (rc) {
70848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
70948761c62SAndrew Jeffery 	}
71048761c62SAndrew Jeffery 
71148761c62SAndrew Jeffery 	if (*effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
71248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
71348761c62SAndrew Jeffery 	}
71448761c62SAndrew Jeffery 
71548761c62SAndrew Jeffery 	pldm_msgbuf_extract_effecter_value(buf, *effecter_data_size,
71648761c62SAndrew Jeffery 					   effecter_value);
71748761c62SAndrew Jeffery 
71848761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
71948761c62SAndrew Jeffery }
72048761c62SAndrew Jeffery 
72148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
72248761c62SAndrew Jeffery int encode_set_numeric_effecter_value_resp(uint8_t instance_id,
72348761c62SAndrew Jeffery 					   uint8_t completion_code,
72448761c62SAndrew Jeffery 					   struct pldm_msg *msg,
72548761c62SAndrew Jeffery 					   size_t payload_length)
72648761c62SAndrew Jeffery {
72748761c62SAndrew Jeffery 	if (msg == NULL) {
72848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
72948761c62SAndrew Jeffery 	}
73048761c62SAndrew Jeffery 
73148761c62SAndrew Jeffery 	if (payload_length != PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES) {
73248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
73348761c62SAndrew Jeffery 	}
73448761c62SAndrew Jeffery 
73548761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
73648761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
73748761c62SAndrew Jeffery 	header.instance = instance_id;
73848761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
73948761c62SAndrew Jeffery 	header.command = PLDM_SET_NUMERIC_EFFECTER_VALUE;
74048761c62SAndrew Jeffery 
74148761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
74248761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
74348761c62SAndrew Jeffery 		return rc;
74448761c62SAndrew Jeffery 	}
74548761c62SAndrew Jeffery 
74648761c62SAndrew Jeffery 	msg->payload[0] = completion_code;
74748761c62SAndrew Jeffery 
74848761c62SAndrew Jeffery 	return rc;
74948761c62SAndrew Jeffery }
75048761c62SAndrew Jeffery 
75148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
75248761c62SAndrew Jeffery int encode_set_numeric_effecter_value_req(uint8_t instance_id,
75348761c62SAndrew Jeffery 					  uint16_t effecter_id,
75448761c62SAndrew Jeffery 					  uint8_t effecter_data_size,
75548761c62SAndrew Jeffery 					  const uint8_t *effecter_value,
75648761c62SAndrew Jeffery 					  struct pldm_msg *msg,
75748761c62SAndrew Jeffery 					  size_t payload_length)
75848761c62SAndrew Jeffery {
75948761c62SAndrew Jeffery 	if (msg == NULL || effecter_value == NULL) {
76048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
76148761c62SAndrew Jeffery 	}
76248761c62SAndrew Jeffery 
76348761c62SAndrew Jeffery 	if (effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
76448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
76548761c62SAndrew Jeffery 	}
76648761c62SAndrew Jeffery 
76748761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
76848761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
76948761c62SAndrew Jeffery 	header.instance = instance_id;
77048761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
77148761c62SAndrew Jeffery 	header.command = PLDM_SET_NUMERIC_EFFECTER_VALUE;
77248761c62SAndrew Jeffery 
77348761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
77448761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
77548761c62SAndrew Jeffery 		return rc;
77648761c62SAndrew Jeffery 	}
77748761c62SAndrew Jeffery 
77848761c62SAndrew Jeffery 	struct pldm_set_numeric_effecter_value_req *request =
77948761c62SAndrew Jeffery 		(struct pldm_set_numeric_effecter_value_req *)msg->payload;
78048761c62SAndrew Jeffery 	if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
78148761c62SAndrew Jeffery 	    effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
78248761c62SAndrew Jeffery 		if (payload_length !=
78348761c62SAndrew Jeffery 		    PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES) {
78448761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
78548761c62SAndrew Jeffery 		}
78648761c62SAndrew Jeffery 		request->effecter_value[0] = *effecter_value;
78748761c62SAndrew Jeffery 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
78848761c62SAndrew Jeffery 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
78948761c62SAndrew Jeffery 		if (payload_length !=
79048761c62SAndrew Jeffery 		    PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1) {
79148761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
79248761c62SAndrew Jeffery 		}
79348761c62SAndrew Jeffery 
79448761c62SAndrew Jeffery 		uint16_t val = *(uint16_t *)(effecter_value);
79548761c62SAndrew Jeffery 		val = htole16(val);
79648761c62SAndrew Jeffery 		memcpy(request->effecter_value, &val, sizeof(uint16_t));
79748761c62SAndrew Jeffery 
79848761c62SAndrew Jeffery 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
79948761c62SAndrew Jeffery 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
80048761c62SAndrew Jeffery 		if (payload_length !=
80148761c62SAndrew Jeffery 		    PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3) {
80248761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
80348761c62SAndrew Jeffery 		}
80448761c62SAndrew Jeffery 
80548761c62SAndrew Jeffery 		uint32_t val = *(uint32_t *)(effecter_value);
80648761c62SAndrew Jeffery 		val = htole32(val);
80748761c62SAndrew Jeffery 		memcpy(request->effecter_value, &val, sizeof(uint32_t));
80848761c62SAndrew Jeffery 	}
80948761c62SAndrew Jeffery 
81048761c62SAndrew Jeffery 	request->effecter_id = htole16(effecter_id);
81148761c62SAndrew Jeffery 	request->effecter_data_size = effecter_data_size;
81248761c62SAndrew Jeffery 
81348761c62SAndrew Jeffery 	return PLDM_SUCCESS;
81448761c62SAndrew Jeffery }
81548761c62SAndrew Jeffery 
81648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
81748761c62SAndrew Jeffery int decode_set_numeric_effecter_value_resp(const struct pldm_msg *msg,
81848761c62SAndrew Jeffery 					   size_t payload_length,
81948761c62SAndrew Jeffery 					   uint8_t *completion_code)
82048761c62SAndrew Jeffery {
82148761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL) {
82248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
82348761c62SAndrew Jeffery 	}
82448761c62SAndrew Jeffery 
82548761c62SAndrew Jeffery 	if (payload_length != PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES) {
82648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
82748761c62SAndrew Jeffery 	}
82848761c62SAndrew Jeffery 
82948761c62SAndrew Jeffery 	*completion_code = msg->payload[0];
83048761c62SAndrew Jeffery 
83148761c62SAndrew Jeffery 	return PLDM_SUCCESS;
83248761c62SAndrew Jeffery }
83348761c62SAndrew Jeffery 
83448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
83548761c62SAndrew Jeffery int encode_get_state_sensor_readings_resp(uint8_t instance_id,
83648761c62SAndrew Jeffery 					  uint8_t completion_code,
83748761c62SAndrew Jeffery 					  uint8_t comp_sensor_count,
83848761c62SAndrew Jeffery 					  get_sensor_state_field *field,
83948761c62SAndrew Jeffery 					  struct pldm_msg *msg)
84048761c62SAndrew Jeffery {
84148761c62SAndrew Jeffery 	if (msg == NULL) {
84248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
84348761c62SAndrew Jeffery 	}
84448761c62SAndrew Jeffery 
84548761c62SAndrew Jeffery 	if (comp_sensor_count < 0x1 || comp_sensor_count > 0x8) {
84648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
84748761c62SAndrew Jeffery 	}
84848761c62SAndrew Jeffery 
84948761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
85048761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
85148761c62SAndrew Jeffery 	header.instance = instance_id;
85248761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
85348761c62SAndrew Jeffery 	header.command = PLDM_GET_STATE_SENSOR_READINGS;
85448761c62SAndrew Jeffery 
85548761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
85648761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
85748761c62SAndrew Jeffery 		return rc;
85848761c62SAndrew Jeffery 	}
85948761c62SAndrew Jeffery 
86048761c62SAndrew Jeffery 	struct pldm_get_state_sensor_readings_resp *response =
86148761c62SAndrew Jeffery 		(struct pldm_get_state_sensor_readings_resp *)msg->payload;
86248761c62SAndrew Jeffery 
86348761c62SAndrew Jeffery 	response->completion_code = completion_code;
86448761c62SAndrew Jeffery 	response->comp_sensor_count = comp_sensor_count;
86548761c62SAndrew Jeffery 	memcpy(response->field, field,
86648761c62SAndrew Jeffery 	       (sizeof(get_sensor_state_field) * comp_sensor_count));
86748761c62SAndrew Jeffery 
86848761c62SAndrew Jeffery 	return PLDM_SUCCESS;
86948761c62SAndrew Jeffery }
87048761c62SAndrew Jeffery 
87148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
87248761c62SAndrew Jeffery int encode_get_state_sensor_readings_req(uint8_t instance_id,
87348761c62SAndrew Jeffery 					 uint16_t sensor_id,
87448761c62SAndrew Jeffery 					 bitfield8_t sensor_rearm,
87548761c62SAndrew Jeffery 					 uint8_t reserved, struct pldm_msg *msg)
87648761c62SAndrew Jeffery {
87748761c62SAndrew Jeffery 	if (msg == NULL) {
87848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
87948761c62SAndrew Jeffery 	}
88048761c62SAndrew Jeffery 
88148761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
88248761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
88348761c62SAndrew Jeffery 	header.instance = instance_id;
88448761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
88548761c62SAndrew Jeffery 	header.command = PLDM_GET_STATE_SENSOR_READINGS;
88648761c62SAndrew Jeffery 
88748761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
88848761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
88948761c62SAndrew Jeffery 		return rc;
89048761c62SAndrew Jeffery 	}
89148761c62SAndrew Jeffery 
89248761c62SAndrew Jeffery 	struct pldm_get_state_sensor_readings_req *request =
89348761c62SAndrew Jeffery 		(struct pldm_get_state_sensor_readings_req *)msg->payload;
89448761c62SAndrew Jeffery 
89548761c62SAndrew Jeffery 	request->sensor_id = htole16(sensor_id);
89648761c62SAndrew Jeffery 	request->reserved = reserved;
89748761c62SAndrew Jeffery 	request->sensor_rearm = sensor_rearm;
89848761c62SAndrew Jeffery 
89948761c62SAndrew Jeffery 	return PLDM_SUCCESS;
90048761c62SAndrew Jeffery }
90148761c62SAndrew Jeffery 
90248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
90348761c62SAndrew Jeffery int decode_get_state_sensor_readings_resp(const struct pldm_msg *msg,
90448761c62SAndrew Jeffery 					  size_t payload_length,
90548761c62SAndrew Jeffery 					  uint8_t *completion_code,
90648761c62SAndrew Jeffery 					  uint8_t *comp_sensor_count,
90748761c62SAndrew Jeffery 					  get_sensor_state_field *field)
90848761c62SAndrew Jeffery {
90948761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
91048761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
91148761c62SAndrew Jeffery 	uint8_t i;
91248761c62SAndrew Jeffery 	int rc;
91348761c62SAndrew Jeffery 
91448761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL ||
91548761c62SAndrew Jeffery 	    comp_sensor_count == NULL || field == NULL) {
91648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
91748761c62SAndrew Jeffery 	}
91848761c62SAndrew Jeffery 
91948761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf,
92048761c62SAndrew Jeffery 				 PLDM_GET_STATE_SENSOR_READINGS_MIN_RESP_BYTES,
92148761c62SAndrew Jeffery 				 msg->payload, payload_length);
92248761c62SAndrew Jeffery 	if (rc) {
92348761c62SAndrew Jeffery 		return rc;
92448761c62SAndrew Jeffery 	}
92548761c62SAndrew Jeffery 
92648761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, completion_code);
92748761c62SAndrew Jeffery 	if (rc) {
92848761c62SAndrew Jeffery 		return rc;
92948761c62SAndrew Jeffery 	}
93048761c62SAndrew Jeffery 
93148761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
93248761c62SAndrew Jeffery 		return PLDM_SUCCESS;
93348761c62SAndrew Jeffery 	}
93448761c62SAndrew Jeffery 
93548761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, comp_sensor_count);
93648761c62SAndrew Jeffery 	if (rc) {
93748761c62SAndrew Jeffery 		return rc;
93848761c62SAndrew Jeffery 	}
93948761c62SAndrew Jeffery 
94048761c62SAndrew Jeffery 	if (*comp_sensor_count < 0x1 || *comp_sensor_count > 0x8) {
94148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
94248761c62SAndrew Jeffery 	}
94348761c62SAndrew Jeffery 
94448761c62SAndrew Jeffery 	for (i = 0; i < *comp_sensor_count; i++) {
94548761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field[i].sensor_op_state);
94648761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field[i].present_state);
94748761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field[i].previous_state);
94848761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field[i].event_state);
94948761c62SAndrew Jeffery 	}
95048761c62SAndrew Jeffery 
95148761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
95248761c62SAndrew Jeffery }
95348761c62SAndrew Jeffery 
95448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
95548761c62SAndrew Jeffery int decode_get_state_sensor_readings_req(const struct pldm_msg *msg,
95648761c62SAndrew Jeffery 					 size_t payload_length,
95748761c62SAndrew Jeffery 					 uint16_t *sensor_id,
95848761c62SAndrew Jeffery 					 bitfield8_t *sensor_rearm,
95948761c62SAndrew Jeffery 					 uint8_t *reserved)
96048761c62SAndrew Jeffery {
96148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
96248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
96348761c62SAndrew Jeffery 	int rc;
96448761c62SAndrew Jeffery 
96548761c62SAndrew Jeffery 	if (msg == NULL || sensor_id == NULL || sensor_rearm == NULL) {
96648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
96748761c62SAndrew Jeffery 	}
96848761c62SAndrew Jeffery 
96948761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES,
97048761c62SAndrew Jeffery 				 msg->payload, payload_length);
97148761c62SAndrew Jeffery 	if (rc) {
97248761c62SAndrew Jeffery 		return rc;
97348761c62SAndrew Jeffery 	}
97448761c62SAndrew Jeffery 
97548761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, sensor_id);
97648761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, sensor_rearm->byte);
97748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, reserved);
97848761c62SAndrew Jeffery 
97948761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
98048761c62SAndrew Jeffery }
98148761c62SAndrew Jeffery 
98248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
98348761c62SAndrew Jeffery int encode_sensor_event_data(
98448761c62SAndrew Jeffery 	struct pldm_sensor_event_data *const event_data,
98548761c62SAndrew Jeffery 	const size_t event_data_size, const uint16_t sensor_id,
98648761c62SAndrew Jeffery 	const enum sensor_event_class_states sensor_event_class,
98748761c62SAndrew Jeffery 	const uint8_t sensor_offset, const uint8_t event_state,
98848761c62SAndrew Jeffery 	const uint8_t previous_event_state,
98948761c62SAndrew Jeffery 	size_t *const actual_event_data_size)
99048761c62SAndrew Jeffery {
99148761c62SAndrew Jeffery 	*actual_event_data_size =
99248761c62SAndrew Jeffery 		(sizeof(*event_data) - sizeof(event_data->event_class) +
99348761c62SAndrew Jeffery 		 sizeof(struct pldm_sensor_event_state_sensor_state));
99448761c62SAndrew Jeffery 
99548761c62SAndrew Jeffery 	if (!event_data) {
99648761c62SAndrew Jeffery 		return PLDM_SUCCESS;
99748761c62SAndrew Jeffery 	}
99848761c62SAndrew Jeffery 
99948761c62SAndrew Jeffery 	if (event_data_size < *actual_event_data_size) {
100048761c62SAndrew Jeffery 		*actual_event_data_size = 0;
100148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
100248761c62SAndrew Jeffery 	}
100348761c62SAndrew Jeffery 
100448761c62SAndrew Jeffery 	event_data->sensor_id = htole16(sensor_id);
100548761c62SAndrew Jeffery 	event_data->sensor_event_class_type = sensor_event_class;
100648761c62SAndrew Jeffery 
100748761c62SAndrew Jeffery 	struct pldm_sensor_event_state_sensor_state *const state_data =
100848761c62SAndrew Jeffery 		(struct pldm_sensor_event_state_sensor_state *)
100948761c62SAndrew Jeffery 			event_data->event_class;
101048761c62SAndrew Jeffery 
101148761c62SAndrew Jeffery 	state_data->sensor_offset = sensor_offset;
101248761c62SAndrew Jeffery 	state_data->event_state = event_state;
101348761c62SAndrew Jeffery 	state_data->previous_event_state = previous_event_state;
101448761c62SAndrew Jeffery 
101548761c62SAndrew Jeffery 	return PLDM_SUCCESS;
101648761c62SAndrew Jeffery }
101748761c62SAndrew Jeffery 
101848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
101948761c62SAndrew Jeffery int decode_platform_event_message_req(const struct pldm_msg *msg,
102048761c62SAndrew Jeffery 				      size_t payload_length,
102148761c62SAndrew Jeffery 				      uint8_t *format_version, uint8_t *tid,
102248761c62SAndrew Jeffery 				      uint8_t *event_class,
102348761c62SAndrew Jeffery 				      size_t *event_data_offset)
102448761c62SAndrew Jeffery {
102548761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
102648761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
102748761c62SAndrew Jeffery 	int rc;
102848761c62SAndrew Jeffery 
102948761c62SAndrew Jeffery 	if (msg == NULL || format_version == NULL || tid == NULL ||
103048761c62SAndrew Jeffery 	    event_class == NULL || event_data_offset == NULL) {
103148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
103248761c62SAndrew Jeffery 	}
103348761c62SAndrew Jeffery 
103448761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES,
103548761c62SAndrew Jeffery 				 msg->payload, payload_length);
103648761c62SAndrew Jeffery 	if (rc) {
103748761c62SAndrew Jeffery 		return rc;
103848761c62SAndrew Jeffery 	}
103948761c62SAndrew Jeffery 
104048761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, format_version);
104148761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, tid);
104248761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_class);
104348761c62SAndrew Jeffery 	*event_data_offset =
104448761c62SAndrew Jeffery 		sizeof(*format_version) + sizeof(*tid) + sizeof(*event_class);
104548761c62SAndrew Jeffery 
104648761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
104748761c62SAndrew Jeffery }
104848761c62SAndrew Jeffery 
1049*387b10f6SThu Nguyen static int pldm_platform_poll_for_platform_event_message_validate(
1050*387b10f6SThu Nguyen 	uint8_t transfer_operation_flag, uint16_t event_id_to_acknowledge)
1051*387b10f6SThu Nguyen {
1052*387b10f6SThu Nguyen 	if (((transfer_operation_flag == PLDM_GET_FIRSTPART) &&
1053*387b10f6SThu Nguyen 	     (event_id_to_acknowledge != PLDM_PLATFORM_EVENT_ID_NULL)) ||
1054*387b10f6SThu Nguyen 	    ((transfer_operation_flag == PLDM_GET_NEXTPART) &&
1055*387b10f6SThu Nguyen 	     (event_id_to_acknowledge != PLDM_PLATFORM_EVENT_ID_FRAGMENT)) ||
1056*387b10f6SThu Nguyen 	    ((transfer_operation_flag == PLDM_ACKNOWLEDGEMENT_ONLY) &&
1057*387b10f6SThu Nguyen 	     (event_id_to_acknowledge != PLDM_PLATFORM_EVENT_ID_FRAGMENT)) ||
1058*387b10f6SThu Nguyen 	    (transfer_operation_flag > PLDM_ACKNOWLEDGEMENT_ONLY)) {
1059*387b10f6SThu Nguyen 		return -EPROTO;
1060*387b10f6SThu Nguyen 	}
1061*387b10f6SThu Nguyen 
1062*387b10f6SThu Nguyen 	return 0;
1063*387b10f6SThu Nguyen }
1064*387b10f6SThu Nguyen 
106548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
106648761c62SAndrew Jeffery int decode_poll_for_platform_event_message_req(
106748761c62SAndrew Jeffery 	const struct pldm_msg *msg, size_t payload_length,
106848761c62SAndrew Jeffery 	uint8_t *format_version, uint8_t *transfer_operation_flag,
106948761c62SAndrew Jeffery 	uint32_t *data_transfer_handle, uint16_t *event_id_to_acknowledge)
107048761c62SAndrew Jeffery {
107148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
107248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
107348761c62SAndrew Jeffery 	int rc;
107448761c62SAndrew Jeffery 
107590bbe6c0SAndrew Jeffery 	if (msg == NULL || format_version == NULL ||
107690bbe6c0SAndrew Jeffery 	    transfer_operation_flag == NULL || data_transfer_handle == NULL ||
107790bbe6c0SAndrew Jeffery 	    event_id_to_acknowledge == NULL) {
107848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
107948761c62SAndrew Jeffery 	}
108048761c62SAndrew Jeffery 
108148761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf,
108248761c62SAndrew Jeffery 				 PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES,
108348761c62SAndrew Jeffery 				 msg->payload, payload_length);
108448761c62SAndrew Jeffery 	if (rc) {
108548761c62SAndrew Jeffery 		return rc;
108648761c62SAndrew Jeffery 	}
108748761c62SAndrew Jeffery 
108848761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, format_version);
108948761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, transfer_operation_flag);
109048761c62SAndrew Jeffery 	if (rc) {
109148761c62SAndrew Jeffery 		return rc;
109248761c62SAndrew Jeffery 	}
109348761c62SAndrew Jeffery 	if (*transfer_operation_flag > PLDM_ACKNOWLEDGEMENT_ONLY) {
109448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
109548761c62SAndrew Jeffery 	}
109648761c62SAndrew Jeffery 
109748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, data_transfer_handle);
109848761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, event_id_to_acknowledge);
109948761c62SAndrew Jeffery 	if (rc) {
110048761c62SAndrew Jeffery 		return rc;
110148761c62SAndrew Jeffery 	}
110248761c62SAndrew Jeffery 
1103*387b10f6SThu Nguyen 	rc = pldm_platform_poll_for_platform_event_message_validate(
1104*387b10f6SThu Nguyen 		*transfer_operation_flag, *event_id_to_acknowledge);
1105*387b10f6SThu Nguyen 	if (rc < 0) {
110648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
110748761c62SAndrew Jeffery 	}
110848761c62SAndrew Jeffery 
110948761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
111048761c62SAndrew Jeffery }
111148761c62SAndrew Jeffery 
111248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
111348761c62SAndrew Jeffery int encode_platform_event_message_resp(uint8_t instance_id,
111448761c62SAndrew Jeffery 				       uint8_t completion_code,
111548761c62SAndrew Jeffery 				       uint8_t platform_event_status,
111648761c62SAndrew Jeffery 				       struct pldm_msg *msg)
111748761c62SAndrew Jeffery {
111848761c62SAndrew Jeffery 	if (msg == NULL) {
111948761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
112048761c62SAndrew Jeffery 	}
112148761c62SAndrew Jeffery 
112248761c62SAndrew Jeffery 	if (platform_event_status > PLDM_EVENT_LOGGING_REJECTED) {
112348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
112448761c62SAndrew Jeffery 	}
112548761c62SAndrew Jeffery 
112648761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
112748761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
112848761c62SAndrew Jeffery 	header.instance = instance_id;
112948761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
113048761c62SAndrew Jeffery 	header.command = PLDM_PLATFORM_EVENT_MESSAGE;
113148761c62SAndrew Jeffery 
113248761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
113348761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
113448761c62SAndrew Jeffery 		return rc;
113548761c62SAndrew Jeffery 	}
113648761c62SAndrew Jeffery 
113748761c62SAndrew Jeffery 	struct pldm_platform_event_message_resp *response =
113848761c62SAndrew Jeffery 		(struct pldm_platform_event_message_resp *)msg->payload;
113948761c62SAndrew Jeffery 	response->completion_code = completion_code;
114048761c62SAndrew Jeffery 	response->platform_event_status = platform_event_status;
114148761c62SAndrew Jeffery 
114248761c62SAndrew Jeffery 	return PLDM_SUCCESS;
114348761c62SAndrew Jeffery }
114448761c62SAndrew Jeffery 
114548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
114648761c62SAndrew Jeffery int encode_poll_for_platform_event_message_resp(
114748761c62SAndrew Jeffery 	uint8_t instance_id, uint8_t completion_code, uint8_t tid,
114848761c62SAndrew Jeffery 	uint16_t event_id, uint32_t next_data_transfer_handle,
114948761c62SAndrew Jeffery 	uint8_t transfer_flag, uint8_t event_class, uint32_t event_data_size,
115048761c62SAndrew Jeffery 	uint8_t *event_data, uint32_t checksum, struct pldm_msg *msg,
115148761c62SAndrew Jeffery 	size_t payload_length)
115248761c62SAndrew Jeffery {
115348761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
115448761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
115548761c62SAndrew Jeffery 	int rc;
115648761c62SAndrew Jeffery 
115748761c62SAndrew Jeffery 	if (!msg) {
115848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
115948761c62SAndrew Jeffery 	}
116048761c62SAndrew Jeffery 
116148761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
116248761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
116348761c62SAndrew Jeffery 	header.instance = instance_id;
116448761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
116548761c62SAndrew Jeffery 	header.command = PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE;
116648761c62SAndrew Jeffery 
116748761c62SAndrew Jeffery 	rc = pack_pldm_header(&header, &(msg->hdr));
116848761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
116948761c62SAndrew Jeffery 		return rc;
117048761c62SAndrew Jeffery 	}
117148761c62SAndrew Jeffery 
117248761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(
117348761c62SAndrew Jeffery 		buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
117448761c62SAndrew Jeffery 		msg->payload, payload_length);
117548761c62SAndrew Jeffery 	if (rc) {
117648761c62SAndrew Jeffery 		return rc;
117748761c62SAndrew Jeffery 	}
117848761c62SAndrew Jeffery 
117948761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, completion_code);
118048761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, tid);
118148761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, event_id);
118248761c62SAndrew Jeffery 
118348761c62SAndrew Jeffery 	if (event_id == 0xffff || event_id == 0x0000) {
118448761c62SAndrew Jeffery 		if (PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES !=
118548761c62SAndrew Jeffery 		    payload_length) {
118648761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
118748761c62SAndrew Jeffery 		}
118848761c62SAndrew Jeffery 		return pldm_msgbuf_destroy(buf);
118948761c62SAndrew Jeffery 	}
119048761c62SAndrew Jeffery 
119148761c62SAndrew Jeffery 	if ((event_data == NULL) && (event_data_size > 0)) {
119248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
119348761c62SAndrew Jeffery 	}
119448761c62SAndrew Jeffery 
119548761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, next_data_transfer_handle);
119648761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, transfer_flag);
119748761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, event_class);
119848761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, event_data_size);
119948761c62SAndrew Jeffery 
120048761c62SAndrew Jeffery 	if ((event_data_size > 0) && event_data) {
12010a1be3cbSAndrew Jeffery 		rc = pldm_msgbuf_insert_array(buf, event_data_size, event_data,
12020a1be3cbSAndrew Jeffery 					      event_data_size);
12030a1be3cbSAndrew Jeffery 		if (rc) {
12040a1be3cbSAndrew Jeffery 			return rc;
12050a1be3cbSAndrew Jeffery 		}
120648761c62SAndrew Jeffery 	}
120748761c62SAndrew Jeffery 
120848761c62SAndrew Jeffery 	if (transfer_flag == PLDM_END || transfer_flag == PLDM_START_AND_END) {
120948761c62SAndrew Jeffery 		pldm_msgbuf_insert(buf, checksum);
121048761c62SAndrew Jeffery 	}
121148761c62SAndrew Jeffery 
121248761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
121348761c62SAndrew Jeffery }
121448761c62SAndrew Jeffery 
121548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
121648761c62SAndrew Jeffery int encode_platform_event_message_req(
121748761c62SAndrew Jeffery 	uint8_t instance_id, uint8_t format_version, uint8_t tid,
121848761c62SAndrew Jeffery 	uint8_t event_class, const uint8_t *event_data,
121948761c62SAndrew Jeffery 	size_t event_data_length, struct pldm_msg *msg, size_t payload_length)
122048761c62SAndrew Jeffery 
122148761c62SAndrew Jeffery {
122248761c62SAndrew Jeffery 	if (format_version != 1) {
122348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
122448761c62SAndrew Jeffery 	}
122548761c62SAndrew Jeffery 
122648761c62SAndrew Jeffery 	if (msg == NULL || event_data == NULL) {
122748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
122848761c62SAndrew Jeffery 	}
122948761c62SAndrew Jeffery 
123048761c62SAndrew Jeffery 	if (event_data_length == 0) {
123148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
123248761c62SAndrew Jeffery 	}
123348761c62SAndrew Jeffery 
123448761c62SAndrew Jeffery 	if (payload_length !=
123548761c62SAndrew Jeffery 	    PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES + event_data_length) {
123648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
123748761c62SAndrew Jeffery 	}
123848761c62SAndrew Jeffery 
123948761c62SAndrew Jeffery 	if (event_class > PLDM_HEARTBEAT_TIMER_ELAPSED_EVENT &&
124048761c62SAndrew Jeffery 	    !(event_class >= 0xf0 && event_class <= 0xfe)) {
124148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
124248761c62SAndrew Jeffery 	}
124348761c62SAndrew Jeffery 
124448761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
124548761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
124648761c62SAndrew Jeffery 	header.instance = instance_id;
124748761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
124848761c62SAndrew Jeffery 	header.command = PLDM_PLATFORM_EVENT_MESSAGE;
124948761c62SAndrew Jeffery 
125048761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
125148761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
125248761c62SAndrew Jeffery 		return rc;
125348761c62SAndrew Jeffery 	}
125448761c62SAndrew Jeffery 
125548761c62SAndrew Jeffery 	struct pldm_platform_event_message_req *request =
125648761c62SAndrew Jeffery 		(struct pldm_platform_event_message_req *)msg->payload;
125748761c62SAndrew Jeffery 	request->format_version = format_version;
125848761c62SAndrew Jeffery 	request->tid = tid;
125948761c62SAndrew Jeffery 	request->event_class = event_class;
126048761c62SAndrew Jeffery 	memcpy(request->event_data, event_data, event_data_length);
126148761c62SAndrew Jeffery 
126248761c62SAndrew Jeffery 	return PLDM_SUCCESS;
126348761c62SAndrew Jeffery }
126448761c62SAndrew Jeffery 
126548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
126648761c62SAndrew Jeffery int decode_platform_event_message_resp(const struct pldm_msg *msg,
126748761c62SAndrew Jeffery 				       size_t payload_length,
126848761c62SAndrew Jeffery 				       uint8_t *completion_code,
126948761c62SAndrew Jeffery 				       uint8_t *platform_event_status)
127048761c62SAndrew Jeffery {
127148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
127248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
127348761c62SAndrew Jeffery 	int rc;
127448761c62SAndrew Jeffery 
127548761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL ||
127648761c62SAndrew Jeffery 	    platform_event_status == NULL) {
127748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
127848761c62SAndrew Jeffery 	}
127948761c62SAndrew Jeffery 
128048761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES,
128148761c62SAndrew Jeffery 				 msg->payload, payload_length);
128248761c62SAndrew Jeffery 	if (rc) {
128348761c62SAndrew Jeffery 		return rc;
128448761c62SAndrew Jeffery 	}
128548761c62SAndrew Jeffery 
128648761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, completion_code);
128748761c62SAndrew Jeffery 	if (rc) {
128848761c62SAndrew Jeffery 		return rc;
128948761c62SAndrew Jeffery 	}
129048761c62SAndrew Jeffery 
129148761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
129248761c62SAndrew Jeffery 		return PLDM_SUCCESS;
129348761c62SAndrew Jeffery 	}
129448761c62SAndrew Jeffery 
129548761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, platform_event_status);
129648761c62SAndrew Jeffery 	if (rc) {
129748761c62SAndrew Jeffery 		return rc;
129848761c62SAndrew Jeffery 	}
129948761c62SAndrew Jeffery 
130048761c62SAndrew Jeffery 	if (*platform_event_status > PLDM_EVENT_LOGGING_REJECTED) {
130148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
130248761c62SAndrew Jeffery 	}
130348761c62SAndrew Jeffery 
130448761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
130548761c62SAndrew Jeffery }
130648761c62SAndrew Jeffery 
130748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
130848761c62SAndrew Jeffery int encode_event_message_buffer_size_req(uint8_t instance_id,
130948761c62SAndrew Jeffery 					 uint16_t event_receiver_max_buffer_size,
131048761c62SAndrew Jeffery 					 struct pldm_msg *msg)
131148761c62SAndrew Jeffery {
131248761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
131348761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
131448761c62SAndrew Jeffery 	header.instance = instance_id;
131548761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
131648761c62SAndrew Jeffery 	header.command = PLDM_EVENT_MESSAGE_BUFFER_SIZE;
131748761c62SAndrew Jeffery 
131848761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
131948761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
132048761c62SAndrew Jeffery 		return rc;
132148761c62SAndrew Jeffery 	}
132248761c62SAndrew Jeffery 
132348761c62SAndrew Jeffery 	struct pldm_event_message_buffer_size_req *request =
132448761c62SAndrew Jeffery 		(struct pldm_event_message_buffer_size_req *)msg->payload;
132548761c62SAndrew Jeffery 	request->event_receiver_max_buffer_size =
132648761c62SAndrew Jeffery 		event_receiver_max_buffer_size;
132748761c62SAndrew Jeffery 
132848761c62SAndrew Jeffery 	return PLDM_SUCCESS;
132948761c62SAndrew Jeffery }
133048761c62SAndrew Jeffery 
133148761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
133248761c62SAndrew Jeffery int decode_event_message_buffer_size_resp(const struct pldm_msg *msg,
133348761c62SAndrew Jeffery 					  size_t payload_length,
133448761c62SAndrew Jeffery 					  uint8_t *completion_code,
133548761c62SAndrew Jeffery 					  uint16_t *terminus_max_buffer_size)
133648761c62SAndrew Jeffery {
133748761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
133848761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
133948761c62SAndrew Jeffery 	int rc;
134048761c62SAndrew Jeffery 
134148761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL ||
134248761c62SAndrew Jeffery 	    terminus_max_buffer_size == NULL) {
134348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
134448761c62SAndrew Jeffery 	}
134548761c62SAndrew Jeffery 
134648761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_EVENT_MESSAGE_BUFFER_SIZE_RESP_BYTES,
134748761c62SAndrew Jeffery 				 msg->payload, payload_length);
134848761c62SAndrew Jeffery 	if (rc) {
134948761c62SAndrew Jeffery 		return rc;
135048761c62SAndrew Jeffery 	}
135148761c62SAndrew Jeffery 
135248761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, completion_code);
135348761c62SAndrew Jeffery 	if (rc) {
135448761c62SAndrew Jeffery 		return rc;
135548761c62SAndrew Jeffery 	}
135648761c62SAndrew Jeffery 
135748761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
135848761c62SAndrew Jeffery 		return PLDM_SUCCESS;
135948761c62SAndrew Jeffery 	}
136048761c62SAndrew Jeffery 
136148761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, terminus_max_buffer_size);
136248761c62SAndrew Jeffery 
136348761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
136448761c62SAndrew Jeffery }
136548761c62SAndrew Jeffery 
136648761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
136748761c62SAndrew Jeffery int encode_event_message_supported_req(uint8_t instance_id,
136848761c62SAndrew Jeffery 				       uint8_t format_version,
136948761c62SAndrew Jeffery 				       struct pldm_msg *msg)
137048761c62SAndrew Jeffery {
137148761c62SAndrew Jeffery 	if (format_version != 1) {
137248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
137348761c62SAndrew Jeffery 	}
137448761c62SAndrew Jeffery 
137548761c62SAndrew Jeffery 	if (msg == NULL) {
137648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
137748761c62SAndrew Jeffery 	}
137848761c62SAndrew Jeffery 
137948761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
138048761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
138148761c62SAndrew Jeffery 	header.instance = instance_id;
138248761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
138348761c62SAndrew Jeffery 	header.command = PLDM_EVENT_MESSAGE_SUPPORTED;
138448761c62SAndrew Jeffery 
138548761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
138648761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
138748761c62SAndrew Jeffery 		return rc;
138848761c62SAndrew Jeffery 	}
138948761c62SAndrew Jeffery 
139048761c62SAndrew Jeffery 	struct pldm_event_message_supported_req *request =
139148761c62SAndrew Jeffery 		(struct pldm_event_message_supported_req *)msg->payload;
139248761c62SAndrew Jeffery 	request->format_version = format_version;
139348761c62SAndrew Jeffery 
139448761c62SAndrew Jeffery 	return PLDM_SUCCESS;
139548761c62SAndrew Jeffery }
139648761c62SAndrew Jeffery 
139748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
139848761c62SAndrew Jeffery int decode_event_message_supported_resp(const struct pldm_msg *msg,
139948761c62SAndrew Jeffery 					size_t payload_length,
140048761c62SAndrew Jeffery 					uint8_t *completion_code,
140148761c62SAndrew Jeffery 					uint8_t *synchrony_config,
140248761c62SAndrew Jeffery 					bitfield8_t *synchrony_config_support,
140348761c62SAndrew Jeffery 					uint8_t *number_event_class_returned,
140448761c62SAndrew Jeffery 					uint8_t *event_class,
140548761c62SAndrew Jeffery 					uint8_t event_class_count)
140648761c62SAndrew Jeffery {
140748761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
140848761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
140948761c62SAndrew Jeffery 	int i;
141048761c62SAndrew Jeffery 	int rc;
141148761c62SAndrew Jeffery 
141248761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL ||
141348761c62SAndrew Jeffery 	    synchrony_config == NULL || synchrony_config_support == NULL ||
141448761c62SAndrew Jeffery 	    number_event_class_returned == NULL || event_class == NULL) {
141548761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
141648761c62SAndrew Jeffery 	}
141748761c62SAndrew Jeffery 
141848761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf,
141948761c62SAndrew Jeffery 				 PLDM_EVENT_MESSAGE_SUPPORTED_MIN_RESP_BYTES,
142048761c62SAndrew Jeffery 				 msg->payload, payload_length);
142148761c62SAndrew Jeffery 	if (rc) {
142248761c62SAndrew Jeffery 		return rc;
142348761c62SAndrew Jeffery 	}
142448761c62SAndrew Jeffery 
142548761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, completion_code);
142648761c62SAndrew Jeffery 	if (rc) {
142748761c62SAndrew Jeffery 		return rc;
142848761c62SAndrew Jeffery 	}
142948761c62SAndrew Jeffery 
143048761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
143148761c62SAndrew Jeffery 		return PLDM_SUCCESS;
143248761c62SAndrew Jeffery 	}
143348761c62SAndrew Jeffery 
143448761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, synchrony_config);
143548761c62SAndrew Jeffery 	if (rc) {
143648761c62SAndrew Jeffery 		return rc;
143748761c62SAndrew Jeffery 	}
143848761c62SAndrew Jeffery 
143948761c62SAndrew Jeffery 	if (*synchrony_config > PLDM_MESSAGE_TYPE_ASYNCHRONOUS_WITH_HEARTBEAT) {
144048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
144148761c62SAndrew Jeffery 	}
144248761c62SAndrew Jeffery 
144348761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, &synchrony_config_support->byte);
144448761c62SAndrew Jeffery 
144548761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, number_event_class_returned);
144648761c62SAndrew Jeffery 	if (rc) {
144748761c62SAndrew Jeffery 		return rc;
144848761c62SAndrew Jeffery 	}
144948761c62SAndrew Jeffery 
145048761c62SAndrew Jeffery 	if (*number_event_class_returned == 0) {
145148761c62SAndrew Jeffery 		return pldm_msgbuf_destroy(buf);
145248761c62SAndrew Jeffery 	}
145348761c62SAndrew Jeffery 
145448761c62SAndrew Jeffery 	if (event_class_count < *number_event_class_returned) {
145548761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
145648761c62SAndrew Jeffery 	}
145748761c62SAndrew Jeffery 
145848761c62SAndrew Jeffery 	for (i = 0; i < *number_event_class_returned; i++) {
145948761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, event_class[i]);
146048761c62SAndrew Jeffery 	}
146148761c62SAndrew Jeffery 
146248761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
146348761c62SAndrew Jeffery }
146448761c62SAndrew Jeffery 
146548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
146648761c62SAndrew Jeffery int decode_sensor_event_data(const uint8_t *event_data,
146748761c62SAndrew Jeffery 			     size_t event_data_length, uint16_t *sensor_id,
146848761c62SAndrew Jeffery 			     uint8_t *sensor_event_class_type,
146948761c62SAndrew Jeffery 			     size_t *event_class_data_offset)
147048761c62SAndrew Jeffery {
147148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
147248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
147348761c62SAndrew Jeffery 	int rc;
147448761c62SAndrew Jeffery 
147590bbe6c0SAndrew Jeffery 	if (event_data == NULL || sensor_id == NULL ||
147690bbe6c0SAndrew Jeffery 	    sensor_event_class_type == NULL ||
147790bbe6c0SAndrew Jeffery 	    event_class_data_offset == NULL) {
147890bbe6c0SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
147990bbe6c0SAndrew Jeffery 	}
148090bbe6c0SAndrew Jeffery 
148148761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_SENSOR_EVENT_DATA_MIN_LENGTH,
148248761c62SAndrew Jeffery 				 event_data, event_data_length);
148348761c62SAndrew Jeffery 	if (rc) {
148448761c62SAndrew Jeffery 		return rc;
148548761c62SAndrew Jeffery 	}
148648761c62SAndrew Jeffery 
148748761c62SAndrew Jeffery 	size_t event_class_data_length =
148848761c62SAndrew Jeffery 		event_data_length - PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES;
148948761c62SAndrew Jeffery 
149048761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, sensor_id);
149148761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, sensor_event_class_type);
149248761c62SAndrew Jeffery 	if (rc) {
149348761c62SAndrew Jeffery 		return rc;
149448761c62SAndrew Jeffery 	}
149548761c62SAndrew Jeffery 
149648761c62SAndrew Jeffery 	if (*sensor_event_class_type == PLDM_SENSOR_OP_STATE) {
149748761c62SAndrew Jeffery 		if (event_class_data_length !=
149848761c62SAndrew Jeffery 		    PLDM_SENSOR_EVENT_SENSOR_OP_STATE_DATA_LENGTH) {
149948761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
150048761c62SAndrew Jeffery 		}
150148761c62SAndrew Jeffery 	} else if (*sensor_event_class_type == PLDM_STATE_SENSOR_STATE) {
150248761c62SAndrew Jeffery 		if (event_class_data_length !=
150348761c62SAndrew Jeffery 		    PLDM_SENSOR_EVENT_STATE_SENSOR_STATE_DATA_LENGTH) {
150448761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
150548761c62SAndrew Jeffery 		}
150648761c62SAndrew Jeffery 	} else if (*sensor_event_class_type == PLDM_NUMERIC_SENSOR_STATE) {
150748761c62SAndrew Jeffery 		if (event_class_data_length <
150848761c62SAndrew Jeffery 			    PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MIN_DATA_LENGTH ||
150948761c62SAndrew Jeffery 		    event_class_data_length >
151048761c62SAndrew Jeffery 			    PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MAX_DATA_LENGTH) {
151148761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
151248761c62SAndrew Jeffery 		}
151348761c62SAndrew Jeffery 	} else {
151448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
151548761c62SAndrew Jeffery 	}
151648761c62SAndrew Jeffery 
151748761c62SAndrew Jeffery 	*event_class_data_offset =
151848761c62SAndrew Jeffery 		sizeof(*sensor_id) + sizeof(*sensor_event_class_type);
151948761c62SAndrew Jeffery 
152048761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
152148761c62SAndrew Jeffery }
152248761c62SAndrew Jeffery 
152348761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
152448761c62SAndrew Jeffery int decode_sensor_op_data(const uint8_t *sensor_data, size_t sensor_data_length,
152548761c62SAndrew Jeffery 			  uint8_t *present_op_state, uint8_t *previous_op_state)
152648761c62SAndrew Jeffery {
152748761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
152848761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
152948761c62SAndrew Jeffery 	int rc;
153048761c62SAndrew Jeffery 
153190bbe6c0SAndrew Jeffery 	if (sensor_data == NULL || present_op_state == NULL ||
153290bbe6c0SAndrew Jeffery 	    previous_op_state == NULL) {
153348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
153448761c62SAndrew Jeffery 	}
153548761c62SAndrew Jeffery 
153648761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf,
153748761c62SAndrew Jeffery 				 PLDM_SENSOR_EVENT_SENSOR_OP_STATE_DATA_LENGTH,
153848761c62SAndrew Jeffery 				 sensor_data, sensor_data_length);
153948761c62SAndrew Jeffery 	if (rc) {
154048761c62SAndrew Jeffery 		return rc;
154148761c62SAndrew Jeffery 	}
154248761c62SAndrew Jeffery 
154348761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, present_op_state);
154448761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, previous_op_state);
154548761c62SAndrew Jeffery 
154648761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
154748761c62SAndrew Jeffery }
154848761c62SAndrew Jeffery 
154948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
155048761c62SAndrew Jeffery int decode_state_sensor_data(const uint8_t *sensor_data,
155148761c62SAndrew Jeffery 			     size_t sensor_data_length, uint8_t *sensor_offset,
155248761c62SAndrew Jeffery 			     uint8_t *event_state,
155348761c62SAndrew Jeffery 			     uint8_t *previous_event_state)
155448761c62SAndrew Jeffery {
155548761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
155648761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
155748761c62SAndrew Jeffery 	int rc;
155848761c62SAndrew Jeffery 
155990bbe6c0SAndrew Jeffery 	if (sensor_data == NULL || sensor_offset == NULL ||
156090bbe6c0SAndrew Jeffery 	    event_state == NULL || previous_event_state == NULL) {
156148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
156248761c62SAndrew Jeffery 	}
156348761c62SAndrew Jeffery 
156448761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(
156548761c62SAndrew Jeffery 		buf, PLDM_SENSOR_EVENT_STATE_SENSOR_STATE_DATA_LENGTH,
156648761c62SAndrew Jeffery 		sensor_data, sensor_data_length);
156748761c62SAndrew Jeffery 	if (rc) {
156848761c62SAndrew Jeffery 		return rc;
156948761c62SAndrew Jeffery 	}
157048761c62SAndrew Jeffery 
157148761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, sensor_offset);
157248761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_state);
157348761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, previous_event_state);
157448761c62SAndrew Jeffery 
157548761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
157648761c62SAndrew Jeffery }
157748761c62SAndrew Jeffery 
157848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
157948761c62SAndrew Jeffery int decode_numeric_sensor_data(const uint8_t *sensor_data,
158048761c62SAndrew Jeffery 			       size_t sensor_data_length, uint8_t *event_state,
158148761c62SAndrew Jeffery 			       uint8_t *previous_event_state,
158248761c62SAndrew Jeffery 			       uint8_t *sensor_data_size,
158348761c62SAndrew Jeffery 			       uint32_t *present_reading)
158448761c62SAndrew Jeffery {
158548761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
158648761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
158748761c62SAndrew Jeffery 	int rc;
158848761c62SAndrew Jeffery 
158990bbe6c0SAndrew Jeffery 	if (sensor_data == NULL || sensor_data_size == NULL ||
159090bbe6c0SAndrew Jeffery 	    event_state == NULL || previous_event_state == NULL ||
159190bbe6c0SAndrew Jeffery 	    present_reading == NULL) {
159248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
159348761c62SAndrew Jeffery 	}
159448761c62SAndrew Jeffery 
159548761c62SAndrew Jeffery 	if (sensor_data_length >
159648761c62SAndrew Jeffery 	    PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MAX_DATA_LENGTH) {
159748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
159848761c62SAndrew Jeffery 	}
159948761c62SAndrew Jeffery 
160048761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(
160148761c62SAndrew Jeffery 		buf, PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MIN_DATA_LENGTH,
160248761c62SAndrew Jeffery 		sensor_data, sensor_data_length);
160348761c62SAndrew Jeffery 	if (rc) {
160448761c62SAndrew Jeffery 		return rc;
160548761c62SAndrew Jeffery 	}
160648761c62SAndrew Jeffery 
160748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_state);
160848761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, previous_event_state);
160948761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, sensor_data_size);
161048761c62SAndrew Jeffery 	if (rc) {
161148761c62SAndrew Jeffery 		return rc;
161248761c62SAndrew Jeffery 	}
161348761c62SAndrew Jeffery 
161448761c62SAndrew Jeffery 	/*
161548761c62SAndrew Jeffery 	 * The implementation below is bonkers, but it's because the function
161648761c62SAndrew Jeffery 	 * prototype is bonkers. The `present_reading` argument should have been
161748761c62SAndrew Jeffery 	 * a tagged union.
161848761c62SAndrew Jeffery 	 */
161948761c62SAndrew Jeffery 	switch (*sensor_data_size) {
162048761c62SAndrew Jeffery 	case PLDM_SENSOR_DATA_SIZE_UINT8: {
162148761c62SAndrew Jeffery 		uint8_t val;
162248761c62SAndrew Jeffery 		if (!pldm_msgbuf_extract(buf, val)) {
162348761c62SAndrew Jeffery 			*present_reading = (uint32_t)val;
162448761c62SAndrew Jeffery 		}
162548761c62SAndrew Jeffery 		break;
162648761c62SAndrew Jeffery 	}
162748761c62SAndrew Jeffery 	case PLDM_SENSOR_DATA_SIZE_SINT8: {
162848761c62SAndrew Jeffery 		int8_t val;
162948761c62SAndrew Jeffery 		if (!pldm_msgbuf_extract(buf, val)) {
163048761c62SAndrew Jeffery 			*present_reading = (uint32_t)(int32_t)val;
163148761c62SAndrew Jeffery 		}
163248761c62SAndrew Jeffery 		break;
163348761c62SAndrew Jeffery 	}
163448761c62SAndrew Jeffery 	case PLDM_SENSOR_DATA_SIZE_UINT16: {
163548761c62SAndrew Jeffery 		uint16_t val;
163648761c62SAndrew Jeffery 		if (!pldm_msgbuf_extract(buf, val)) {
163748761c62SAndrew Jeffery 			*present_reading = (uint32_t)val;
163848761c62SAndrew Jeffery 		}
163948761c62SAndrew Jeffery 		break;
164048761c62SAndrew Jeffery 	}
164148761c62SAndrew Jeffery 	case PLDM_SENSOR_DATA_SIZE_SINT16: {
164248761c62SAndrew Jeffery 		int16_t val;
164348761c62SAndrew Jeffery 		if (!pldm_msgbuf_extract(buf, val)) {
164448761c62SAndrew Jeffery 			*present_reading = (uint32_t)(int32_t)val;
164548761c62SAndrew Jeffery 		}
164648761c62SAndrew Jeffery 		break;
164748761c62SAndrew Jeffery 	}
164848761c62SAndrew Jeffery 	case PLDM_SENSOR_DATA_SIZE_UINT32: {
164948761c62SAndrew Jeffery 		uint32_t val;
165048761c62SAndrew Jeffery 		if (!pldm_msgbuf_extract(buf, val)) {
165148761c62SAndrew Jeffery 			*present_reading = (uint32_t)val;
165248761c62SAndrew Jeffery 		}
165348761c62SAndrew Jeffery 		break;
165448761c62SAndrew Jeffery 	}
165548761c62SAndrew Jeffery 	case PLDM_SENSOR_DATA_SIZE_SINT32: {
165648761c62SAndrew Jeffery 		int32_t val;
165748761c62SAndrew Jeffery 		if (!pldm_msgbuf_extract(buf, val)) {
165848761c62SAndrew Jeffery 			*present_reading = (uint32_t)val;
165948761c62SAndrew Jeffery 		}
166048761c62SAndrew Jeffery 		break;
166148761c62SAndrew Jeffery 	}
166248761c62SAndrew Jeffery 	default:
166348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
166448761c62SAndrew Jeffery 	}
166548761c62SAndrew Jeffery 
166648761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
166748761c62SAndrew Jeffery }
166848761c62SAndrew Jeffery 
166948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
167048761c62SAndrew Jeffery int decode_numeric_sensor_pdr_data(
167148761c62SAndrew Jeffery 	const void *pdr_data, size_t pdr_data_length,
167248761c62SAndrew Jeffery 	struct pldm_numeric_sensor_value_pdr *pdr_value)
167348761c62SAndrew Jeffery {
167448761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
167548761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
167648761c62SAndrew Jeffery 	int rc;
167748761c62SAndrew Jeffery 
167848761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
167948761c62SAndrew Jeffery 				 pdr_data, pdr_data_length);
168048761c62SAndrew Jeffery 	if (rc) {
168148761c62SAndrew Jeffery 		return rc;
168248761c62SAndrew Jeffery 	}
168348761c62SAndrew Jeffery 
168448761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_value_pdr_hdr(buf, &pdr_value->hdr);
168548761c62SAndrew Jeffery 	if (rc) {
168648761c62SAndrew Jeffery 		return rc;
168748761c62SAndrew Jeffery 	}
168848761c62SAndrew Jeffery 
168948761c62SAndrew Jeffery 	rc = pldm_platform_pdr_hdr_validate(
169048761c62SAndrew Jeffery 		&pdr_value->hdr, PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
169148761c62SAndrew Jeffery 		pdr_data_length);
169248761c62SAndrew Jeffery 	if (rc) {
169348761c62SAndrew Jeffery 		return rc;
169448761c62SAndrew Jeffery 	}
169548761c62SAndrew Jeffery 
169648761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->terminus_handle);
169748761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->sensor_id);
169848761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->entity_type);
169948761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->entity_instance_num);
170048761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->container_id);
170148761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->sensor_init);
170248761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->sensor_auxiliary_names_pdr);
170348761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->base_unit);
170448761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->unit_modifier);
170548761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->rate_unit);
170648761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->base_oem_unit_handle);
170748761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_unit);
170848761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_unit_modifier);
170948761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_rate_unit);
171048761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->rel);
171148761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_oem_unit_handle);
171248761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->is_linear);
171348761c62SAndrew Jeffery 
171448761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, pdr_value->sensor_data_size);
171548761c62SAndrew Jeffery 	if (rc) {
171648761c62SAndrew Jeffery 		return rc;
171748761c62SAndrew Jeffery 	}
171848761c62SAndrew Jeffery 	if (pdr_value->sensor_data_size > PLDM_SENSOR_DATA_SIZE_MAX) {
171948761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
172048761c62SAndrew Jeffery 	}
172148761c62SAndrew Jeffery 
172248761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->resolution);
172348761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->offset);
172448761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->accuracy);
172548761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->plus_tolerance);
172648761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->minus_tolerance);
172748761c62SAndrew Jeffery 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
172848761c62SAndrew Jeffery 					&pdr_value->hysteresis);
172948761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->supported_thresholds.byte);
173048761c62SAndrew Jeffery 	pldm_msgbuf_extract(
173148761c62SAndrew Jeffery 		buf, pdr_value->threshold_and_hysteresis_volatility.byte);
173248761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->state_transition_interval);
173348761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->update_interval);
173448761c62SAndrew Jeffery 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
173548761c62SAndrew Jeffery 					&pdr_value->max_readable);
173648761c62SAndrew Jeffery 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
173748761c62SAndrew Jeffery 					&pdr_value->min_readable);
173848761c62SAndrew Jeffery 
173948761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, pdr_value->range_field_format);
174048761c62SAndrew Jeffery 	if (rc) {
174148761c62SAndrew Jeffery 		return rc;
174248761c62SAndrew Jeffery 	}
174348761c62SAndrew Jeffery 	if (pdr_value->range_field_format > PLDM_RANGE_FIELD_FORMAT_MAX) {
174448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
174548761c62SAndrew Jeffery 	}
174648761c62SAndrew Jeffery 
174748761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->range_field_support.byte);
174848761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
174948761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->nominal_value);
175048761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
175148761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->normal_max);
175248761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
175348761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->normal_min);
175448761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
175548761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->warning_high);
175648761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
175748761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->warning_low);
175848761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
175948761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->critical_high);
176048761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
176148761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->critical_low);
176248761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
176348761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->fatal_high);
176448761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
176548761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->fatal_low);
176648761c62SAndrew Jeffery 
176748761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
176848761c62SAndrew Jeffery }
176948761c62SAndrew Jeffery 
177048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
177148761c62SAndrew Jeffery int encode_get_numeric_effecter_value_req(uint8_t instance_id,
177248761c62SAndrew Jeffery 					  uint16_t effecter_id,
177348761c62SAndrew Jeffery 					  struct pldm_msg *msg)
177448761c62SAndrew Jeffery {
177548761c62SAndrew Jeffery 	if (msg == NULL) {
177648761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
177748761c62SAndrew Jeffery 	}
177848761c62SAndrew Jeffery 
177948761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
178048761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
178148761c62SAndrew Jeffery 	header.instance = instance_id;
178248761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
178348761c62SAndrew Jeffery 	header.command = PLDM_GET_NUMERIC_EFFECTER_VALUE;
178448761c62SAndrew Jeffery 
178548761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
178648761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
178748761c62SAndrew Jeffery 		return rc;
178848761c62SAndrew Jeffery 	}
178948761c62SAndrew Jeffery 
179048761c62SAndrew Jeffery 	struct pldm_get_numeric_effecter_value_req *request =
179148761c62SAndrew Jeffery 		(struct pldm_get_numeric_effecter_value_req *)msg->payload;
179248761c62SAndrew Jeffery 	request->effecter_id = htole16(effecter_id);
179348761c62SAndrew Jeffery 
179448761c62SAndrew Jeffery 	return PLDM_SUCCESS;
179548761c62SAndrew Jeffery }
179648761c62SAndrew Jeffery 
179748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
179848761c62SAndrew Jeffery int encode_get_numeric_effecter_value_resp(
179948761c62SAndrew Jeffery 	uint8_t instance_id, uint8_t completion_code,
180048761c62SAndrew Jeffery 	uint8_t effecter_data_size, uint8_t effecter_oper_state,
180148761c62SAndrew Jeffery 	const uint8_t *pending_value, const uint8_t *present_value,
180248761c62SAndrew Jeffery 	struct pldm_msg *msg, size_t payload_length)
180348761c62SAndrew Jeffery {
180448761c62SAndrew Jeffery 	if (msg == NULL || pending_value == NULL || present_value == NULL) {
180548761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
180648761c62SAndrew Jeffery 	}
180748761c62SAndrew Jeffery 
180848761c62SAndrew Jeffery 	if (effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
180948761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
181048761c62SAndrew Jeffery 	}
181148761c62SAndrew Jeffery 
181248761c62SAndrew Jeffery 	if (effecter_oper_state > EFFECTER_OPER_STATE_INTEST) {
181348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
181448761c62SAndrew Jeffery 	}
181548761c62SAndrew Jeffery 
181648761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
181748761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
181848761c62SAndrew Jeffery 	header.instance = instance_id;
181948761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
182048761c62SAndrew Jeffery 	header.command = PLDM_GET_NUMERIC_EFFECTER_VALUE;
182148761c62SAndrew Jeffery 
182248761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
182348761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
182448761c62SAndrew Jeffery 		return rc;
182548761c62SAndrew Jeffery 	}
182648761c62SAndrew Jeffery 
182748761c62SAndrew Jeffery 	struct pldm_get_numeric_effecter_value_resp *response =
182848761c62SAndrew Jeffery 		(struct pldm_get_numeric_effecter_value_resp *)msg->payload;
182948761c62SAndrew Jeffery 
183048761c62SAndrew Jeffery 	response->completion_code = completion_code;
183148761c62SAndrew Jeffery 	response->effecter_data_size = effecter_data_size;
183248761c62SAndrew Jeffery 	response->effecter_oper_state = effecter_oper_state;
183348761c62SAndrew Jeffery 
183448761c62SAndrew Jeffery 	if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
183548761c62SAndrew Jeffery 	    effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
183648761c62SAndrew Jeffery 		if (payload_length !=
183748761c62SAndrew Jeffery 		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES) {
183848761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
183948761c62SAndrew Jeffery 		}
184048761c62SAndrew Jeffery 		response->pending_and_present_values[0] = *pending_value;
184148761c62SAndrew Jeffery 		response->pending_and_present_values[1] = *present_value;
184248761c62SAndrew Jeffery 
184348761c62SAndrew Jeffery 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
184448761c62SAndrew Jeffery 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
184548761c62SAndrew Jeffery 		if (payload_length !=
184648761c62SAndrew Jeffery 		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 2) {
184748761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
184848761c62SAndrew Jeffery 		}
184948761c62SAndrew Jeffery 		uint16_t val_pending = *(uint16_t *)pending_value;
185048761c62SAndrew Jeffery 		val_pending = htole16(val_pending);
185148761c62SAndrew Jeffery 		memcpy(response->pending_and_present_values, &val_pending,
185248761c62SAndrew Jeffery 		       sizeof(uint16_t));
185348761c62SAndrew Jeffery 		uint16_t val_present = *(uint16_t *)present_value;
185448761c62SAndrew Jeffery 		val_present = htole16(val_present);
185548761c62SAndrew Jeffery 		memcpy((response->pending_and_present_values +
185648761c62SAndrew Jeffery 			sizeof(uint16_t)),
185748761c62SAndrew Jeffery 		       &val_present, sizeof(uint16_t));
185848761c62SAndrew Jeffery 
185948761c62SAndrew Jeffery 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
186048761c62SAndrew Jeffery 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
186148761c62SAndrew Jeffery 		if (payload_length !=
186248761c62SAndrew Jeffery 		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 6) {
186348761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
186448761c62SAndrew Jeffery 		}
186548761c62SAndrew Jeffery 		uint32_t val_pending = *(uint32_t *)pending_value;
186648761c62SAndrew Jeffery 		val_pending = htole32(val_pending);
186748761c62SAndrew Jeffery 		memcpy(response->pending_and_present_values, &val_pending,
186848761c62SAndrew Jeffery 		       sizeof(uint32_t));
186948761c62SAndrew Jeffery 		uint32_t val_present = *(uint32_t *)present_value;
187048761c62SAndrew Jeffery 		val_present = htole32(val_present);
187148761c62SAndrew Jeffery 		memcpy((response->pending_and_present_values +
187248761c62SAndrew Jeffery 			sizeof(uint32_t)),
187348761c62SAndrew Jeffery 		       &val_present, sizeof(uint32_t));
187448761c62SAndrew Jeffery 	}
187548761c62SAndrew Jeffery 	return PLDM_SUCCESS;
187648761c62SAndrew Jeffery }
187748761c62SAndrew Jeffery 
187848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
187948761c62SAndrew Jeffery int decode_get_numeric_effecter_value_req(const struct pldm_msg *msg,
188048761c62SAndrew Jeffery 					  size_t payload_length,
188148761c62SAndrew Jeffery 					  uint16_t *effecter_id)
188248761c62SAndrew Jeffery {
188348761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
188448761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
188548761c62SAndrew Jeffery 	int rc;
188648761c62SAndrew Jeffery 
188748761c62SAndrew Jeffery 	if (msg == NULL || effecter_id == NULL) {
188848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
188948761c62SAndrew Jeffery 	}
189048761c62SAndrew Jeffery 
189148761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES,
189248761c62SAndrew Jeffery 				 msg->payload, payload_length);
189348761c62SAndrew Jeffery 	if (rc) {
189448761c62SAndrew Jeffery 		return rc;
189548761c62SAndrew Jeffery 	}
189648761c62SAndrew Jeffery 
189748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, effecter_id);
189848761c62SAndrew Jeffery 
189948761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
190048761c62SAndrew Jeffery }
190148761c62SAndrew Jeffery 
190248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
190348761c62SAndrew Jeffery int decode_get_numeric_effecter_value_resp(const struct pldm_msg *msg,
190448761c62SAndrew Jeffery 					   size_t payload_length,
190548761c62SAndrew Jeffery 					   uint8_t *completion_code,
190648761c62SAndrew Jeffery 					   uint8_t *effecter_data_size,
190748761c62SAndrew Jeffery 					   uint8_t *effecter_oper_state,
190848761c62SAndrew Jeffery 					   uint8_t *pending_value,
190948761c62SAndrew Jeffery 					   uint8_t *present_value)
191048761c62SAndrew Jeffery {
191148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
191248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
191348761c62SAndrew Jeffery 	int rc;
191448761c62SAndrew Jeffery 
191548761c62SAndrew Jeffery 	if (msg == NULL || effecter_data_size == NULL ||
191648761c62SAndrew Jeffery 	    effecter_oper_state == NULL || pending_value == NULL ||
191748761c62SAndrew Jeffery 	    present_value == NULL) {
191848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
191948761c62SAndrew Jeffery 	}
192048761c62SAndrew Jeffery 
192148761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf,
192248761c62SAndrew Jeffery 				 PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES,
192348761c62SAndrew Jeffery 				 msg->payload, payload_length);
192448761c62SAndrew Jeffery 	if (rc) {
192548761c62SAndrew Jeffery 		return rc;
192648761c62SAndrew Jeffery 	}
192748761c62SAndrew Jeffery 
192848761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, completion_code);
192948761c62SAndrew Jeffery 	if (rc) {
193048761c62SAndrew Jeffery 		return rc;
193148761c62SAndrew Jeffery 	}
193248761c62SAndrew Jeffery 
193348761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
193448761c62SAndrew Jeffery 		return PLDM_SUCCESS;
193548761c62SAndrew Jeffery 	}
193648761c62SAndrew Jeffery 
193748761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, effecter_data_size);
193848761c62SAndrew Jeffery 	if (rc) {
193948761c62SAndrew Jeffery 		return rc;
194048761c62SAndrew Jeffery 	}
194148761c62SAndrew Jeffery 
194248761c62SAndrew Jeffery 	if (*effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
194348761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
194448761c62SAndrew Jeffery 	}
194548761c62SAndrew Jeffery 
194648761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, effecter_oper_state);
194748761c62SAndrew Jeffery 	if (rc) {
194848761c62SAndrew Jeffery 		return rc;
194948761c62SAndrew Jeffery 	}
195048761c62SAndrew Jeffery 
195148761c62SAndrew Jeffery 	if (*effecter_oper_state > EFFECTER_OPER_STATE_INTEST) {
195248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
195348761c62SAndrew Jeffery 	}
195448761c62SAndrew Jeffery 
195548761c62SAndrew Jeffery 	pldm_msgbuf_extract_effecter_value(buf, *effecter_data_size,
195648761c62SAndrew Jeffery 					   pending_value);
195748761c62SAndrew Jeffery 	pldm_msgbuf_extract_effecter_value(buf, *effecter_data_size,
195848761c62SAndrew Jeffery 					   present_value);
195948761c62SAndrew Jeffery 
196048761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
196148761c62SAndrew Jeffery }
196248761c62SAndrew Jeffery 
196348761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
196448761c62SAndrew Jeffery int encode_pldm_pdr_repository_chg_event_data(
196548761c62SAndrew Jeffery 	uint8_t event_data_format, uint8_t number_of_change_records,
196648761c62SAndrew Jeffery 	const uint8_t *event_data_operations,
196748761c62SAndrew Jeffery 	const uint8_t *numbers_of_change_entries,
196848761c62SAndrew Jeffery 	const uint32_t *const *change_entries,
196948761c62SAndrew Jeffery 	struct pldm_pdr_repository_chg_event_data *event_data,
197048761c62SAndrew Jeffery 	size_t *actual_change_records_size, size_t max_change_records_size)
197148761c62SAndrew Jeffery {
197248761c62SAndrew Jeffery 	if (event_data_operations == NULL ||
197348761c62SAndrew Jeffery 	    numbers_of_change_entries == NULL || change_entries == NULL) {
197448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
197548761c62SAndrew Jeffery 	}
197648761c62SAndrew Jeffery 
197748761c62SAndrew Jeffery 	size_t expected_size =
197848761c62SAndrew Jeffery 		sizeof(event_data_format) + sizeof(number_of_change_records);
197948761c62SAndrew Jeffery 
198048761c62SAndrew Jeffery 	expected_size +=
198148761c62SAndrew Jeffery 		sizeof(*event_data_operations) * number_of_change_records;
198248761c62SAndrew Jeffery 	expected_size +=
198348761c62SAndrew Jeffery 		sizeof(*numbers_of_change_entries) * number_of_change_records;
198448761c62SAndrew Jeffery 
198548761c62SAndrew Jeffery 	for (uint8_t i = 0; i < number_of_change_records; ++i) {
198648761c62SAndrew Jeffery 		expected_size += sizeof(*change_entries[0]) *
198748761c62SAndrew Jeffery 				 numbers_of_change_entries[i];
198848761c62SAndrew Jeffery 	}
198948761c62SAndrew Jeffery 
199048761c62SAndrew Jeffery 	*actual_change_records_size = expected_size;
199148761c62SAndrew Jeffery 
199248761c62SAndrew Jeffery 	if (event_data == NULL) {
199348761c62SAndrew Jeffery 		return PLDM_SUCCESS;
199448761c62SAndrew Jeffery 	}
199548761c62SAndrew Jeffery 
199648761c62SAndrew Jeffery 	if (max_change_records_size < expected_size) {
199748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_LENGTH;
199848761c62SAndrew Jeffery 	}
199948761c62SAndrew Jeffery 
200048761c62SAndrew Jeffery 	event_data->event_data_format = event_data_format;
200148761c62SAndrew Jeffery 	event_data->number_of_change_records = number_of_change_records;
200248761c62SAndrew Jeffery 
200348761c62SAndrew Jeffery 	struct pldm_pdr_repository_change_record_data *record_data =
200448761c62SAndrew Jeffery 		(struct pldm_pdr_repository_change_record_data *)
200548761c62SAndrew Jeffery 			event_data->change_records;
200648761c62SAndrew Jeffery 
200748761c62SAndrew Jeffery 	for (uint8_t i = 0; i < number_of_change_records; ++i) {
200848761c62SAndrew Jeffery 		record_data->event_data_operation = event_data_operations[i];
200948761c62SAndrew Jeffery 		record_data->number_of_change_entries =
201048761c62SAndrew Jeffery 			numbers_of_change_entries[i];
201148761c62SAndrew Jeffery 
201248761c62SAndrew Jeffery 		for (uint8_t j = 0; j < record_data->number_of_change_entries;
201348761c62SAndrew Jeffery 		     ++j) {
201448761c62SAndrew Jeffery 			record_data->change_entry[j] =
201548761c62SAndrew Jeffery 				htole32(change_entries[i][j]);
201648761c62SAndrew Jeffery 		}
201748761c62SAndrew Jeffery 
201848761c62SAndrew Jeffery 		record_data =
201948761c62SAndrew Jeffery 			(struct pldm_pdr_repository_change_record_data
202048761c62SAndrew Jeffery 				 *)(record_data->change_entry +
202148761c62SAndrew Jeffery 				    record_data->number_of_change_entries);
202248761c62SAndrew Jeffery 	}
202348761c62SAndrew Jeffery 
202448761c62SAndrew Jeffery 	return PLDM_SUCCESS;
202548761c62SAndrew Jeffery }
202648761c62SAndrew Jeffery 
202748761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
202848761c62SAndrew Jeffery int decode_pldm_pdr_repository_chg_event_data(const uint8_t *event_data,
202948761c62SAndrew Jeffery 					      size_t event_data_size,
203048761c62SAndrew Jeffery 					      uint8_t *event_data_format,
203148761c62SAndrew Jeffery 					      uint8_t *number_of_change_records,
203248761c62SAndrew Jeffery 					      size_t *change_record_data_offset)
203348761c62SAndrew Jeffery {
203448761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
203548761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
203648761c62SAndrew Jeffery 	int rc;
203748761c62SAndrew Jeffery 
203890bbe6c0SAndrew Jeffery 	if (event_data == NULL || event_data_format == NULL ||
203990bbe6c0SAndrew Jeffery 	    number_of_change_records == NULL ||
204048761c62SAndrew Jeffery 	    change_record_data_offset == NULL) {
204148761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
204248761c62SAndrew Jeffery 	}
204348761c62SAndrew Jeffery 
204448761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH,
204548761c62SAndrew Jeffery 				 event_data, event_data_size);
204648761c62SAndrew Jeffery 	if (rc) {
204748761c62SAndrew Jeffery 		return rc;
204848761c62SAndrew Jeffery 	}
204948761c62SAndrew Jeffery 
205048761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_data_format);
205148761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, number_of_change_records);
205248761c62SAndrew Jeffery 
205348761c62SAndrew Jeffery 	*change_record_data_offset =
205448761c62SAndrew Jeffery 		sizeof(*event_data_format) + sizeof(*number_of_change_records);
205548761c62SAndrew Jeffery 
205648761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
205748761c62SAndrew Jeffery }
205848761c62SAndrew Jeffery 
2059f874b383SThu Nguyen LIBPLDM_ABI_STABLE
20607739d123SThu Nguyen int decode_pldm_message_poll_event_data(
20617739d123SThu Nguyen 	const void *event_data, size_t event_data_length,
20627739d123SThu Nguyen 	struct pldm_message_poll_event *poll_event)
206348761c62SAndrew Jeffery {
206448761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
206548761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
206648761c62SAndrew Jeffery 	int rc;
206748761c62SAndrew Jeffery 
206890bbe6c0SAndrew Jeffery 	if (!event_data || !poll_event) {
20697739d123SThu Nguyen 		return -EINVAL;
207048761c62SAndrew Jeffery 	}
207148761c62SAndrew Jeffery 
20727739d123SThu Nguyen 	rc = pldm_msgbuf_init_errno(buf, PLDM_MSG_POLL_EVENT_LENGTH, event_data,
207348761c62SAndrew Jeffery 				    event_data_length);
207448761c62SAndrew Jeffery 	if (rc) {
207548761c62SAndrew Jeffery 		return rc;
207648761c62SAndrew Jeffery 	}
207748761c62SAndrew Jeffery 
20787739d123SThu Nguyen 	pldm_msgbuf_extract(buf, poll_event->format_version);
20797739d123SThu Nguyen 	rc = pldm_msgbuf_extract(buf, poll_event->event_id);
208048761c62SAndrew Jeffery 	if (rc) {
208148761c62SAndrew Jeffery 		return rc;
208248761c62SAndrew Jeffery 	}
208348761c62SAndrew Jeffery 
20847739d123SThu Nguyen 	if (poll_event->event_id == 0x0000 || poll_event->event_id == 0xffff) {
20857739d123SThu Nguyen 		return -EPROTO;
208648761c62SAndrew Jeffery 	}
208748761c62SAndrew Jeffery 
20887739d123SThu Nguyen 	pldm_msgbuf_extract(buf, poll_event->data_transfer_handle);
208948761c62SAndrew Jeffery 
209048761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
209148761c62SAndrew Jeffery }
209248761c62SAndrew Jeffery 
209348761c62SAndrew Jeffery LIBPLDM_ABI_TESTING
20947739d123SThu Nguyen int encode_pldm_message_poll_event_data(
20957739d123SThu Nguyen 	const struct pldm_message_poll_event *poll_event, void *event_data,
209648761c62SAndrew Jeffery 	size_t event_data_length)
209748761c62SAndrew Jeffery {
209848761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
209948761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
210048761c62SAndrew Jeffery 	int rc;
210148761c62SAndrew Jeffery 
210290bbe6c0SAndrew Jeffery 	if (poll_event == NULL || event_data == NULL) {
210390bbe6c0SAndrew Jeffery 		return -EINVAL;
210490bbe6c0SAndrew Jeffery 	}
210590bbe6c0SAndrew Jeffery 
21067739d123SThu Nguyen 	if (poll_event->event_id == 0x0000 || poll_event->event_id == 0xffff) {
21077739d123SThu Nguyen 		return -EPROTO;
210848761c62SAndrew Jeffery 	}
210948761c62SAndrew Jeffery 
21107739d123SThu Nguyen 	rc = pldm_msgbuf_init_errno(buf, PLDM_MSG_POLL_EVENT_LENGTH, event_data,
211148761c62SAndrew Jeffery 				    event_data_length);
211248761c62SAndrew Jeffery 	if (rc) {
211348761c62SAndrew Jeffery 		return rc;
211448761c62SAndrew Jeffery 	}
21157739d123SThu Nguyen 	pldm_msgbuf_insert(buf, poll_event->format_version);
21167739d123SThu Nguyen 	pldm_msgbuf_insert(buf, poll_event->event_id);
21177739d123SThu Nguyen 	pldm_msgbuf_insert(buf, poll_event->data_transfer_handle);
211848761c62SAndrew Jeffery 
21197739d123SThu Nguyen 	return pldm_msgbuf_destroy_consumed(buf);
212048761c62SAndrew Jeffery }
212148761c62SAndrew Jeffery 
212248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
212348761c62SAndrew Jeffery int decode_pldm_pdr_repository_change_record_data(
212448761c62SAndrew Jeffery 	const uint8_t *change_record_data, size_t change_record_data_size,
212548761c62SAndrew Jeffery 	uint8_t *event_data_operation, uint8_t *number_of_change_entries,
212648761c62SAndrew Jeffery 	size_t *change_entry_data_offset)
212748761c62SAndrew Jeffery {
212848761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
212948761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
213048761c62SAndrew Jeffery 	int rc;
213148761c62SAndrew Jeffery 
213290bbe6c0SAndrew Jeffery 	if (change_record_data == NULL || event_data_operation == NULL ||
213390bbe6c0SAndrew Jeffery 	    number_of_change_entries == NULL ||
213448761c62SAndrew Jeffery 	    change_entry_data_offset == NULL) {
213548761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
213648761c62SAndrew Jeffery 	}
213748761c62SAndrew Jeffery 
213848761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf,
213948761c62SAndrew Jeffery 				 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH,
214048761c62SAndrew Jeffery 				 change_record_data, change_record_data_size);
214148761c62SAndrew Jeffery 	if (rc) {
214248761c62SAndrew Jeffery 		return rc;
214348761c62SAndrew Jeffery 	}
214448761c62SAndrew Jeffery 
214548761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_data_operation);
214648761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, number_of_change_entries);
214748761c62SAndrew Jeffery 
214848761c62SAndrew Jeffery 	*change_entry_data_offset = sizeof(*event_data_operation) +
214948761c62SAndrew Jeffery 				    sizeof(*number_of_change_entries);
215048761c62SAndrew Jeffery 
215148761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
215248761c62SAndrew Jeffery }
215348761c62SAndrew Jeffery 
215448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
215548761c62SAndrew Jeffery int encode_get_sensor_reading_req(uint8_t instance_id, uint16_t sensor_id,
215648761c62SAndrew Jeffery 				  uint8_t rearm_event_state,
215748761c62SAndrew Jeffery 				  struct pldm_msg *msg)
215848761c62SAndrew Jeffery {
215948761c62SAndrew Jeffery 	if (msg == NULL) {
216048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
216148761c62SAndrew Jeffery 	}
216248761c62SAndrew Jeffery 
216348761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
216448761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
216548761c62SAndrew Jeffery 	header.instance = instance_id;
216648761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
216748761c62SAndrew Jeffery 	header.command = PLDM_GET_SENSOR_READING;
216848761c62SAndrew Jeffery 
216948761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
217048761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
217148761c62SAndrew Jeffery 		return rc;
217248761c62SAndrew Jeffery 	}
217348761c62SAndrew Jeffery 
217448761c62SAndrew Jeffery 	struct pldm_get_sensor_reading_req *request =
217548761c62SAndrew Jeffery 		(struct pldm_get_sensor_reading_req *)msg->payload;
217648761c62SAndrew Jeffery 
217748761c62SAndrew Jeffery 	request->sensor_id = htole16(sensor_id);
217848761c62SAndrew Jeffery 	request->rearm_event_state = rearm_event_state;
217948761c62SAndrew Jeffery 
218048761c62SAndrew Jeffery 	return PLDM_SUCCESS;
218148761c62SAndrew Jeffery }
218248761c62SAndrew Jeffery 
218348761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
218448761c62SAndrew Jeffery int decode_get_sensor_reading_resp(
218548761c62SAndrew Jeffery 	const struct pldm_msg *msg, size_t payload_length,
218648761c62SAndrew Jeffery 	uint8_t *completion_code, uint8_t *sensor_data_size,
218748761c62SAndrew Jeffery 	uint8_t *sensor_operational_state, uint8_t *sensor_event_message_enable,
218848761c62SAndrew Jeffery 	uint8_t *present_state, uint8_t *previous_state, uint8_t *event_state,
218948761c62SAndrew Jeffery 	uint8_t *present_reading)
219048761c62SAndrew Jeffery {
219148761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
219248761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
219348761c62SAndrew Jeffery 	int rc;
219448761c62SAndrew Jeffery 
219548761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL ||
219648761c62SAndrew Jeffery 	    sensor_data_size == NULL || sensor_operational_state == NULL ||
219748761c62SAndrew Jeffery 	    sensor_event_message_enable == NULL || present_state == NULL ||
219848761c62SAndrew Jeffery 	    previous_state == NULL || event_state == NULL ||
219948761c62SAndrew Jeffery 	    present_reading == NULL) {
220048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
220148761c62SAndrew Jeffery 	}
220248761c62SAndrew Jeffery 
220348761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_GET_SENSOR_READING_MIN_RESP_BYTES,
220448761c62SAndrew Jeffery 				 msg->payload, payload_length);
220548761c62SAndrew Jeffery 	if (rc) {
220648761c62SAndrew Jeffery 		return rc;
220748761c62SAndrew Jeffery 	}
220848761c62SAndrew Jeffery 
220948761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, completion_code);
221048761c62SAndrew Jeffery 	if (rc) {
221148761c62SAndrew Jeffery 		return rc;
221248761c62SAndrew Jeffery 	}
221348761c62SAndrew Jeffery 
221448761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
221548761c62SAndrew Jeffery 		return PLDM_SUCCESS;
221648761c62SAndrew Jeffery 	}
221748761c62SAndrew Jeffery 
221848761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, sensor_data_size);
221948761c62SAndrew Jeffery 	if (rc) {
222048761c62SAndrew Jeffery 		return rc;
222148761c62SAndrew Jeffery 	}
222248761c62SAndrew Jeffery 
222348761c62SAndrew Jeffery 	if (*sensor_data_size > PLDM_SENSOR_DATA_SIZE_SINT32) {
222448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
222548761c62SAndrew Jeffery 	}
222648761c62SAndrew Jeffery 
222748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, sensor_operational_state);
222848761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, sensor_event_message_enable);
222948761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, present_state);
223048761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, previous_state);
223148761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_state);
223248761c62SAndrew Jeffery 
223348761c62SAndrew Jeffery 	pldm_msgbuf_extract_sensor_value(buf, *sensor_data_size,
223448761c62SAndrew Jeffery 					 present_reading);
223548761c62SAndrew Jeffery 
223648761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
223748761c62SAndrew Jeffery }
223848761c62SAndrew Jeffery 
223948761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
224048761c62SAndrew Jeffery int encode_get_sensor_reading_resp(uint8_t instance_id, uint8_t completion_code,
224148761c62SAndrew Jeffery 				   uint8_t sensor_data_size,
224248761c62SAndrew Jeffery 				   uint8_t sensor_operational_state,
224348761c62SAndrew Jeffery 				   uint8_t sensor_event_message_enable,
224448761c62SAndrew Jeffery 				   uint8_t present_state,
224548761c62SAndrew Jeffery 				   uint8_t previous_state, uint8_t event_state,
224648761c62SAndrew Jeffery 				   const uint8_t *present_reading,
224748761c62SAndrew Jeffery 				   struct pldm_msg *msg, size_t payload_length)
224848761c62SAndrew Jeffery {
224948761c62SAndrew Jeffery 	if (msg == NULL || present_reading == NULL) {
225048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
225148761c62SAndrew Jeffery 	}
225248761c62SAndrew Jeffery 
225348761c62SAndrew Jeffery 	if (sensor_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
225448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
225548761c62SAndrew Jeffery 	}
225648761c62SAndrew Jeffery 
225748761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
225848761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
225948761c62SAndrew Jeffery 	header.instance = instance_id;
226048761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
226148761c62SAndrew Jeffery 	header.command = PLDM_GET_SENSOR_READING;
226248761c62SAndrew Jeffery 
226348761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
226448761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
226548761c62SAndrew Jeffery 		return rc;
226648761c62SAndrew Jeffery 	}
226748761c62SAndrew Jeffery 
226848761c62SAndrew Jeffery 	struct pldm_get_sensor_reading_resp *response =
226948761c62SAndrew Jeffery 		(struct pldm_get_sensor_reading_resp *)msg->payload;
227048761c62SAndrew Jeffery 
227148761c62SAndrew Jeffery 	response->completion_code = completion_code;
227248761c62SAndrew Jeffery 	response->sensor_data_size = sensor_data_size;
227348761c62SAndrew Jeffery 	response->sensor_operational_state = sensor_operational_state;
227448761c62SAndrew Jeffery 	response->sensor_event_message_enable = sensor_event_message_enable;
227548761c62SAndrew Jeffery 	response->present_state = present_state;
227648761c62SAndrew Jeffery 	response->previous_state = previous_state;
227748761c62SAndrew Jeffery 	response->event_state = event_state;
227848761c62SAndrew Jeffery 
227948761c62SAndrew Jeffery 	if (sensor_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
228048761c62SAndrew Jeffery 	    sensor_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
228148761c62SAndrew Jeffery 		if (payload_length != PLDM_GET_SENSOR_READING_MIN_RESP_BYTES) {
228248761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
228348761c62SAndrew Jeffery 		}
228448761c62SAndrew Jeffery 		response->present_reading[0] = *present_reading;
228548761c62SAndrew Jeffery 
228648761c62SAndrew Jeffery 	} else if (sensor_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
228748761c62SAndrew Jeffery 		   sensor_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
228848761c62SAndrew Jeffery 		if (payload_length !=
228948761c62SAndrew Jeffery 		    PLDM_GET_SENSOR_READING_MIN_RESP_BYTES + 1) {
229048761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
229148761c62SAndrew Jeffery 		}
229248761c62SAndrew Jeffery 		uint16_t val = *(uint16_t *)present_reading;
229348761c62SAndrew Jeffery 		val = htole16(val);
229448761c62SAndrew Jeffery 		memcpy(response->present_reading, &val, 2);
229548761c62SAndrew Jeffery 
229648761c62SAndrew Jeffery 	} else if (sensor_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
229748761c62SAndrew Jeffery 		   sensor_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
229848761c62SAndrew Jeffery 		if (payload_length !=
229948761c62SAndrew Jeffery 		    PLDM_GET_SENSOR_READING_MIN_RESP_BYTES + 3) {
230048761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_LENGTH;
230148761c62SAndrew Jeffery 		}
230248761c62SAndrew Jeffery 		uint32_t val = *(uint32_t *)present_reading;
230348761c62SAndrew Jeffery 		val = htole32(val);
230448761c62SAndrew Jeffery 		memcpy(response->present_reading, &val, 4);
230548761c62SAndrew Jeffery 	}
230648761c62SAndrew Jeffery 
230748761c62SAndrew Jeffery 	return PLDM_SUCCESS;
230848761c62SAndrew Jeffery }
230948761c62SAndrew Jeffery 
231048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
231148761c62SAndrew Jeffery int decode_get_sensor_reading_req(const struct pldm_msg *msg,
231248761c62SAndrew Jeffery 				  size_t payload_length, uint16_t *sensor_id,
231348761c62SAndrew Jeffery 				  uint8_t *rearm_event_state)
231448761c62SAndrew Jeffery {
231548761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
231648761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
231748761c62SAndrew Jeffery 	int rc;
231848761c62SAndrew Jeffery 
231948761c62SAndrew Jeffery 	if (msg == NULL || sensor_id == NULL || rearm_event_state == NULL) {
232048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
232148761c62SAndrew Jeffery 	}
232248761c62SAndrew Jeffery 
232348761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_GET_SENSOR_READING_REQ_BYTES,
232448761c62SAndrew Jeffery 				 msg->payload, payload_length);
232548761c62SAndrew Jeffery 	if (rc) {
232648761c62SAndrew Jeffery 		return rc;
232748761c62SAndrew Jeffery 	}
232848761c62SAndrew Jeffery 
232948761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, sensor_id);
233048761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, rearm_event_state);
233148761c62SAndrew Jeffery 
233248761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
233348761c62SAndrew Jeffery }
233448761c62SAndrew Jeffery 
233548761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
233648761c62SAndrew Jeffery int encode_set_event_receiver_req(uint8_t instance_id,
233748761c62SAndrew Jeffery 				  uint8_t event_message_global_enable,
233848761c62SAndrew Jeffery 				  uint8_t transport_protocol_type,
233948761c62SAndrew Jeffery 				  uint8_t event_receiver_address_info,
234048761c62SAndrew Jeffery 				  uint16_t heartbeat_timer,
234148761c62SAndrew Jeffery 				  struct pldm_msg *msg)
234248761c62SAndrew Jeffery {
234348761c62SAndrew Jeffery 	if (msg == NULL) {
234448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
234548761c62SAndrew Jeffery 	}
234648761c62SAndrew Jeffery 
234748761c62SAndrew Jeffery 	if (transport_protocol_type != PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP) {
234848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
234948761c62SAndrew Jeffery 	}
235048761c62SAndrew Jeffery 
235148761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
235248761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
235348761c62SAndrew Jeffery 	header.instance = instance_id;
235448761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
235548761c62SAndrew Jeffery 	header.command = PLDM_SET_EVENT_RECEIVER;
235648761c62SAndrew Jeffery 
235748761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
235848761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
235948761c62SAndrew Jeffery 		return rc;
236048761c62SAndrew Jeffery 	}
236148761c62SAndrew Jeffery 
236248761c62SAndrew Jeffery 	struct pldm_set_event_receiver_req *request =
236348761c62SAndrew Jeffery 		(struct pldm_set_event_receiver_req *)msg->payload;
236448761c62SAndrew Jeffery 	request->event_message_global_enable = event_message_global_enable;
236548761c62SAndrew Jeffery 
236648761c62SAndrew Jeffery 	request->transport_protocol_type = transport_protocol_type;
236748761c62SAndrew Jeffery 	request->event_receiver_address_info = event_receiver_address_info;
236848761c62SAndrew Jeffery 
236948761c62SAndrew Jeffery 	if (event_message_global_enable ==
237048761c62SAndrew Jeffery 	    PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE) {
237148761c62SAndrew Jeffery 		if (heartbeat_timer == 0) {
237248761c62SAndrew Jeffery 			return PLDM_ERROR_INVALID_DATA;
237348761c62SAndrew Jeffery 		}
237448761c62SAndrew Jeffery 		request->heartbeat_timer = htole16(heartbeat_timer);
237548761c62SAndrew Jeffery 	}
237648761c62SAndrew Jeffery 
237748761c62SAndrew Jeffery 	return PLDM_SUCCESS;
237848761c62SAndrew Jeffery }
237948761c62SAndrew Jeffery 
238048761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
238148761c62SAndrew Jeffery int decode_set_event_receiver_resp(const struct pldm_msg *msg,
238248761c62SAndrew Jeffery 				   size_t payload_length,
238348761c62SAndrew Jeffery 				   uint8_t *completion_code)
238448761c62SAndrew Jeffery {
238548761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
238648761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
238748761c62SAndrew Jeffery 	int rc;
238848761c62SAndrew Jeffery 
238948761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL) {
239048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
239148761c62SAndrew Jeffery 	}
239248761c62SAndrew Jeffery 
239348761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_SET_EVENT_RECEIVER_RESP_BYTES,
239448761c62SAndrew Jeffery 				 msg->payload, payload_length);
239548761c62SAndrew Jeffery 	if (rc) {
239648761c62SAndrew Jeffery 		return rc;
239748761c62SAndrew Jeffery 	}
239848761c62SAndrew Jeffery 
239948761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, completion_code);
240048761c62SAndrew Jeffery 
240148761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
240248761c62SAndrew Jeffery }
240348761c62SAndrew Jeffery 
240448761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
240548761c62SAndrew Jeffery int decode_set_event_receiver_req(const struct pldm_msg *msg,
240648761c62SAndrew Jeffery 				  size_t payload_length,
240748761c62SAndrew Jeffery 				  uint8_t *event_message_global_enable,
240848761c62SAndrew Jeffery 				  uint8_t *transport_protocol_type,
240948761c62SAndrew Jeffery 				  uint8_t *event_receiver_address_info,
241048761c62SAndrew Jeffery 				  uint16_t *heartbeat_timer)
241148761c62SAndrew Jeffery 
241248761c62SAndrew Jeffery {
241348761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
241448761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
241548761c62SAndrew Jeffery 	int rc;
241648761c62SAndrew Jeffery 
241748761c62SAndrew Jeffery 	if (msg == NULL || event_message_global_enable == NULL ||
241848761c62SAndrew Jeffery 	    transport_protocol_type == NULL ||
241948761c62SAndrew Jeffery 	    event_receiver_address_info == NULL || heartbeat_timer == NULL) {
242048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
242148761c62SAndrew Jeffery 	}
242248761c62SAndrew Jeffery 
242348761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_SET_EVENT_RECEIVER_REQ_BYTES,
242448761c62SAndrew Jeffery 				 msg->payload, payload_length);
242548761c62SAndrew Jeffery 	if (rc) {
242648761c62SAndrew Jeffery 		return rc;
242748761c62SAndrew Jeffery 	}
242848761c62SAndrew Jeffery 
242948761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_message_global_enable);
243048761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, transport_protocol_type);
243148761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_receiver_address_info);
243248761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, heartbeat_timer);
243348761c62SAndrew Jeffery 
243448761c62SAndrew Jeffery 	rc = pldm_msgbuf_destroy(buf);
243548761c62SAndrew Jeffery 	if (rc) {
243648761c62SAndrew Jeffery 		return rc;
243748761c62SAndrew Jeffery 	}
243848761c62SAndrew Jeffery 
243948761c62SAndrew Jeffery 	if ((*event_message_global_enable ==
244048761c62SAndrew Jeffery 	     PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE) &&
244148761c62SAndrew Jeffery 	    (*heartbeat_timer == 0)) {
244248761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
244348761c62SAndrew Jeffery 	}
244448761c62SAndrew Jeffery 
244548761c62SAndrew Jeffery 	return PLDM_SUCCESS;
244648761c62SAndrew Jeffery }
244748761c62SAndrew Jeffery 
244848761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
244948761c62SAndrew Jeffery int encode_set_event_receiver_resp(uint8_t instance_id, uint8_t completion_code,
245048761c62SAndrew Jeffery 				   struct pldm_msg *msg)
245148761c62SAndrew Jeffery 
245248761c62SAndrew Jeffery {
245348761c62SAndrew Jeffery 	if (msg == NULL) {
245448761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
245548761c62SAndrew Jeffery 	}
245648761c62SAndrew Jeffery 
245748761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
245848761c62SAndrew Jeffery 	header.instance = instance_id;
245948761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
246048761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
246148761c62SAndrew Jeffery 	header.command = PLDM_SET_EVENT_RECEIVER;
246248761c62SAndrew Jeffery 
246348761c62SAndrew Jeffery 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
246448761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
246548761c62SAndrew Jeffery 		return rc;
246648761c62SAndrew Jeffery 	}
246748761c62SAndrew Jeffery 
246848761c62SAndrew Jeffery 	msg->payload[0] = completion_code;
246948761c62SAndrew Jeffery 
247048761c62SAndrew Jeffery 	return PLDM_SUCCESS;
247148761c62SAndrew Jeffery }
247248761c62SAndrew Jeffery 
247348761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
247448761c62SAndrew Jeffery int encode_poll_for_platform_event_message_req(uint8_t instance_id,
247548761c62SAndrew Jeffery 					       uint8_t format_version,
247648761c62SAndrew Jeffery 					       uint8_t transfer_operation_flag,
247748761c62SAndrew Jeffery 					       uint32_t data_transfer_handle,
247848761c62SAndrew Jeffery 					       uint16_t event_id_to_acknowledge,
247948761c62SAndrew Jeffery 					       struct pldm_msg *msg,
248048761c62SAndrew Jeffery 					       size_t payload_length)
248148761c62SAndrew Jeffery {
248248761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
248348761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
248448761c62SAndrew Jeffery 	int rc;
248548761c62SAndrew Jeffery 
248648761c62SAndrew Jeffery 	if (msg == NULL) {
248748761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
248848761c62SAndrew Jeffery 	}
248948761c62SAndrew Jeffery 
2490*387b10f6SThu Nguyen 	rc = pldm_platform_poll_for_platform_event_message_validate(
2491*387b10f6SThu Nguyen 		transfer_operation_flag, event_id_to_acknowledge);
2492*387b10f6SThu Nguyen 	if (rc < 0) {
2493*387b10f6SThu Nguyen 		return PLDM_ERROR_INVALID_DATA;
2494*387b10f6SThu Nguyen 	}
2495*387b10f6SThu Nguyen 
249648761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
249748761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
249848761c62SAndrew Jeffery 	header.instance = instance_id;
249948761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
250048761c62SAndrew Jeffery 	header.command = PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE;
250148761c62SAndrew Jeffery 
250248761c62SAndrew Jeffery 	rc = pack_pldm_header(&header, &(msg->hdr));
250348761c62SAndrew Jeffery 	if (rc != PLDM_SUCCESS) {
250448761c62SAndrew Jeffery 		return rc;
250548761c62SAndrew Jeffery 	}
250648761c62SAndrew Jeffery 
250748761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(
250848761c62SAndrew Jeffery 		buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
250948761c62SAndrew Jeffery 		msg->payload, payload_length);
251048761c62SAndrew Jeffery 	if (rc) {
251148761c62SAndrew Jeffery 		return rc;
251248761c62SAndrew Jeffery 	}
251348761c62SAndrew Jeffery 
251448761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, format_version);
251548761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, transfer_operation_flag);
251648761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, data_transfer_handle);
251748761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, event_id_to_acknowledge);
251848761c62SAndrew Jeffery 
251948761c62SAndrew Jeffery 	return pldm_msgbuf_destroy(buf);
252048761c62SAndrew Jeffery }
252148761c62SAndrew Jeffery 
252248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
252348761c62SAndrew Jeffery int decode_poll_for_platform_event_message_resp(
252448761c62SAndrew Jeffery 	const struct pldm_msg *msg, size_t payload_length,
252548761c62SAndrew Jeffery 	uint8_t *completion_code, uint8_t *tid, uint16_t *event_id,
252648761c62SAndrew Jeffery 	uint32_t *next_data_transfer_handle, uint8_t *transfer_flag,
252748761c62SAndrew Jeffery 	uint8_t *event_class, uint32_t *event_data_size, void **event_data,
252848761c62SAndrew Jeffery 	uint32_t *event_data_integrity_checksum)
252948761c62SAndrew Jeffery {
253048761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
253148761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
253248761c62SAndrew Jeffery 	int rc;
253348761c62SAndrew Jeffery 
253448761c62SAndrew Jeffery 	if (msg == NULL || completion_code == NULL || tid == NULL ||
253548761c62SAndrew Jeffery 	    event_id == NULL || next_data_transfer_handle == NULL ||
253648761c62SAndrew Jeffery 	    transfer_flag == NULL || event_class == NULL ||
253748761c62SAndrew Jeffery 	    event_data_size == NULL || event_data == NULL ||
253848761c62SAndrew Jeffery 	    event_data_integrity_checksum == NULL) {
253948761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
254048761c62SAndrew Jeffery 	}
254148761c62SAndrew Jeffery 
254248761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(
254348761c62SAndrew Jeffery 		buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
254448761c62SAndrew Jeffery 		msg->payload, payload_length);
254548761c62SAndrew Jeffery 	if (rc) {
254648761c62SAndrew Jeffery 		return rc;
254748761c62SAndrew Jeffery 	}
254848761c62SAndrew Jeffery 
254948761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, completion_code);
255048761c62SAndrew Jeffery 	if (rc) {
255148761c62SAndrew Jeffery 		return rc;
255248761c62SAndrew Jeffery 	}
255348761c62SAndrew Jeffery 	if (PLDM_SUCCESS != *completion_code) {
255448761c62SAndrew Jeffery 		return *completion_code;
255548761c62SAndrew Jeffery 	}
255648761c62SAndrew Jeffery 
255748761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, tid);
255848761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, event_id);
255948761c62SAndrew Jeffery 	if (rc) {
256048761c62SAndrew Jeffery 		return rc;
256148761c62SAndrew Jeffery 	}
256248761c62SAndrew Jeffery 	if ((*event_id == 0) || (*event_id == 0xffff)) {
256348761c62SAndrew Jeffery 		return PLDM_SUCCESS;
256448761c62SAndrew Jeffery 	}
256548761c62SAndrew Jeffery 
256648761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, next_data_transfer_handle);
256748761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, transfer_flag);
256848761c62SAndrew Jeffery 	if (rc) {
256948761c62SAndrew Jeffery 		return rc;
257048761c62SAndrew Jeffery 	}
257148761c62SAndrew Jeffery 
257248761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, event_class);
257348761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_p(buf, event_data_size);
257448761c62SAndrew Jeffery 	if (rc) {
257548761c62SAndrew Jeffery 		return rc;
257648761c62SAndrew Jeffery 	}
257748761c62SAndrew Jeffery 	if (*event_data_size > payload_length) {
257848761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
257948761c62SAndrew Jeffery 	}
258048761c62SAndrew Jeffery 
258148761c62SAndrew Jeffery 	if (*event_data_size > 0) {
258248761c62SAndrew Jeffery 		pldm_msgbuf_span_required(buf, *event_data_size, event_data);
258348761c62SAndrew Jeffery 	}
258448761c62SAndrew Jeffery 
258548761c62SAndrew Jeffery 	if (*transfer_flag == PLDM_END ||
258648761c62SAndrew Jeffery 	    *transfer_flag == PLDM_START_AND_END) {
258748761c62SAndrew Jeffery 		pldm_msgbuf_extract_p(buf, event_data_integrity_checksum);
258848761c62SAndrew Jeffery 	}
258948761c62SAndrew Jeffery 
259048761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
259148761c62SAndrew Jeffery }
259248761c62SAndrew Jeffery 
259348761c62SAndrew Jeffery LIBPLDM_ABI_TESTING
259448761c62SAndrew Jeffery int decode_numeric_effecter_pdr_data(
259548761c62SAndrew Jeffery 	const void *pdr_data, size_t pdr_data_length,
259648761c62SAndrew Jeffery 	struct pldm_numeric_effecter_value_pdr *pdr_value)
259748761c62SAndrew Jeffery {
259848761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
259948761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
260048761c62SAndrew Jeffery 	struct pldm_value_pdr_hdr hdr;
260148761c62SAndrew Jeffery 	int rc;
260248761c62SAndrew Jeffery 
260390bbe6c0SAndrew Jeffery 	if (!pdr_data || !pdr_value) {
260490bbe6c0SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
260590bbe6c0SAndrew Jeffery 	}
260690bbe6c0SAndrew Jeffery 
260748761c62SAndrew Jeffery 	rc = pldm_msgbuf_init_cc(buf, PLDM_PDR_NUMERIC_EFFECTER_PDR_MIN_LENGTH,
260848761c62SAndrew Jeffery 				 pdr_data, pdr_data_length);
260948761c62SAndrew Jeffery 	if (rc) {
261048761c62SAndrew Jeffery 		return rc;
261148761c62SAndrew Jeffery 	}
261248761c62SAndrew Jeffery 
261348761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract_value_pdr_hdr(buf, &hdr);
261448761c62SAndrew Jeffery 	if (rc) {
261548761c62SAndrew Jeffery 		return rc;
261648761c62SAndrew Jeffery 	}
261748761c62SAndrew Jeffery 
261848761c62SAndrew Jeffery 	rc = pldm_platform_pdr_hdr_validate(
261948761c62SAndrew Jeffery 		&hdr, PLDM_PDR_NUMERIC_EFFECTER_PDR_MIN_LENGTH,
262048761c62SAndrew Jeffery 		pdr_data_length);
262148761c62SAndrew Jeffery 	if (rc) {
262248761c62SAndrew Jeffery 		return rc;
262348761c62SAndrew Jeffery 	}
262448761c62SAndrew Jeffery 
262548761c62SAndrew Jeffery 	memcpy(&pdr_value->hdr, &hdr, sizeof(hdr));
262648761c62SAndrew Jeffery 
262748761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->terminus_handle);
262848761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->effecter_id);
262948761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->entity_type);
263048761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->entity_instance);
263148761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->container_id);
263248761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->effecter_semantic_id);
263348761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->effecter_init);
263448761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->effecter_auxiliary_names);
263548761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->base_unit);
263648761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->unit_modifier);
263748761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->rate_unit);
263848761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->base_oem_unit_handle);
263948761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_unit);
264048761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_unit_modifier);
264148761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_rate_unit);
264248761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->aux_oem_unit_handle);
264348761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->is_linear);
264448761c62SAndrew Jeffery 
264548761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, pdr_value->effecter_data_size);
264648761c62SAndrew Jeffery 	if (rc) {
264748761c62SAndrew Jeffery 		return rc;
264848761c62SAndrew Jeffery 	}
264948761c62SAndrew Jeffery 	if (pdr_value->effecter_data_size > PLDM_SENSOR_DATA_SIZE_MAX) {
265048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
265148761c62SAndrew Jeffery 	}
265248761c62SAndrew Jeffery 
265348761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->resolution);
265448761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->offset);
265548761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->accuracy);
265648761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->plus_tolerance);
265748761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->minus_tolerance);
265848761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->state_transition_interval);
265948761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->transition_interval);
266048761c62SAndrew Jeffery 	pldm_msgbuf_extract_effecter_data(buf, pdr_value->effecter_data_size,
266148761c62SAndrew Jeffery 					  pdr_value->max_settable);
266248761c62SAndrew Jeffery 	pldm_msgbuf_extract_effecter_data(buf, pdr_value->effecter_data_size,
266348761c62SAndrew Jeffery 					  pdr_value->min_settable);
266448761c62SAndrew Jeffery 
266548761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, pdr_value->range_field_format);
266648761c62SAndrew Jeffery 	if (rc) {
266748761c62SAndrew Jeffery 		return rc;
266848761c62SAndrew Jeffery 	}
266948761c62SAndrew Jeffery 	if (pdr_value->range_field_format > PLDM_RANGE_FIELD_FORMAT_MAX) {
267048761c62SAndrew Jeffery 		return PLDM_ERROR_INVALID_DATA;
267148761c62SAndrew Jeffery 	}
267248761c62SAndrew Jeffery 
267348761c62SAndrew Jeffery 	pldm_msgbuf_extract(buf, pdr_value->range_field_support.byte);
267448761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
267548761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->nominal_value);
267648761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
267748761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->normal_max);
267848761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
267948761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->normal_min);
268048761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
268148761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->rated_max);
268248761c62SAndrew Jeffery 	pldm_msgbuf_extract_range_field_format(
268348761c62SAndrew Jeffery 		buf, pdr_value->range_field_format, pdr_value->rated_min);
268448761c62SAndrew Jeffery 
268548761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
268648761c62SAndrew Jeffery }
268748761c62SAndrew Jeffery 
2688de67ab62STal Yacobi LIBPLDM_ABI_STABLE
268948761c62SAndrew Jeffery int encode_get_state_effecter_states_req(uint8_t instance_id,
269048761c62SAndrew Jeffery 					 uint16_t effecter_id,
269148761c62SAndrew Jeffery 					 struct pldm_msg *msg,
269248761c62SAndrew Jeffery 					 size_t payload_length)
269348761c62SAndrew Jeffery {
269448761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
269548761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
269648761c62SAndrew Jeffery 	int rc;
269748761c62SAndrew Jeffery 
269848761c62SAndrew Jeffery 	if (msg == NULL) {
2699f490a38fSTal Yacobi 		return -EINVAL;
270048761c62SAndrew Jeffery 	}
270148761c62SAndrew Jeffery 
270248761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
270348761c62SAndrew Jeffery 	header.msg_type = PLDM_REQUEST;
270448761c62SAndrew Jeffery 	header.instance = instance_id;
270548761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
270648761c62SAndrew Jeffery 	header.command = PLDM_GET_STATE_EFFECTER_STATES;
270748761c62SAndrew Jeffery 
2708f490a38fSTal Yacobi 	rc = pack_pldm_header_errno(&header, &msg->hdr);
2709f490a38fSTal Yacobi 	if (rc < 0) {
271048761c62SAndrew Jeffery 		return rc;
271148761c62SAndrew Jeffery 	}
271248761c62SAndrew Jeffery 
2713f490a38fSTal Yacobi 	rc = pldm_msgbuf_init_errno(buf,
2714f490a38fSTal Yacobi 				    PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES,
271548761c62SAndrew Jeffery 				    msg->payload, payload_length);
271648761c62SAndrew Jeffery 	if (rc) {
271748761c62SAndrew Jeffery 		return rc;
271848761c62SAndrew Jeffery 	}
271948761c62SAndrew Jeffery 
272048761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, effecter_id);
272148761c62SAndrew Jeffery 
272248761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
272348761c62SAndrew Jeffery }
272448761c62SAndrew Jeffery 
2725de67ab62STal Yacobi LIBPLDM_ABI_STABLE
272648761c62SAndrew Jeffery int decode_get_state_effecter_states_req(const struct pldm_msg *msg,
272748761c62SAndrew Jeffery 					 size_t payload_length,
272848761c62SAndrew Jeffery 					 uint16_t *effecter_id)
272948761c62SAndrew Jeffery {
273048761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
273148761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
273248761c62SAndrew Jeffery 	int rc;
273348761c62SAndrew Jeffery 
273448761c62SAndrew Jeffery 	if (msg == NULL || effecter_id == NULL) {
2735f490a38fSTal Yacobi 		return -EINVAL;
273648761c62SAndrew Jeffery 	}
273748761c62SAndrew Jeffery 
2738f490a38fSTal Yacobi 	rc = pldm_msgbuf_init_errno(
2739f490a38fSTal Yacobi 		buf, PLDM_GET_STATE_EFFECTER_STATES_MIN_RESP_BYTES,
274048761c62SAndrew Jeffery 		msg->payload, payload_length);
274148761c62SAndrew Jeffery 	if (rc) {
274248761c62SAndrew Jeffery 		return rc;
274348761c62SAndrew Jeffery 	}
274448761c62SAndrew Jeffery 
274548761c62SAndrew Jeffery 	pldm_msgbuf_extract_p(buf, effecter_id);
274648761c62SAndrew Jeffery 
274748761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
274848761c62SAndrew Jeffery }
274948761c62SAndrew Jeffery 
2750de67ab62STal Yacobi LIBPLDM_ABI_STABLE
275148761c62SAndrew Jeffery int decode_get_state_effecter_states_resp(
275248761c62SAndrew Jeffery 	const struct pldm_msg *msg, size_t payload_length,
275348761c62SAndrew Jeffery 	struct pldm_get_state_effecter_states_resp *resp)
275448761c62SAndrew Jeffery {
275548761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
275648761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
275748761c62SAndrew Jeffery 	get_effecter_state_field *field;
275848761c62SAndrew Jeffery 	int rc;
275948761c62SAndrew Jeffery 	int i;
276048761c62SAndrew Jeffery 
276148761c62SAndrew Jeffery 	if (msg == NULL || resp == NULL) {
2762f490a38fSTal Yacobi 		return -EINVAL;
276348761c62SAndrew Jeffery 	}
276448761c62SAndrew Jeffery 
2765f490a38fSTal Yacobi 	rc = pldm_msgbuf_init_errno(
2766f490a38fSTal Yacobi 		buf, PLDM_GET_STATE_EFFECTER_STATES_MIN_RESP_BYTES,
276748761c62SAndrew Jeffery 		msg->payload, payload_length);
276848761c62SAndrew Jeffery 	if (rc) {
276948761c62SAndrew Jeffery 		return rc;
277048761c62SAndrew Jeffery 	}
277148761c62SAndrew Jeffery 
277248761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, resp->completion_code);
277348761c62SAndrew Jeffery 	if (rc) {
277448761c62SAndrew Jeffery 		return rc;
277548761c62SAndrew Jeffery 	}
277648761c62SAndrew Jeffery 
277748761c62SAndrew Jeffery 	if (PLDM_SUCCESS != resp->completion_code) {
2778f490a38fSTal Yacobi 		return 0;
277948761c62SAndrew Jeffery 	}
278048761c62SAndrew Jeffery 
278148761c62SAndrew Jeffery 	rc = pldm_msgbuf_extract(buf, resp->comp_effecter_count);
278248761c62SAndrew Jeffery 	if (rc) {
278348761c62SAndrew Jeffery 		return rc;
278448761c62SAndrew Jeffery 	}
278548761c62SAndrew Jeffery 
278648761c62SAndrew Jeffery 	uint8_t comp_effecter_count = resp->comp_effecter_count;
278748761c62SAndrew Jeffery 
278848761c62SAndrew Jeffery 	if (comp_effecter_count < PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MIN ||
278948761c62SAndrew Jeffery 	    comp_effecter_count > PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MAX) {
2790f490a38fSTal Yacobi 		return -EBADMSG;
279148761c62SAndrew Jeffery 	}
279248761c62SAndrew Jeffery 
279348761c62SAndrew Jeffery 	for (i = 0, field = resp->field; i < comp_effecter_count;
279448761c62SAndrew Jeffery 	     i++, field++) {
279548761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field->effecter_op_state);
279648761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field->pending_state);
279748761c62SAndrew Jeffery 		pldm_msgbuf_extract(buf, field->present_state);
279848761c62SAndrew Jeffery 	}
279948761c62SAndrew Jeffery 
280048761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
280148761c62SAndrew Jeffery }
280248761c62SAndrew Jeffery 
2803de67ab62STal Yacobi LIBPLDM_ABI_STABLE
280448761c62SAndrew Jeffery int encode_get_state_effecter_states_resp(
280548761c62SAndrew Jeffery 	uint8_t instance_id, struct pldm_get_state_effecter_states_resp *resp,
280648761c62SAndrew Jeffery 	struct pldm_msg *msg, size_t payload_length)
280748761c62SAndrew Jeffery {
280848761c62SAndrew Jeffery 	struct pldm_msgbuf _buf;
280948761c62SAndrew Jeffery 	struct pldm_msgbuf *buf = &_buf;
281048761c62SAndrew Jeffery 	get_effecter_state_field *field;
281148761c62SAndrew Jeffery 	int rc;
281248761c62SAndrew Jeffery 	int i;
281348761c62SAndrew Jeffery 
281448761c62SAndrew Jeffery 	if (msg == NULL || resp == NULL) {
2815f490a38fSTal Yacobi 		return -EINVAL;
281648761c62SAndrew Jeffery 	}
281748761c62SAndrew Jeffery 
281848761c62SAndrew Jeffery 	uint8_t comp_effecter_count = resp->comp_effecter_count;
281948761c62SAndrew Jeffery 
282048761c62SAndrew Jeffery 	if (comp_effecter_count < PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MIN ||
282148761c62SAndrew Jeffery 	    comp_effecter_count > PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MAX) {
2822f490a38fSTal Yacobi 		return -EBADMSG;
282348761c62SAndrew Jeffery 	}
282448761c62SAndrew Jeffery 
282548761c62SAndrew Jeffery 	struct pldm_header_info header = { 0 };
282648761c62SAndrew Jeffery 	header.msg_type = PLDM_RESPONSE;
282748761c62SAndrew Jeffery 	header.instance = instance_id;
282848761c62SAndrew Jeffery 	header.pldm_type = PLDM_PLATFORM;
282948761c62SAndrew Jeffery 	header.command = PLDM_GET_STATE_EFFECTER_STATES;
283048761c62SAndrew Jeffery 
2831f490a38fSTal Yacobi 	rc = pack_pldm_header_errno(&header, &msg->hdr);
2832f490a38fSTal Yacobi 	if (rc < 0) {
283348761c62SAndrew Jeffery 		return rc;
283448761c62SAndrew Jeffery 	}
283548761c62SAndrew Jeffery 
2836f490a38fSTal Yacobi 	rc = pldm_msgbuf_init_errno(
2837f490a38fSTal Yacobi 		buf, PLDM_GET_STATE_EFFECTER_STATES_MIN_RESP_BYTES,
283848761c62SAndrew Jeffery 		msg->payload, payload_length);
283948761c62SAndrew Jeffery 	if (rc) {
284048761c62SAndrew Jeffery 		return rc;
284148761c62SAndrew Jeffery 	}
284248761c62SAndrew Jeffery 
284348761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, resp->completion_code);
284448761c62SAndrew Jeffery 	pldm_msgbuf_insert(buf, comp_effecter_count);
284548761c62SAndrew Jeffery 
284648761c62SAndrew Jeffery 	for (i = 0, field = resp->field; i < comp_effecter_count;
284748761c62SAndrew Jeffery 	     i++, field++) {
284848761c62SAndrew Jeffery 		pldm_msgbuf_insert(buf, field->effecter_op_state);
284948761c62SAndrew Jeffery 		pldm_msgbuf_insert(buf, field->pending_state);
285048761c62SAndrew Jeffery 		pldm_msgbuf_insert(buf, field->present_state);
285148761c62SAndrew Jeffery 	}
285248761c62SAndrew Jeffery 
285348761c62SAndrew Jeffery 	return pldm_msgbuf_destroy_consumed(buf);
285448761c62SAndrew Jeffery }
2855dacfa354SThu Nguyen 
285643cb4b5fSThu Nguyen LIBPLDM_ABI_STABLE
2857dacfa354SThu Nguyen int decode_entity_auxiliary_names_pdr(
2858dacfa354SThu Nguyen 	const void *data, size_t data_length,
2859dacfa354SThu Nguyen 	struct pldm_entity_auxiliary_names_pdr *pdr, size_t pdr_length)
2860dacfa354SThu Nguyen {
2861dacfa354SThu Nguyen 	struct pldm_msgbuf _buf;
2862dacfa354SThu Nguyen 	struct pldm_msgbuf *buf = &_buf;
2863dacfa354SThu Nguyen 	struct pldm_msgbuf _src;
2864dacfa354SThu Nguyen 	struct pldm_msgbuf *src = &_src;
2865dacfa354SThu Nguyen 	struct pldm_msgbuf _dst;
2866dacfa354SThu Nguyen 	struct pldm_msgbuf *dst = &_dst;
2867dacfa354SThu Nguyen 	size_t names_len = 0;
2868dacfa354SThu Nguyen 	void *names = NULL;
2869dacfa354SThu Nguyen 	int rc;
2870dacfa354SThu Nguyen 	int i;
2871dacfa354SThu Nguyen 
287290bbe6c0SAndrew Jeffery 	if (!data || !pdr) {
287390bbe6c0SAndrew Jeffery 		return -EINVAL;
287490bbe6c0SAndrew Jeffery 	}
287590bbe6c0SAndrew Jeffery 
2876dacfa354SThu Nguyen 	/*
2877dacfa354SThu Nguyen 	 * Alignment of auxiliary_name_data is an invariant as we statically assert
2878dacfa354SThu Nguyen 	 * its behaviour in the header.
2879dacfa354SThu Nguyen 	 */
2880dacfa354SThu Nguyen 	assert(!((uintptr_t)pdr->auxiliary_name_data &
2881dacfa354SThu Nguyen 		 (alignof(pldm_utf16be) - 1)));
2882dacfa354SThu Nguyen 
2883dacfa354SThu Nguyen 	/* Reject any lengths that are obviously invalid */
2884dacfa354SThu Nguyen 	if (pdr_length < data_length || pdr_length < sizeof(*pdr)) {
2885dacfa354SThu Nguyen 		return -EINVAL;
2886dacfa354SThu Nguyen 	}
2887dacfa354SThu Nguyen 
2888dacfa354SThu Nguyen 	rc = pldm_msgbuf_init_errno(
2889dacfa354SThu Nguyen 		buf, PLDM_PDR_ENTITY_AUXILIARY_NAME_PDR_MIN_LENGTH, data,
2890dacfa354SThu Nguyen 		data_length);
2891dacfa354SThu Nguyen 	if (rc) {
2892dacfa354SThu Nguyen 		return rc;
2893dacfa354SThu Nguyen 	}
2894dacfa354SThu Nguyen 
2895dacfa354SThu Nguyen 	rc = pldm_msgbuf_extract_value_pdr_hdr(buf, &pdr->hdr);
2896dacfa354SThu Nguyen 	if (rc) {
2897dacfa354SThu Nguyen 		return rc;
2898dacfa354SThu Nguyen 	}
2899dacfa354SThu Nguyen 
2900dacfa354SThu Nguyen 	rc = pldm_platform_pdr_hdr_validate(
2901dacfa354SThu Nguyen 		&pdr->hdr, PLDM_PDR_ENTITY_AUXILIARY_NAME_PDR_MIN_LENGTH,
2902dacfa354SThu Nguyen 		data_length);
2903dacfa354SThu Nguyen 	if (rc) {
2904dacfa354SThu Nguyen 		return rc;
2905dacfa354SThu Nguyen 	}
2906dacfa354SThu Nguyen 
2907dacfa354SThu Nguyen 	pldm_msgbuf_extract(buf, pdr->container.entity_type);
2908dacfa354SThu Nguyen 	pldm_msgbuf_extract(buf, pdr->container.entity_instance_num);
2909dacfa354SThu Nguyen 	pldm_msgbuf_extract(buf, pdr->container.entity_container_id);
2910dacfa354SThu Nguyen 	pldm_msgbuf_extract(buf, pdr->shared_name_count);
2911dacfa354SThu Nguyen 	rc = pldm_msgbuf_extract(buf, pdr->name_string_count);
2912dacfa354SThu Nguyen 	if (rc < 0) {
2913dacfa354SThu Nguyen 		return rc;
2914dacfa354SThu Nguyen 	}
2915dacfa354SThu Nguyen 
2916dacfa354SThu Nguyen 	rc = pldm_msgbuf_span_remaining(buf, &names, &names_len);
2917dacfa354SThu Nguyen 	if (rc < 0) {
2918dacfa354SThu Nguyen 		return rc;
2919dacfa354SThu Nguyen 	}
292090bbe6c0SAndrew Jeffery 	assert(names);
2921dacfa354SThu Nguyen 
2922dacfa354SThu Nguyen 	pdr->auxiliary_name_data_size = pdr_length - sizeof(*pdr);
2923dacfa354SThu Nguyen 
2924dacfa354SThu Nguyen 	rc = pldm_msgbuf_init_errno(dst, pdr->auxiliary_name_data_size,
2925dacfa354SThu Nguyen 				    pdr->auxiliary_name_data,
2926dacfa354SThu Nguyen 				    pdr->auxiliary_name_data_size);
2927dacfa354SThu Nguyen 	if (rc < 0) {
2928dacfa354SThu Nguyen 		return rc;
2929dacfa354SThu Nguyen 	}
2930dacfa354SThu Nguyen 
2931dacfa354SThu Nguyen 	/*
2932dacfa354SThu Nguyen 	 * Below we do two passes over the same region. This is to first pack the
2933dacfa354SThu Nguyen 	 * UTF16-BE strings into auxiliary_name_data, followed by the ASCII strings,
2934dacfa354SThu Nguyen 	 * to maintain appropriate alignment.
2935dacfa354SThu Nguyen 	 */
2936dacfa354SThu Nguyen 
2937dacfa354SThu Nguyen 	/* Initialise for the first pass to extract the UTF16-BE name strings */
2938dacfa354SThu Nguyen 	rc = pldm_msgbuf_init_errno(src, names_len, names, names_len);
2939dacfa354SThu Nguyen 	if (rc < 0) {
2940dacfa354SThu Nguyen 		return rc;
2941dacfa354SThu Nguyen 	}
2942dacfa354SThu Nguyen 
2943dacfa354SThu Nguyen 	for (i = 0; i < pdr->name_string_count; i++) {
2944dacfa354SThu Nguyen 		pldm_msgbuf_span_string_ascii(src, NULL, NULL);
29450a1be3cbSAndrew Jeffery 		rc = pldm_msgbuf_copy_string_utf16(dst, src);
29460a1be3cbSAndrew Jeffery 		if (rc) {
29470a1be3cbSAndrew Jeffery 			return rc;
29480a1be3cbSAndrew Jeffery 		}
2949dacfa354SThu Nguyen 	}
2950dacfa354SThu Nguyen 
2951dacfa354SThu Nguyen 	rc = pldm_msgbuf_destroy_consumed(src);
2952dacfa354SThu Nguyen 	if (rc < 0) {
2953dacfa354SThu Nguyen 		return rc;
2954dacfa354SThu Nguyen 	}
2955dacfa354SThu Nguyen 
2956dacfa354SThu Nguyen 	/* Reinitialise for the second pass to extract the ASCII tag strings */
2957dacfa354SThu Nguyen 	rc = pldm_msgbuf_init_errno(src, names_len, names, names_len);
2958dacfa354SThu Nguyen 	if (rc < 0) {
2959dacfa354SThu Nguyen 		return rc;
2960dacfa354SThu Nguyen 	}
2961dacfa354SThu Nguyen 
2962dacfa354SThu Nguyen 	for (i = 0; i < pdr->name_string_count; i++) {
29630a1be3cbSAndrew Jeffery 		rc = pldm_msgbuf_copy_string_ascii(dst, src);
29640a1be3cbSAndrew Jeffery 		if (rc) {
29650a1be3cbSAndrew Jeffery 			return rc;
29660a1be3cbSAndrew Jeffery 		}
2967dacfa354SThu Nguyen 		pldm_msgbuf_span_string_utf16(src, NULL, NULL);
2968dacfa354SThu Nguyen 	}
2969dacfa354SThu Nguyen 
2970dacfa354SThu Nguyen 	if ((rc = pldm_msgbuf_destroy(dst)) ||
2971dacfa354SThu Nguyen 	    (rc = pldm_msgbuf_destroy(src)) ||
2972dacfa354SThu Nguyen 	    (rc = pldm_msgbuf_destroy(buf))) {
2973dacfa354SThu Nguyen 		return rc;
2974dacfa354SThu Nguyen 	}
2975dacfa354SThu Nguyen 
2976dacfa354SThu Nguyen 	return 0;
2977dacfa354SThu Nguyen }
2978dacfa354SThu Nguyen 
297943cb4b5fSThu Nguyen LIBPLDM_ABI_STABLE
2980dacfa354SThu Nguyen int decode_pldm_entity_auxiliary_names_pdr_index(
2981dacfa354SThu Nguyen 	struct pldm_entity_auxiliary_names_pdr *pdr)
2982dacfa354SThu Nguyen {
2983dacfa354SThu Nguyen 	struct pldm_msgbuf _buf;
2984dacfa354SThu Nguyen 	struct pldm_msgbuf *buf = &_buf;
2985dacfa354SThu Nguyen 	int rc;
2986dacfa354SThu Nguyen 	int i;
2987dacfa354SThu Nguyen 
2988dacfa354SThu Nguyen 	if (!pdr) {
2989dacfa354SThu Nguyen 		return -EINVAL;
2990dacfa354SThu Nguyen 	}
2991dacfa354SThu Nguyen 
2992dacfa354SThu Nguyen 	if (pdr->name_string_count == 0 && pdr->names) {
2993dacfa354SThu Nguyen 		return -EINVAL;
2994dacfa354SThu Nguyen 	}
2995dacfa354SThu Nguyen 
2996dacfa354SThu Nguyen 	if (pdr->name_string_count > 0 && !pdr->names) {
2997dacfa354SThu Nguyen 		return -EINVAL;
2998dacfa354SThu Nguyen 	}
2999dacfa354SThu Nguyen 
3000dacfa354SThu Nguyen 	if (pdr->name_string_count == 0) {
3001dacfa354SThu Nguyen 		return 0;
3002dacfa354SThu Nguyen 	}
3003dacfa354SThu Nguyen 
3004dacfa354SThu Nguyen 	/*
3005dacfa354SThu Nguyen 	 * Minimum size is one NUL for each member of each entry
3006dacfa354SThu Nguyen 	 *
3007dacfa354SThu Nguyen 	 * Note that the definition of nameLanguageTag in DSP0248 v1.2.2
3008dacfa354SThu Nguyen 	 * states the following:
3009dacfa354SThu Nguyen 	 *
3010dacfa354SThu Nguyen 	 * > A null-terminated ISO646 ASCII string ...
3011dacfa354SThu Nguyen 	 * >
3012dacfa354SThu Nguyen 	 * > special value: null string = 0x0000 = unspecified.
3013dacfa354SThu Nguyen 	 *
3014dacfa354SThu Nguyen 	 * Until proven otherwise we will assume the "0x0000" is a
3015dacfa354SThu Nguyen 	 * misrepresentation of an ASCII NUL, and that ASCII NUL is
3016dacfa354SThu Nguyen 	 * represented by a single byte.
3017dacfa354SThu Nguyen 	 */
3018dacfa354SThu Nguyen 	rc = pldm_msgbuf_init_errno(
3019dacfa354SThu Nguyen 		buf, pdr->name_string_count * (sizeof(char) + sizeof(char16_t)),
3020dacfa354SThu Nguyen 		pdr->auxiliary_name_data, pdr->auxiliary_name_data_size);
3021dacfa354SThu Nguyen 	if (rc) {
3022dacfa354SThu Nguyen 		return rc;
3023dacfa354SThu Nguyen 	}
3024dacfa354SThu Nguyen 
3025dacfa354SThu Nguyen 	for (i = 0; i < pdr->name_string_count; i++) {
3026dacfa354SThu Nguyen 		void *loc = NULL;
3027dacfa354SThu Nguyen 		pldm_msgbuf_span_string_utf16(buf, &loc, NULL);
3028dacfa354SThu Nguyen 		pdr->names[i].name = loc;
3029dacfa354SThu Nguyen 	}
3030dacfa354SThu Nguyen 
3031dacfa354SThu Nguyen 	for (i = 0; i < pdr->name_string_count; i++) {
3032dacfa354SThu Nguyen 		void *loc = NULL;
3033dacfa354SThu Nguyen 		pldm_msgbuf_span_string_ascii(buf, &loc, NULL);
3034dacfa354SThu Nguyen 		pdr->names[i].tag = loc;
3035dacfa354SThu Nguyen 	}
3036dacfa354SThu Nguyen 
3037dacfa354SThu Nguyen 	return pldm_msgbuf_destroy_consumed(buf);
3038dacfa354SThu Nguyen }
3039a5d18dc7SThu Nguyen 
30403559aa1fSThu Nguyen LIBPLDM_ABI_STABLE
304102903038SThu Nguyen int decode_pldm_platform_cper_event(const void *event_data,
304202903038SThu Nguyen 				    size_t event_data_length,
304302903038SThu Nguyen 				    struct pldm_platform_cper_event *cper_event,
304402903038SThu Nguyen 				    size_t cper_event_length)
3045a5d18dc7SThu Nguyen {
3046a5d18dc7SThu Nguyen 	struct pldm_msgbuf _buf;
3047a5d18dc7SThu Nguyen 	struct pldm_msgbuf *buf = &_buf;
3048a5d18dc7SThu Nguyen 	int rc;
3049a5d18dc7SThu Nguyen 
3050a5d18dc7SThu Nguyen 	if (!cper_event || !event_data) {
3051a5d18dc7SThu Nguyen 		return -EINVAL;
3052a5d18dc7SThu Nguyen 	}
3053a5d18dc7SThu Nguyen 
3054a5d18dc7SThu Nguyen 	if (cper_event_length < sizeof(*cper_event)) {
3055a5d18dc7SThu Nguyen 		return -EINVAL;
3056a5d18dc7SThu Nguyen 	}
3057a5d18dc7SThu Nguyen 
3058a5d18dc7SThu Nguyen 	rc = pldm_msgbuf_init_errno(buf, PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH,
3059a5d18dc7SThu Nguyen 				    event_data, event_data_length);
3060a5d18dc7SThu Nguyen 	if (rc) {
3061a5d18dc7SThu Nguyen 		return rc;
3062a5d18dc7SThu Nguyen 	}
3063a5d18dc7SThu Nguyen 
3064a5d18dc7SThu Nguyen 	pldm_msgbuf_extract(buf, cper_event->format_version);
3065a5d18dc7SThu Nguyen 	rc = pldm_msgbuf_extract(buf, cper_event->format_type);
3066a5d18dc7SThu Nguyen 	if (rc) {
3067a5d18dc7SThu Nguyen 		return rc;
3068a5d18dc7SThu Nguyen 	}
3069a5d18dc7SThu Nguyen 	if (cper_event->format_type != PLDM_PLATFORM_CPER_EVENT_WITH_HEADER &&
3070a5d18dc7SThu Nguyen 	    cper_event->format_type !=
3071a5d18dc7SThu Nguyen 		    PLDM_PLATFORM_CPER_EVENT_WITHOUT_HEADER) {
3072a5d18dc7SThu Nguyen 		return -EPROTO;
3073a5d18dc7SThu Nguyen 	}
3074a5d18dc7SThu Nguyen 
3075a5d18dc7SThu Nguyen 	rc = pldm_msgbuf_extract(buf, cper_event->event_data_length);
3076a5d18dc7SThu Nguyen 	if (rc) {
3077a5d18dc7SThu Nguyen 		return rc;
3078a5d18dc7SThu Nguyen 	}
3079a5d18dc7SThu Nguyen 
3080a5d18dc7SThu Nguyen 	if (cper_event->event_data_length >
3081a5d18dc7SThu Nguyen 	    (cper_event_length - sizeof(*cper_event))) {
3082a5d18dc7SThu Nguyen 		return -EOVERFLOW;
3083a5d18dc7SThu Nguyen 	}
3084a5d18dc7SThu Nguyen 
30850a1be3cbSAndrew Jeffery 	rc = pldm_msgbuf_extract_array_uint8(
30860a1be3cbSAndrew Jeffery 		buf, cper_event->event_data_length, cper_event->event_data,
30870a1be3cbSAndrew Jeffery 		cper_event_length - sizeof(*cper_event));
30880a1be3cbSAndrew Jeffery 	if (rc) {
30890a1be3cbSAndrew Jeffery 		return rc;
30900a1be3cbSAndrew Jeffery 	}
3091a5d18dc7SThu Nguyen 
3092a5d18dc7SThu Nguyen 	return pldm_msgbuf_destroy_consumed(buf);
3093a5d18dc7SThu Nguyen }
3094a5d18dc7SThu Nguyen 
30953559aa1fSThu Nguyen LIBPLDM_ABI_STABLE
3096a5d18dc7SThu Nguyen uint8_t *
3097a5d18dc7SThu Nguyen pldm_platform_cper_event_event_data(struct pldm_platform_cper_event *event)
3098a5d18dc7SThu Nguyen {
3099a5d18dc7SThu Nguyen 	return event->event_data;
3100a5d18dc7SThu Nguyen }
3101