xref: /openbmc/libpldm/src/dsp/platform.c (revision 684a9ab09c9671ce6d2e94729915a4393ecd8b85)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #include "api.h"
3 #include "compiler.h"
4 #include "dsp/base.h"
5 #include "msgbuf.h"
6 #include "msgbuf/platform.h"
7 
8 #include <libpldm/base.h>
9 #include <libpldm/platform.h>
10 #include <libpldm/pldm_types.h>
11 
12 #include <endian.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <uchar.h>
17 
18 LIBPLDM_ABI_STABLE
encode_state_effecter_pdr(struct pldm_state_effecter_pdr * const effecter,const size_t allocation_size,const struct state_effecter_possible_states * const possible_states,const size_t possible_states_size,size_t * const actual_size)19 int encode_state_effecter_pdr(
20 	struct pldm_state_effecter_pdr *const effecter,
21 	const size_t allocation_size,
22 	const struct state_effecter_possible_states *const possible_states,
23 	const size_t possible_states_size, size_t *const actual_size)
24 {
25 	size_t calculated_possible_states_size = 0;
26 
27 	if (!effecter || !possible_states || !actual_size) {
28 		return PLDM_ERROR;
29 	}
30 
31 	if (SIZE_MAX - (sizeof(*effecter) - sizeof(effecter->possible_states)) <
32 	    possible_states_size) {
33 		return PLDM_ERROR;
34 	}
35 
36 	if (allocation_size <
37 	    (sizeof(*effecter) - sizeof(effecter->possible_states)) +
38 		    possible_states_size) {
39 		return PLDM_ERROR_INVALID_LENGTH;
40 	}
41 
42 	// Encode possible states
43 
44 	{
45 		char *states_ptr = (char *)possible_states;
46 		char *const begin_states_ptr = states_ptr;
47 
48 		for (int i = 0; i < effecter->composite_effecter_count; ++i) {
49 			struct state_effecter_possible_states *states =
50 				(struct state_effecter_possible_states *)
51 					states_ptr;
52 
53 			HTOLE16(states->state_set_id);
54 
55 			states_ptr +=
56 				(sizeof(*states) - sizeof(states->states) +
57 				 states->possible_states_size);
58 		}
59 
60 		calculated_possible_states_size = states_ptr - begin_states_ptr;
61 	}
62 
63 	// Check lengths
64 
65 	if (possible_states_size != calculated_possible_states_size) {
66 		*actual_size = 0;
67 		return PLDM_ERROR;
68 	}
69 
70 	*actual_size =
71 		(sizeof(struct pldm_state_effecter_pdr) + possible_states_size -
72 		 sizeof(effecter->possible_states));
73 
74 	// Encode rest of PDR
75 
76 	effecter->hdr.version = 1;
77 	effecter->hdr.type = PLDM_STATE_EFFECTER_PDR;
78 	effecter->hdr.length = *actual_size - sizeof(struct pldm_pdr_hdr);
79 
80 	memcpy(effecter->possible_states, possible_states,
81 	       possible_states_size);
82 
83 	// Convert effecter PDR body
84 	HTOLE16(effecter->terminus_handle);
85 	HTOLE16(effecter->effecter_id);
86 	HTOLE16(effecter->entity_type);
87 	HTOLE16(effecter->entity_instance);
88 	HTOLE16(effecter->container_id);
89 	HTOLE16(effecter->effecter_semantic_id);
90 
91 	// Convert header
92 	HTOLE32(effecter->hdr.record_handle);
93 	HTOLE16(effecter->hdr.record_change_num);
94 	HTOLE16(effecter->hdr.length);
95 
96 	return PLDM_SUCCESS;
97 }
98 
99 LIBPLDM_ABI_STABLE
encode_state_sensor_pdr(struct pldm_state_sensor_pdr * const sensor,const size_t allocation_size,const struct state_sensor_possible_states * const possible_states,const size_t possible_states_size,size_t * const actual_size)100 int encode_state_sensor_pdr(
101 	struct pldm_state_sensor_pdr *const sensor,
102 	const size_t allocation_size,
103 	const struct state_sensor_possible_states *const possible_states,
104 	const size_t possible_states_size, size_t *const actual_size)
105 {
106 	size_t calculated_possible_states_size = 0;
107 
108 	if (!sensor || !possible_states || !actual_size) {
109 		return PLDM_ERROR;
110 	}
111 
112 	if (SIZE_MAX - (sizeof(*sensor) - sizeof(sensor->possible_states)) <
113 	    possible_states_size) {
114 		return PLDM_ERROR;
115 	}
116 
117 	if (allocation_size <
118 	    (sizeof(*sensor) - sizeof(sensor->possible_states) +
119 	     possible_states_size)) {
120 		return PLDM_ERROR_INVALID_LENGTH;
121 	}
122 
123 	{
124 		// Encode possible states
125 		char *states_ptr = (char *)possible_states;
126 		char *const begin_states_ptr = states_ptr;
127 
128 		for (int i = 0; i < sensor->composite_sensor_count; ++i) {
129 			struct state_sensor_possible_states *states =
130 				(struct state_sensor_possible_states *)
131 					states_ptr;
132 
133 			HTOLE16(states->state_set_id);
134 
135 			states_ptr +=
136 				(sizeof(*states) - sizeof(states->states) +
137 				 states->possible_states_size);
138 		}
139 
140 		calculated_possible_states_size = states_ptr - begin_states_ptr;
141 	}
142 
143 	// Check lengths
144 
145 	if (possible_states_size != calculated_possible_states_size) {
146 		*actual_size = 0;
147 		return PLDM_ERROR;
148 	}
149 
150 	*actual_size = (sizeof(struct pldm_state_sensor_pdr) +
151 			possible_states_size - sizeof(sensor->possible_states));
152 
153 	// Encode rest of PDR
154 
155 	sensor->hdr.version = 1;
156 	sensor->hdr.type = PLDM_STATE_SENSOR_PDR;
157 	sensor->hdr.length = *actual_size - sizeof(struct pldm_pdr_hdr);
158 
159 	memcpy(sensor->possible_states, possible_states, possible_states_size);
160 
161 	// Convert sensor PDR body
162 	HTOLE16(sensor->terminus_handle);
163 	HTOLE16(sensor->sensor_id);
164 	HTOLE16(sensor->entity_type);
165 	HTOLE16(sensor->entity_instance);
166 	HTOLE16(sensor->container_id);
167 
168 	// Convert header
169 	HTOLE32(sensor->hdr.record_handle);
170 	HTOLE16(sensor->hdr.record_change_num);
171 	HTOLE16(sensor->hdr.length);
172 
173 	return PLDM_SUCCESS;
174 }
175 
176 LIBPLDM_ABI_STABLE
encode_set_state_effecter_states_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg)177 int encode_set_state_effecter_states_resp(uint8_t instance_id,
178 					  uint8_t completion_code,
179 					  struct pldm_msg *msg)
180 {
181 	if (msg == NULL) {
182 		return PLDM_ERROR_INVALID_DATA;
183 	}
184 
185 	struct pldm_header_info header = { 0 };
186 	header.msg_type = PLDM_RESPONSE;
187 	header.instance = instance_id;
188 	header.pldm_type = PLDM_PLATFORM;
189 	header.command = PLDM_SET_STATE_EFFECTER_STATES;
190 
191 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
192 	if (rc != PLDM_SUCCESS) {
193 		return rc;
194 	}
195 
196 	msg->payload[0] = completion_code;
197 
198 	return PLDM_SUCCESS;
199 }
200 
201 LIBPLDM_ABI_STABLE
encode_set_state_effecter_states_req(uint8_t instance_id,uint16_t effecter_id,uint8_t comp_effecter_count,set_effecter_state_field * field,struct pldm_msg * msg)202 int encode_set_state_effecter_states_req(uint8_t instance_id,
203 					 uint16_t effecter_id,
204 					 uint8_t comp_effecter_count,
205 					 set_effecter_state_field *field,
206 					 struct pldm_msg *msg)
207 {
208 	if (msg == NULL) {
209 		return PLDM_ERROR_INVALID_DATA;
210 	}
211 
212 	if (comp_effecter_count < 0x1 || comp_effecter_count > 0x8 ||
213 	    field == NULL) {
214 		return PLDM_ERROR_INVALID_DATA;
215 	}
216 
217 	struct pldm_header_info header = { 0 };
218 	header.msg_type = PLDM_REQUEST;
219 	header.instance = instance_id;
220 	header.pldm_type = PLDM_PLATFORM;
221 	header.command = PLDM_SET_STATE_EFFECTER_STATES;
222 
223 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
224 	if (rc != PLDM_SUCCESS) {
225 		return rc;
226 	}
227 
228 	struct pldm_set_state_effecter_states_req *request =
229 		(struct pldm_set_state_effecter_states_req *)msg->payload;
230 	effecter_id = htole16(effecter_id);
231 	request->effecter_id = effecter_id;
232 	request->comp_effecter_count = comp_effecter_count;
233 	memcpy(request->field, field,
234 	       (sizeof(set_effecter_state_field) * comp_effecter_count));
235 
236 	return PLDM_SUCCESS;
237 }
238 
239 LIBPLDM_ABI_STABLE
decode_set_state_effecter_states_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)240 int decode_set_state_effecter_states_resp(const struct pldm_msg *msg,
241 					  size_t payload_length,
242 					  uint8_t *completion_code)
243 {
244 	if (msg == NULL || completion_code == NULL) {
245 		return PLDM_ERROR_INVALID_DATA;
246 	}
247 
248 	*completion_code = msg->payload[0];
249 	if (PLDM_SUCCESS != *completion_code) {
250 		return PLDM_SUCCESS;
251 	}
252 
253 	if (payload_length > PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES) {
254 		return PLDM_ERROR_INVALID_LENGTH;
255 	}
256 
257 	return PLDM_SUCCESS;
258 }
259 
260 #define PLDM_SET_STATE_EFFECTER_STATES_MIN_SIZE 3
261 LIBPLDM_ABI_STABLE
decode_set_state_effecter_states_req(const struct pldm_msg * msg,size_t payload_length,uint16_t * effecter_id,uint8_t * comp_effecter_count,set_effecter_state_field * field)262 int decode_set_state_effecter_states_req(const struct pldm_msg *msg,
263 					 size_t payload_length,
264 					 uint16_t *effecter_id,
265 					 uint8_t *comp_effecter_count,
266 					 set_effecter_state_field *field)
267 {
268 	PLDM_MSGBUF_DEFINE_P(buf);
269 	int rc;
270 	int i;
271 
272 	if (msg == NULL || effecter_id == NULL || comp_effecter_count == NULL ||
273 	    field == NULL) {
274 		return PLDM_ERROR_INVALID_DATA;
275 	}
276 
277 	if (payload_length > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) {
278 		return PLDM_ERROR_INVALID_LENGTH;
279 	}
280 
281 	rc = pldm_msgbuf_init_errno(buf,
282 				    PLDM_SET_STATE_EFFECTER_STATES_MIN_SIZE,
283 				    msg->payload, payload_length);
284 	if (rc) {
285 		return pldm_xlate_errno(rc);
286 	}
287 
288 	pldm_msgbuf_extract_p(buf, effecter_id);
289 	rc = pldm_msgbuf_extract_p(buf, comp_effecter_count);
290 	if (rc) {
291 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
292 	}
293 
294 	if (*comp_effecter_count > 8) {
295 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
296 	}
297 
298 	for (i = 0; i < *comp_effecter_count; i++) {
299 		pldm_msgbuf_extract(buf, field[i].set_request);
300 		pldm_msgbuf_extract(buf, field[i].effecter_state);
301 	}
302 
303 	rc = pldm_msgbuf_complete(buf);
304 	if (rc) {
305 		return pldm_xlate_errno(rc);
306 	}
307 
308 	return PLDM_SUCCESS;
309 }
310 
311 LIBPLDM_ABI_STABLE
decode_get_pdr_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * record_hndl,uint32_t * data_transfer_hndl,uint8_t * transfer_op_flag,uint16_t * request_cnt,uint16_t * record_chg_num)312 int decode_get_pdr_req(const struct pldm_msg *msg, size_t payload_length,
313 		       uint32_t *record_hndl, uint32_t *data_transfer_hndl,
314 		       uint8_t *transfer_op_flag, uint16_t *request_cnt,
315 		       uint16_t *record_chg_num)
316 {
317 	PLDM_MSGBUF_DEFINE_P(buf);
318 	int rc;
319 
320 	if (msg == NULL || record_hndl == NULL || data_transfer_hndl == NULL ||
321 	    transfer_op_flag == NULL || request_cnt == NULL ||
322 	    record_chg_num == NULL) {
323 		return PLDM_ERROR_INVALID_DATA;
324 	}
325 
326 	if (payload_length != PLDM_GET_PDR_REQ_BYTES) {
327 		return PLDM_ERROR_INVALID_LENGTH;
328 	}
329 
330 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_PDR_REQ_BYTES, msg->payload,
331 				    payload_length);
332 	if (rc) {
333 		return pldm_xlate_errno(rc);
334 	}
335 
336 	pldm_msgbuf_extract_p(buf, record_hndl);
337 	pldm_msgbuf_extract_p(buf, data_transfer_hndl);
338 	pldm_msgbuf_extract_p(buf, transfer_op_flag);
339 	pldm_msgbuf_extract_p(buf, request_cnt);
340 	pldm_msgbuf_extract_p(buf, record_chg_num);
341 
342 	rc = pldm_msgbuf_complete(buf);
343 	if (rc) {
344 		return pldm_xlate_errno(rc);
345 	}
346 
347 	return PLDM_SUCCESS;
348 }
349 
350 LIBPLDM_ABI_DEPRECATED_UNSAFE
encode_get_pdr_resp(uint8_t instance_id,uint8_t completion_code,uint32_t next_record_hndl,uint32_t next_data_transfer_hndl,uint8_t transfer_flag,uint16_t resp_cnt,const uint8_t * record_data,uint8_t transfer_crc,struct pldm_msg * msg)351 int encode_get_pdr_resp(uint8_t instance_id, uint8_t completion_code,
352 			uint32_t next_record_hndl,
353 			uint32_t next_data_transfer_hndl, uint8_t transfer_flag,
354 			uint16_t resp_cnt, const uint8_t *record_data,
355 			uint8_t transfer_crc, struct pldm_msg *msg)
356 {
357 	if (msg == NULL) {
358 		return PLDM_ERROR_INVALID_DATA;
359 	}
360 
361 	struct pldm_header_info header = { 0 };
362 	header.msg_type = PLDM_RESPONSE;
363 	header.instance = instance_id;
364 	header.pldm_type = PLDM_PLATFORM;
365 	header.command = PLDM_GET_PDR;
366 
367 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
368 	if (rc != PLDM_SUCCESS) {
369 		return rc;
370 	}
371 
372 	struct pldm_get_pdr_resp *response =
373 		(struct pldm_get_pdr_resp *)msg->payload;
374 	response->completion_code = completion_code;
375 
376 	if (response->completion_code == PLDM_SUCCESS) {
377 		response->next_record_handle = htole32(next_record_hndl);
378 		response->next_data_transfer_handle =
379 			htole32(next_data_transfer_hndl);
380 		response->transfer_flag = transfer_flag;
381 		response->response_count = htole16(resp_cnt);
382 		if (record_data != NULL && resp_cnt > 0) {
383 			memcpy(response->record_data, record_data, resp_cnt);
384 		}
385 		if (transfer_flag == PLDM_END) {
386 			uint8_t *dst = msg->payload;
387 			dst += (sizeof(struct pldm_get_pdr_resp) - 1) +
388 			       resp_cnt;
389 			*dst = transfer_crc;
390 		}
391 	}
392 
393 	return PLDM_SUCCESS;
394 }
395 
396 LIBPLDM_ABI_TESTING
encode_get_pdr_repository_info_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length LIBPLDM_CC_UNUSED)397 int encode_get_pdr_repository_info_req(uint8_t instance_id,
398 				       struct pldm_msg *msg,
399 				       size_t payload_length LIBPLDM_CC_UNUSED)
400 {
401 	if (!msg) {
402 		return -EINVAL;
403 	}
404 
405 	struct pldm_header_info header = { 0 };
406 	header.msg_type = PLDM_REQUEST;
407 	header.instance = instance_id;
408 	header.pldm_type = PLDM_PLATFORM;
409 	header.command = PLDM_GET_PDR_REPOSITORY_INFO;
410 
411 	return pack_pldm_header_errno(&header, &(msg->hdr));
412 }
413 
414 LIBPLDM_ABI_STABLE
encode_get_pdr_repository_info_resp(uint8_t instance_id,uint8_t completion_code,uint8_t repository_state,const uint8_t * update_time,const uint8_t * oem_update_time,uint32_t record_count,uint32_t repository_size,uint32_t largest_record_size,uint8_t data_transfer_handle_timeout,struct pldm_msg * msg)415 int encode_get_pdr_repository_info_resp(
416 	uint8_t instance_id, uint8_t completion_code, uint8_t repository_state,
417 	const uint8_t *update_time, const uint8_t *oem_update_time,
418 	uint32_t record_count, uint32_t repository_size,
419 	uint32_t largest_record_size, uint8_t data_transfer_handle_timeout,
420 	struct pldm_msg *msg)
421 {
422 	if (msg == NULL) {
423 		return PLDM_ERROR_INVALID_DATA;
424 	}
425 
426 	struct pldm_header_info header = { 0 };
427 	header.msg_type = PLDM_RESPONSE;
428 	header.instance = instance_id;
429 	header.pldm_type = PLDM_PLATFORM;
430 	header.command = PLDM_GET_PDR_REPOSITORY_INFO;
431 
432 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
433 	if (rc != PLDM_SUCCESS) {
434 		return rc;
435 	}
436 
437 	struct pldm_pdr_repository_info_resp *response =
438 		(struct pldm_pdr_repository_info_resp *)msg->payload;
439 	response->completion_code = completion_code;
440 
441 	if (response->completion_code == PLDM_SUCCESS) {
442 		response->repository_state = repository_state;
443 		if (update_time != NULL) {
444 			memcpy(response->update_time, update_time,
445 			       PLDM_TIMESTAMP104_SIZE);
446 		}
447 		if (oem_update_time != NULL) {
448 			memcpy(response->oem_update_time, oem_update_time,
449 			       PLDM_TIMESTAMP104_SIZE);
450 		}
451 		response->record_count = htole32(record_count);
452 		response->repository_size = htole32(repository_size);
453 		response->largest_record_size = htole32(largest_record_size);
454 		response->data_transfer_handle_timeout =
455 			data_transfer_handle_timeout;
456 	}
457 
458 	return PLDM_SUCCESS;
459 }
460 
461 LIBPLDM_ABI_DEPRECATED
decode_get_pdr_repository_info_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * repository_state,uint8_t * update_time,uint8_t * oem_update_time,uint32_t * record_count,uint32_t * repository_size,uint32_t * largest_record_size,uint8_t * data_transfer_handle_timeout)462 int decode_get_pdr_repository_info_resp(
463 	const struct pldm_msg *msg, size_t payload_length,
464 	uint8_t *completion_code, uint8_t *repository_state,
465 	uint8_t *update_time, uint8_t *oem_update_time, uint32_t *record_count,
466 	uint32_t *repository_size, uint32_t *largest_record_size,
467 	uint8_t *data_transfer_handle_timeout)
468 {
469 	PLDM_MSGBUF_DEFINE_P(buf);
470 	int rc;
471 
472 	if (msg == NULL || completion_code == NULL ||
473 	    repository_state == NULL || update_time == NULL ||
474 	    oem_update_time == NULL || record_count == NULL ||
475 	    repository_size == NULL || largest_record_size == NULL ||
476 	    data_transfer_handle_timeout == NULL) {
477 		return PLDM_ERROR_INVALID_DATA;
478 	}
479 
480 	rc = pldm_msgbuf_init_errno(buf,
481 				    PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES,
482 				    msg->payload, payload_length);
483 	if (rc) {
484 		return pldm_xlate_errno(rc);
485 	}
486 
487 	rc = pldm_msgbuf_extract_p(buf, completion_code);
488 	if (rc) {
489 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
490 	}
491 	if (PLDM_SUCCESS != *completion_code) {
492 		return PLDM_SUCCESS;
493 	}
494 
495 	rc = pldm_msgbuf_extract_p(buf, repository_state);
496 	if (rc) {
497 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
498 	}
499 
500 	if (*repository_state > PLDM_FAILED) {
501 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
502 	}
503 
504 	/* NOTE: Memory safety */
505 	rc = pldm_msgbuf_extract_array(buf, PLDM_TIMESTAMP104_SIZE, update_time,
506 				       PLDM_TIMESTAMP104_SIZE);
507 	if (rc) {
508 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
509 	}
510 
511 	/* NOTE: Memory safety */
512 	rc = pldm_msgbuf_extract_array(buf, PLDM_TIMESTAMP104_SIZE,
513 				       oem_update_time, PLDM_TIMESTAMP104_SIZE);
514 	if (rc) {
515 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
516 	}
517 
518 	pldm_msgbuf_extract_p(buf, record_count);
519 	pldm_msgbuf_extract_p(buf, repository_size);
520 	pldm_msgbuf_extract_p(buf, largest_record_size);
521 	pldm_msgbuf_extract_p(buf, data_transfer_handle_timeout);
522 
523 	rc = pldm_msgbuf_complete(buf);
524 	if (rc) {
525 		return pldm_xlate_errno(rc);
526 	}
527 
528 	return PLDM_SUCCESS;
529 }
530 
531 LIBPLDM_ABI_TESTING
decode_get_pdr_repository_info_resp_safe(const struct pldm_msg * msg,size_t payload_length,struct pldm_pdr_repository_info_resp * resp)532 int decode_get_pdr_repository_info_resp_safe(
533 	const struct pldm_msg *msg, size_t payload_length,
534 	struct pldm_pdr_repository_info_resp *resp)
535 {
536 	PLDM_MSGBUF_DEFINE_P(buf);
537 	int rc;
538 
539 	if (msg == NULL || resp == NULL) {
540 		return -EINVAL;
541 	}
542 
543 	rc = pldm_msg_has_error(msg, payload_length);
544 	if (rc) {
545 		resp->completion_code = rc;
546 		return 0;
547 	}
548 
549 	rc = pldm_msgbuf_init_errno(buf,
550 				    PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES,
551 				    msg->payload, payload_length);
552 	if (rc) {
553 		return rc;
554 	}
555 
556 	rc = pldm_msgbuf_extract(buf, resp->completion_code);
557 	if (rc) {
558 		return pldm_msgbuf_discard(buf, rc);
559 	}
560 
561 	pldm_msgbuf_extract(buf, resp->repository_state);
562 
563 	rc = pldm_msgbuf_extract_array(buf, sizeof(resp->update_time),
564 				       resp->update_time,
565 				       sizeof(resp->update_time));
566 	if (rc) {
567 		return pldm_msgbuf_discard(buf, rc);
568 	}
569 
570 	rc = pldm_msgbuf_extract_array(buf, sizeof(resp->oem_update_time),
571 				       resp->oem_update_time,
572 				       sizeof(resp->oem_update_time));
573 	if (rc) {
574 		return pldm_msgbuf_discard(buf, rc);
575 	}
576 
577 	pldm_msgbuf_extract(buf, resp->record_count);
578 	pldm_msgbuf_extract(buf, resp->repository_size);
579 	pldm_msgbuf_extract(buf, resp->largest_record_size);
580 	pldm_msgbuf_extract(buf, resp->data_transfer_handle_timeout);
581 
582 	return pldm_msgbuf_complete_consumed(buf);
583 }
584 
585 LIBPLDM_ABI_STABLE
encode_get_pdr_req(uint8_t instance_id,uint32_t record_hndl,uint32_t data_transfer_hndl,uint8_t transfer_op_flag,uint16_t request_cnt,uint16_t record_chg_num,struct pldm_msg * msg,size_t payload_length)586 int encode_get_pdr_req(uint8_t instance_id, uint32_t record_hndl,
587 		       uint32_t data_transfer_hndl, uint8_t transfer_op_flag,
588 		       uint16_t request_cnt, uint16_t record_chg_num,
589 		       struct pldm_msg *msg, size_t payload_length)
590 {
591 	if (msg == NULL) {
592 		return PLDM_ERROR_INVALID_DATA;
593 	}
594 
595 	if (payload_length != PLDM_GET_PDR_REQ_BYTES) {
596 		return PLDM_ERROR_INVALID_LENGTH;
597 	}
598 
599 	struct pldm_header_info header = { 0 };
600 	header.msg_type = PLDM_REQUEST;
601 	header.instance = instance_id;
602 	header.pldm_type = PLDM_PLATFORM;
603 	header.command = PLDM_GET_PDR;
604 
605 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
606 	if (rc != PLDM_SUCCESS) {
607 		return rc;
608 	}
609 
610 	struct pldm_get_pdr_req *request =
611 		(struct pldm_get_pdr_req *)msg->payload;
612 	request->record_handle = htole32(record_hndl);
613 	request->data_transfer_handle = htole32(data_transfer_hndl);
614 	request->transfer_op_flag = transfer_op_flag;
615 	request->request_count = htole16(request_cnt);
616 	request->record_change_number = htole16(record_chg_num);
617 
618 	return PLDM_SUCCESS;
619 }
620 
621 LIBPLDM_ABI_DEPRECATED
decode_get_pdr_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * next_record_hndl,uint32_t * next_data_transfer_hndl,uint8_t * transfer_flag,uint16_t * resp_cnt,uint8_t * record_data,size_t record_data_length,uint8_t * transfer_crc)622 int decode_get_pdr_resp(const struct pldm_msg *msg, size_t payload_length,
623 			uint8_t *completion_code, uint32_t *next_record_hndl,
624 			uint32_t *next_data_transfer_hndl,
625 			uint8_t *transfer_flag, uint16_t *resp_cnt,
626 			uint8_t *record_data, size_t record_data_length,
627 			uint8_t *transfer_crc)
628 {
629 	PLDM_MSGBUF_DEFINE_P(buf);
630 	int rc;
631 
632 	if (msg == NULL || completion_code == NULL ||
633 	    next_record_hndl == NULL || next_data_transfer_hndl == NULL ||
634 	    transfer_flag == NULL || resp_cnt == NULL || transfer_crc == NULL) {
635 		return PLDM_ERROR_INVALID_DATA;
636 	}
637 
638 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_PDR_MIN_RESP_BYTES,
639 				    msg->payload, payload_length);
640 	if (rc) {
641 		return pldm_xlate_errno(rc);
642 	}
643 
644 	rc = pldm_msgbuf_extract_p(buf, completion_code);
645 	if (rc) {
646 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
647 	}
648 
649 	if (PLDM_SUCCESS != *completion_code) {
650 		return pldm_msgbuf_complete(buf);
651 	}
652 
653 	pldm_msgbuf_extract_p(buf, next_record_hndl);
654 	pldm_msgbuf_extract_p(buf, next_data_transfer_hndl);
655 	pldm_msgbuf_extract_p(buf, transfer_flag);
656 	rc = pldm_msgbuf_extract_p(buf, resp_cnt);
657 	if (rc) {
658 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
659 	}
660 
661 	if (*resp_cnt > 0 && record_data != NULL) {
662 		if (record_data_length < *resp_cnt) {
663 			return pldm_msgbuf_discard(buf,
664 						   PLDM_ERROR_INVALID_LENGTH);
665 		}
666 		/* NOTE: Memory safety */
667 		rc = pldm_msgbuf_extract_array(buf, *resp_cnt, record_data,
668 					       *resp_cnt);
669 		if (rc) {
670 			return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
671 		}
672 	}
673 
674 	if (*transfer_flag == PLDM_END) {
675 		pldm_msgbuf_extract_p(buf, transfer_crc);
676 	}
677 
678 	rc = pldm_msgbuf_complete(buf);
679 	if (rc) {
680 		return pldm_xlate_errno(rc);
681 	}
682 
683 	return PLDM_SUCCESS;
684 }
685 
686 LIBPLDM_ABI_TESTING
decode_get_pdr_resp_safe(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_pdr_resp * resp,size_t resp_len,uint8_t * transfer_crc)687 int decode_get_pdr_resp_safe(const struct pldm_msg *msg, size_t payload_length,
688 			     struct pldm_get_pdr_resp *resp, size_t resp_len,
689 			     uint8_t *transfer_crc)
690 {
691 	PLDM_MSGBUF_DEFINE_P(buf);
692 	int rc;
693 
694 	if (msg == NULL || resp == NULL || transfer_crc == NULL) {
695 		return -EINVAL;
696 	}
697 
698 	rc = pldm_msg_has_error(msg, payload_length);
699 	if (rc) {
700 		resp->completion_code = rc;
701 		return 0;
702 	}
703 
704 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_PDR_MIN_RESP_BYTES,
705 				    msg->payload, payload_length);
706 	if (rc) {
707 		return rc;
708 	}
709 
710 	pldm_msgbuf_extract(buf, resp->completion_code);
711 	pldm_msgbuf_extract(buf, resp->next_record_handle);
712 	pldm_msgbuf_extract(buf, resp->next_data_transfer_handle);
713 
714 	rc = pldm_msgbuf_extract(buf, resp->transfer_flag);
715 	if (rc) {
716 		return pldm_msgbuf_discard(buf, rc);
717 	}
718 
719 	rc = pldm_msgbuf_extract(buf, resp->response_count);
720 	if (rc) {
721 		return pldm_msgbuf_discard(buf, rc);
722 	}
723 
724 	rc = pldm_msgbuf_extract_array(
725 		buf, resp->response_count, resp->record_data,
726 		resp_len - (sizeof(*resp) - sizeof(resp->record_data)));
727 	if (rc) {
728 		return pldm_msgbuf_discard(buf, rc);
729 	}
730 
731 	if (resp->transfer_flag == PLDM_END) {
732 		pldm_msgbuf_extract_p(buf, transfer_crc);
733 	}
734 
735 	return pldm_msgbuf_complete_consumed(buf);
736 }
737 
738 LIBPLDM_ABI_STABLE
decode_set_numeric_effecter_value_req(const struct pldm_msg * msg,size_t payload_length,uint16_t * effecter_id,uint8_t * effecter_data_size,uint8_t effecter_value[4])739 int decode_set_numeric_effecter_value_req(const struct pldm_msg *msg,
740 					  size_t payload_length,
741 					  uint16_t *effecter_id,
742 					  uint8_t *effecter_data_size,
743 					  uint8_t effecter_value[4])
744 {
745 	PLDM_MSGBUF_DEFINE_P(buf);
746 	int rc;
747 
748 	if (msg == NULL || effecter_id == NULL || effecter_data_size == NULL ||
749 	    effecter_value == NULL) {
750 		return PLDM_ERROR_INVALID_DATA;
751 	}
752 
753 	rc = pldm_msgbuf_init_errno(
754 		buf, PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES,
755 		msg->payload, payload_length);
756 	if (rc) {
757 		return pldm_xlate_errno(rc);
758 	}
759 
760 	pldm_msgbuf_extract_p(buf, effecter_id);
761 	rc = pldm_msgbuf_extract_p(buf, effecter_data_size);
762 	if (rc) {
763 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
764 	}
765 
766 	if (*effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
767 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
768 	}
769 
770 	pldm_msgbuf_extract_effecter_value(buf, *effecter_data_size,
771 					   effecter_value);
772 
773 	rc = pldm_msgbuf_complete(buf);
774 	if (rc) {
775 		return pldm_xlate_errno(rc);
776 	}
777 
778 	return PLDM_SUCCESS;
779 }
780 
781 LIBPLDM_ABI_STABLE
encode_set_numeric_effecter_value_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)782 int encode_set_numeric_effecter_value_resp(uint8_t instance_id,
783 					   uint8_t completion_code,
784 					   struct pldm_msg *msg,
785 					   size_t payload_length)
786 {
787 	if (msg == NULL) {
788 		return PLDM_ERROR_INVALID_DATA;
789 	}
790 
791 	if (payload_length != PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES) {
792 		return PLDM_ERROR_INVALID_LENGTH;
793 	}
794 
795 	struct pldm_header_info header = { 0 };
796 	header.msg_type = PLDM_RESPONSE;
797 	header.instance = instance_id;
798 	header.pldm_type = PLDM_PLATFORM;
799 	header.command = PLDM_SET_NUMERIC_EFFECTER_VALUE;
800 
801 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
802 	if (rc != PLDM_SUCCESS) {
803 		return rc;
804 	}
805 
806 	msg->payload[0] = completion_code;
807 
808 	return rc;
809 }
810 
811 LIBPLDM_ABI_STABLE
encode_set_numeric_effecter_value_req(uint8_t instance_id,uint16_t effecter_id,uint8_t effecter_data_size,const uint8_t * effecter_value,struct pldm_msg * msg,size_t payload_length)812 int encode_set_numeric_effecter_value_req(uint8_t instance_id,
813 					  uint16_t effecter_id,
814 					  uint8_t effecter_data_size,
815 					  const uint8_t *effecter_value,
816 					  struct pldm_msg *msg,
817 					  size_t payload_length)
818 {
819 	if (msg == NULL || effecter_value == NULL) {
820 		return PLDM_ERROR_INVALID_DATA;
821 	}
822 
823 	if (effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
824 		return PLDM_ERROR_INVALID_DATA;
825 	}
826 
827 	struct pldm_header_info header = { 0 };
828 	header.msg_type = PLDM_REQUEST;
829 	header.instance = instance_id;
830 	header.pldm_type = PLDM_PLATFORM;
831 	header.command = PLDM_SET_NUMERIC_EFFECTER_VALUE;
832 
833 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
834 	if (rc != PLDM_SUCCESS) {
835 		return rc;
836 	}
837 
838 	struct pldm_set_numeric_effecter_value_req *request =
839 		(struct pldm_set_numeric_effecter_value_req *)msg->payload;
840 	if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
841 	    effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
842 		if (payload_length !=
843 		    PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES) {
844 			return PLDM_ERROR_INVALID_LENGTH;
845 		}
846 		request->effecter_value[0] = *effecter_value;
847 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
848 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
849 		if (payload_length !=
850 		    PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1) {
851 			return PLDM_ERROR_INVALID_LENGTH;
852 		}
853 
854 		uint16_t val = *(uint16_t *)(effecter_value);
855 		val = htole16(val);
856 		memcpy(request->effecter_value, &val, sizeof(uint16_t));
857 
858 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
859 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
860 		if (payload_length !=
861 		    PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3) {
862 			return PLDM_ERROR_INVALID_LENGTH;
863 		}
864 
865 		uint32_t val = *(uint32_t *)(effecter_value);
866 		val = htole32(val);
867 		memcpy(request->effecter_value, &val, sizeof(uint32_t));
868 	}
869 
870 	request->effecter_id = htole16(effecter_id);
871 	request->effecter_data_size = effecter_data_size;
872 
873 	return PLDM_SUCCESS;
874 }
875 
876 LIBPLDM_ABI_STABLE
decode_set_numeric_effecter_value_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)877 int decode_set_numeric_effecter_value_resp(const struct pldm_msg *msg,
878 					   size_t payload_length,
879 					   uint8_t *completion_code)
880 {
881 	if (msg == NULL || completion_code == NULL) {
882 		return PLDM_ERROR_INVALID_DATA;
883 	}
884 
885 	if (payload_length != PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES) {
886 		return PLDM_ERROR_INVALID_LENGTH;
887 	}
888 
889 	*completion_code = msg->payload[0];
890 
891 	return PLDM_SUCCESS;
892 }
893 
894 LIBPLDM_ABI_STABLE
encode_get_state_sensor_readings_resp(uint8_t instance_id,uint8_t completion_code,uint8_t comp_sensor_count,get_sensor_state_field * field,struct pldm_msg * msg)895 int encode_get_state_sensor_readings_resp(uint8_t instance_id,
896 					  uint8_t completion_code,
897 					  uint8_t comp_sensor_count,
898 					  get_sensor_state_field *field,
899 					  struct pldm_msg *msg)
900 {
901 	if (msg == NULL) {
902 		return PLDM_ERROR_INVALID_DATA;
903 	}
904 
905 	if (comp_sensor_count < 0x1 || comp_sensor_count > 0x8) {
906 		return PLDM_ERROR_INVALID_DATA;
907 	}
908 
909 	struct pldm_header_info header = { 0 };
910 	header.msg_type = PLDM_RESPONSE;
911 	header.instance = instance_id;
912 	header.pldm_type = PLDM_PLATFORM;
913 	header.command = PLDM_GET_STATE_SENSOR_READINGS;
914 
915 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
916 	if (rc != PLDM_SUCCESS) {
917 		return rc;
918 	}
919 
920 	struct pldm_get_state_sensor_readings_resp *response =
921 		(struct pldm_get_state_sensor_readings_resp *)msg->payload;
922 
923 	response->completion_code = completion_code;
924 	response->comp_sensor_count = comp_sensor_count;
925 	memcpy(response->field, field,
926 	       (sizeof(get_sensor_state_field) * comp_sensor_count));
927 
928 	return PLDM_SUCCESS;
929 }
930 
931 LIBPLDM_ABI_STABLE
encode_get_state_sensor_readings_req(uint8_t instance_id,uint16_t sensor_id,bitfield8_t sensor_rearm,uint8_t reserved,struct pldm_msg * msg)932 int encode_get_state_sensor_readings_req(uint8_t instance_id,
933 					 uint16_t sensor_id,
934 					 bitfield8_t sensor_rearm,
935 					 uint8_t reserved, struct pldm_msg *msg)
936 {
937 	if (msg == NULL) {
938 		return PLDM_ERROR_INVALID_DATA;
939 	}
940 
941 	struct pldm_header_info header = { 0 };
942 	header.msg_type = PLDM_REQUEST;
943 	header.instance = instance_id;
944 	header.pldm_type = PLDM_PLATFORM;
945 	header.command = PLDM_GET_STATE_SENSOR_READINGS;
946 
947 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
948 	if (rc != PLDM_SUCCESS) {
949 		return rc;
950 	}
951 
952 	struct pldm_get_state_sensor_readings_req *request =
953 		(struct pldm_get_state_sensor_readings_req *)msg->payload;
954 
955 	request->sensor_id = htole16(sensor_id);
956 	request->reserved = reserved;
957 	request->sensor_rearm = sensor_rearm;
958 
959 	return PLDM_SUCCESS;
960 }
961 
962 LIBPLDM_ABI_STABLE
decode_get_state_sensor_readings_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * comp_sensor_count,get_sensor_state_field * field)963 int decode_get_state_sensor_readings_resp(const struct pldm_msg *msg,
964 					  size_t payload_length,
965 					  uint8_t *completion_code,
966 					  uint8_t *comp_sensor_count,
967 					  get_sensor_state_field *field)
968 {
969 	PLDM_MSGBUF_DEFINE_P(buf);
970 	uint8_t i;
971 	int rc;
972 
973 	if (msg == NULL || completion_code == NULL ||
974 	    comp_sensor_count == NULL || field == NULL) {
975 		return PLDM_ERROR_INVALID_DATA;
976 	}
977 
978 	rc = pldm_msgbuf_init_errno(
979 		buf, PLDM_GET_STATE_SENSOR_READINGS_MIN_RESP_BYTES,
980 		msg->payload, payload_length);
981 	if (rc) {
982 		return pldm_xlate_errno(rc);
983 	}
984 
985 	rc = pldm_msgbuf_extract_p(buf, completion_code);
986 	if (rc) {
987 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
988 	}
989 
990 	if (PLDM_SUCCESS != *completion_code) {
991 		return pldm_msgbuf_discard(buf, PLDM_SUCCESS);
992 	}
993 
994 	rc = pldm_msgbuf_extract_p(buf, comp_sensor_count);
995 	if (rc) {
996 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
997 	}
998 
999 	if (*comp_sensor_count < 0x1 || *comp_sensor_count > 0x8) {
1000 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1001 	}
1002 
1003 	for (i = 0; i < *comp_sensor_count; i++) {
1004 		pldm_msgbuf_extract(buf, field[i].sensor_op_state);
1005 		pldm_msgbuf_extract(buf, field[i].present_state);
1006 		pldm_msgbuf_extract(buf, field[i].previous_state);
1007 		pldm_msgbuf_extract(buf, field[i].event_state);
1008 	}
1009 
1010 	rc = pldm_msgbuf_complete_consumed(buf);
1011 	if (rc) {
1012 		return pldm_xlate_errno(rc);
1013 	}
1014 
1015 	return PLDM_SUCCESS;
1016 }
1017 
1018 LIBPLDM_ABI_STABLE
decode_get_state_sensor_readings_req(const struct pldm_msg * msg,size_t payload_length,uint16_t * sensor_id,bitfield8_t * sensor_rearm,uint8_t * reserved)1019 int decode_get_state_sensor_readings_req(const struct pldm_msg *msg,
1020 					 size_t payload_length,
1021 					 uint16_t *sensor_id,
1022 					 bitfield8_t *sensor_rearm,
1023 					 uint8_t *reserved)
1024 {
1025 	PLDM_MSGBUF_DEFINE_P(buf);
1026 	int rc;
1027 
1028 	if (msg == NULL || sensor_id == NULL || sensor_rearm == NULL) {
1029 		return PLDM_ERROR_INVALID_DATA;
1030 	}
1031 
1032 	rc = pldm_msgbuf_init_errno(buf,
1033 				    PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES,
1034 				    msg->payload, payload_length);
1035 	if (rc) {
1036 		return pldm_xlate_errno(rc);
1037 	}
1038 
1039 	pldm_msgbuf_extract_p(buf, sensor_id);
1040 	pldm_msgbuf_extract(buf, sensor_rearm->byte);
1041 	pldm_msgbuf_extract_p(buf, reserved);
1042 
1043 	rc = pldm_msgbuf_complete(buf);
1044 	if (rc) {
1045 		return pldm_xlate_errno(rc);
1046 	}
1047 
1048 	return PLDM_SUCCESS;
1049 }
1050 
1051 LIBPLDM_ABI_STABLE
encode_sensor_event_data(struct pldm_sensor_event_data * const event_data,const size_t event_data_size,const uint16_t sensor_id,const enum sensor_event_class_states sensor_event_class,const uint8_t sensor_offset,const uint8_t event_state,const uint8_t previous_event_state,size_t * const actual_event_data_size)1052 int encode_sensor_event_data(
1053 	struct pldm_sensor_event_data *const event_data,
1054 	const size_t event_data_size, const uint16_t sensor_id,
1055 	const enum sensor_event_class_states sensor_event_class,
1056 	const uint8_t sensor_offset, const uint8_t event_state,
1057 	const uint8_t previous_event_state,
1058 	size_t *const actual_event_data_size)
1059 {
1060 	*actual_event_data_size =
1061 		(sizeof(*event_data) - sizeof(event_data->event_class) +
1062 		 sizeof(struct pldm_sensor_event_state_sensor_state));
1063 
1064 	if (!event_data) {
1065 		return PLDM_SUCCESS;
1066 	}
1067 
1068 	if (event_data_size < *actual_event_data_size) {
1069 		*actual_event_data_size = 0;
1070 		return PLDM_ERROR_INVALID_LENGTH;
1071 	}
1072 
1073 	event_data->sensor_id = htole16(sensor_id);
1074 	event_data->sensor_event_class_type = sensor_event_class;
1075 
1076 	struct pldm_sensor_event_state_sensor_state *const state_data =
1077 		(struct pldm_sensor_event_state_sensor_state *)
1078 			event_data->event_class;
1079 
1080 	state_data->sensor_offset = sensor_offset;
1081 	state_data->event_state = event_state;
1082 	state_data->previous_event_state = previous_event_state;
1083 
1084 	return PLDM_SUCCESS;
1085 }
1086 
1087 LIBPLDM_ABI_STABLE
decode_platform_event_message_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * format_version,uint8_t * tid,uint8_t * event_class,size_t * event_data_offset)1088 int decode_platform_event_message_req(const struct pldm_msg *msg,
1089 				      size_t payload_length,
1090 				      uint8_t *format_version, uint8_t *tid,
1091 				      uint8_t *event_class,
1092 				      size_t *event_data_offset)
1093 {
1094 	PLDM_MSGBUF_DEFINE_P(buf);
1095 	int rc;
1096 
1097 	if (msg == NULL || format_version == NULL || tid == NULL ||
1098 	    event_class == NULL || event_data_offset == NULL) {
1099 		return PLDM_ERROR_INVALID_DATA;
1100 	}
1101 
1102 	rc = pldm_msgbuf_init_errno(buf,
1103 				    PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES,
1104 				    msg->payload, payload_length);
1105 	if (rc) {
1106 		return pldm_xlate_errno(rc);
1107 	}
1108 
1109 	pldm_msgbuf_extract_p(buf, format_version);
1110 	pldm_msgbuf_extract_p(buf, tid);
1111 	pldm_msgbuf_extract_p(buf, event_class);
1112 
1113 	rc = pldm_msgbuf_complete(buf);
1114 	if (rc) {
1115 		return pldm_xlate_errno(rc);
1116 	}
1117 
1118 	*event_data_offset =
1119 		sizeof(*format_version) + sizeof(*tid) + sizeof(*event_class);
1120 
1121 	return PLDM_SUCCESS;
1122 }
1123 
pldm_platform_poll_for_platform_event_message_validate(uint8_t transfer_operation_flag,uint16_t event_id_to_acknowledge)1124 static int pldm_platform_poll_for_platform_event_message_validate(
1125 	uint8_t transfer_operation_flag, uint16_t event_id_to_acknowledge)
1126 {
1127 	if (((transfer_operation_flag == PLDM_GET_FIRSTPART) &&
1128 	     (event_id_to_acknowledge != PLDM_PLATFORM_EVENT_ID_NULL)) ||
1129 	    ((transfer_operation_flag == PLDM_GET_NEXTPART) &&
1130 	     (event_id_to_acknowledge != PLDM_PLATFORM_EVENT_ID_FRAGMENT)) ||
1131 	    ((transfer_operation_flag == PLDM_ACKNOWLEDGEMENT_ONLY) &&
1132 	     (event_id_to_acknowledge == PLDM_PLATFORM_EVENT_ID_FRAGMENT)) ||
1133 	    ((transfer_operation_flag == PLDM_ACKNOWLEDGEMENT_ONLY) &&
1134 	     (event_id_to_acknowledge == PLDM_PLATFORM_EVENT_ID_NULL)) ||
1135 	    (transfer_operation_flag > PLDM_ACKNOWLEDGEMENT_ONLY)) {
1136 		return -EPROTO;
1137 	}
1138 
1139 	return 0;
1140 }
1141 
1142 LIBPLDM_ABI_STABLE
decode_poll_for_platform_event_message_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * format_version,uint8_t * transfer_operation_flag,uint32_t * data_transfer_handle,uint16_t * event_id_to_acknowledge)1143 int decode_poll_for_platform_event_message_req(
1144 	const struct pldm_msg *msg, size_t payload_length,
1145 	uint8_t *format_version, uint8_t *transfer_operation_flag,
1146 	uint32_t *data_transfer_handle, uint16_t *event_id_to_acknowledge)
1147 {
1148 	PLDM_MSGBUF_DEFINE_P(buf);
1149 	int rc;
1150 
1151 	if (msg == NULL || format_version == NULL ||
1152 	    transfer_operation_flag == NULL || data_transfer_handle == NULL ||
1153 	    event_id_to_acknowledge == NULL) {
1154 		return PLDM_ERROR_INVALID_DATA;
1155 	}
1156 
1157 	rc = pldm_msgbuf_init_errno(
1158 		buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_REQ_BYTES,
1159 		msg->payload, payload_length);
1160 	if (rc) {
1161 		return pldm_xlate_errno(rc);
1162 	}
1163 
1164 	pldm_msgbuf_extract_p(buf, format_version);
1165 	rc = pldm_msgbuf_extract_p(buf, transfer_operation_flag);
1166 	if (rc) {
1167 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1168 	}
1169 	if (*transfer_operation_flag > PLDM_ACKNOWLEDGEMENT_ONLY) {
1170 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1171 	}
1172 
1173 	pldm_msgbuf_extract_p(buf, data_transfer_handle);
1174 	rc = pldm_msgbuf_extract_p(buf, event_id_to_acknowledge);
1175 	if (rc) {
1176 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1177 	}
1178 
1179 	rc = pldm_platform_poll_for_platform_event_message_validate(
1180 		*transfer_operation_flag, *event_id_to_acknowledge);
1181 	if (rc < 0) {
1182 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1183 	}
1184 
1185 	rc = pldm_msgbuf_complete(buf);
1186 	if (rc) {
1187 		return pldm_xlate_errno(rc);
1188 	}
1189 
1190 	return PLDM_SUCCESS;
1191 }
1192 
1193 LIBPLDM_ABI_STABLE
encode_platform_event_message_resp(uint8_t instance_id,uint8_t completion_code,uint8_t platform_event_status,struct pldm_msg * msg)1194 int encode_platform_event_message_resp(uint8_t instance_id,
1195 				       uint8_t completion_code,
1196 				       uint8_t platform_event_status,
1197 				       struct pldm_msg *msg)
1198 {
1199 	if (msg == NULL) {
1200 		return PLDM_ERROR_INVALID_DATA;
1201 	}
1202 
1203 	if (platform_event_status > PLDM_EVENT_LOGGING_REJECTED) {
1204 		return PLDM_ERROR_INVALID_DATA;
1205 	}
1206 
1207 	struct pldm_header_info header = { 0 };
1208 	header.msg_type = PLDM_RESPONSE;
1209 	header.instance = instance_id;
1210 	header.pldm_type = PLDM_PLATFORM;
1211 	header.command = PLDM_PLATFORM_EVENT_MESSAGE;
1212 
1213 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1214 	if (rc != PLDM_SUCCESS) {
1215 		return rc;
1216 	}
1217 
1218 	struct pldm_platform_event_message_resp *response =
1219 		(struct pldm_platform_event_message_resp *)msg->payload;
1220 	response->completion_code = completion_code;
1221 	response->platform_event_status = platform_event_status;
1222 
1223 	return PLDM_SUCCESS;
1224 }
1225 
1226 LIBPLDM_ABI_STABLE
encode_poll_for_platform_event_message_resp(uint8_t instance_id,uint8_t completion_code,uint8_t tid,uint16_t event_id,uint32_t next_data_transfer_handle,uint8_t transfer_flag,uint8_t event_class,uint32_t event_data_size,uint8_t * event_data,uint32_t checksum,struct pldm_msg * msg,size_t payload_length)1227 int encode_poll_for_platform_event_message_resp(
1228 	uint8_t instance_id, uint8_t completion_code, uint8_t tid,
1229 	uint16_t event_id, uint32_t next_data_transfer_handle,
1230 	uint8_t transfer_flag, uint8_t event_class, uint32_t event_data_size,
1231 	uint8_t *event_data, uint32_t checksum, struct pldm_msg *msg,
1232 	size_t payload_length)
1233 {
1234 	PLDM_MSGBUF_DEFINE_P(buf);
1235 	int rc;
1236 
1237 	if (!msg) {
1238 		return PLDM_ERROR_INVALID_DATA;
1239 	}
1240 
1241 	struct pldm_header_info header = { 0 };
1242 	header.msg_type = PLDM_RESPONSE;
1243 	header.instance = instance_id;
1244 	header.pldm_type = PLDM_PLATFORM;
1245 	header.command = PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE;
1246 
1247 	rc = pack_pldm_header(&header, &(msg->hdr));
1248 	if (rc != PLDM_SUCCESS) {
1249 		return rc;
1250 	}
1251 
1252 	rc = pldm_msgbuf_init_errno(
1253 		buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
1254 		msg->payload, payload_length);
1255 	if (rc) {
1256 		return pldm_xlate_errno(rc);
1257 	}
1258 
1259 	pldm_msgbuf_insert(buf, completion_code);
1260 	pldm_msgbuf_insert(buf, tid);
1261 	rc = pldm_msgbuf_insert(buf, event_id);
1262 	if (rc) {
1263 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1264 	}
1265 
1266 	if (event_id == 0xffff || event_id == 0x0000) {
1267 		if (PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES !=
1268 		    payload_length) {
1269 			return pldm_msgbuf_discard(buf,
1270 						   PLDM_ERROR_INVALID_LENGTH);
1271 		}
1272 
1273 		rc = pldm_msgbuf_complete(buf);
1274 		if (rc) {
1275 			return pldm_xlate_errno(rc);
1276 		}
1277 
1278 		return PLDM_SUCCESS;
1279 	}
1280 
1281 	if ((event_data == NULL) && (event_data_size > 0)) {
1282 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1283 	}
1284 
1285 	pldm_msgbuf_insert(buf, next_data_transfer_handle);
1286 	pldm_msgbuf_insert(buf, transfer_flag);
1287 	pldm_msgbuf_insert(buf, event_class);
1288 	rc = pldm_msgbuf_insert(buf, event_data_size);
1289 	if (rc) {
1290 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1291 	}
1292 
1293 	if ((event_data_size > 0) && event_data) {
1294 		rc = pldm_msgbuf_insert_array(buf, event_data_size, event_data,
1295 					      event_data_size);
1296 		if (rc) {
1297 			return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1298 		}
1299 	}
1300 
1301 	if (transfer_flag == PLDM_END || transfer_flag == PLDM_START_AND_END) {
1302 		pldm_msgbuf_insert(buf, checksum);
1303 	}
1304 
1305 	rc = pldm_msgbuf_complete(buf);
1306 	if (rc) {
1307 		return pldm_xlate_errno(rc);
1308 	}
1309 
1310 	return PLDM_SUCCESS;
1311 }
1312 
1313 LIBPLDM_ABI_STABLE
encode_platform_event_message_req(uint8_t instance_id,uint8_t format_version,uint8_t tid,uint8_t event_class,const uint8_t * event_data,size_t event_data_length,struct pldm_msg * msg,size_t payload_length)1314 int encode_platform_event_message_req(
1315 	uint8_t instance_id, uint8_t format_version, uint8_t tid,
1316 	uint8_t event_class, const uint8_t *event_data,
1317 	size_t event_data_length, struct pldm_msg *msg, size_t payload_length)
1318 
1319 {
1320 	if (format_version != 1) {
1321 		return PLDM_ERROR_INVALID_DATA;
1322 	}
1323 
1324 	if (msg == NULL || event_data == NULL) {
1325 		return PLDM_ERROR_INVALID_DATA;
1326 	}
1327 
1328 	if (event_data_length == 0) {
1329 		return PLDM_ERROR_INVALID_DATA;
1330 	}
1331 
1332 	if ((SIZE_MAX - PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES) <
1333 	    event_data_length) {
1334 		return PLDM_ERROR_INVALID_LENGTH;
1335 	}
1336 
1337 	if (payload_length !=
1338 	    PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES + event_data_length) {
1339 		return PLDM_ERROR_INVALID_LENGTH;
1340 	}
1341 
1342 	if (event_class > PLDM_CPER_EVENT &&
1343 	    !(event_class >= 0xf0 && event_class <= 0xfe)) {
1344 		return PLDM_ERROR_INVALID_DATA;
1345 	}
1346 
1347 	struct pldm_header_info header = { 0 };
1348 	header.msg_type = PLDM_REQUEST;
1349 	header.instance = instance_id;
1350 	header.pldm_type = PLDM_PLATFORM;
1351 	header.command = PLDM_PLATFORM_EVENT_MESSAGE;
1352 
1353 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1354 	if (rc != PLDM_SUCCESS) {
1355 		return rc;
1356 	}
1357 
1358 	struct pldm_platform_event_message_req *request =
1359 		(struct pldm_platform_event_message_req *)msg->payload;
1360 	request->format_version = format_version;
1361 	request->tid = tid;
1362 	request->event_class = event_class;
1363 	memcpy(request->event_data, event_data, event_data_length);
1364 
1365 	return PLDM_SUCCESS;
1366 }
1367 
1368 LIBPLDM_ABI_STABLE
decode_platform_event_message_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * platform_event_status)1369 int decode_platform_event_message_resp(const struct pldm_msg *msg,
1370 				       size_t payload_length,
1371 				       uint8_t *completion_code,
1372 				       uint8_t *platform_event_status)
1373 {
1374 	PLDM_MSGBUF_DEFINE_P(buf);
1375 	int rc;
1376 
1377 	if (msg == NULL || completion_code == NULL ||
1378 	    platform_event_status == NULL) {
1379 		return PLDM_ERROR_INVALID_DATA;
1380 	}
1381 
1382 	rc = pldm_msgbuf_init_errno(buf, PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES,
1383 				    msg->payload, payload_length);
1384 	if (rc) {
1385 		return pldm_xlate_errno(rc);
1386 	}
1387 
1388 	rc = pldm_msgbuf_extract_p(buf, completion_code);
1389 	if (rc) {
1390 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1391 	}
1392 
1393 	if (PLDM_SUCCESS != *completion_code) {
1394 		return pldm_msgbuf_discard(buf, PLDM_SUCCESS);
1395 	}
1396 
1397 	rc = pldm_msgbuf_extract_p(buf, platform_event_status);
1398 	if (rc) {
1399 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1400 	}
1401 
1402 	if (*platform_event_status > PLDM_EVENT_LOGGING_REJECTED) {
1403 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1404 	}
1405 
1406 	rc = pldm_msgbuf_complete(buf);
1407 	if (rc) {
1408 		return pldm_xlate_errno(rc);
1409 	}
1410 
1411 	return PLDM_SUCCESS;
1412 }
1413 
1414 LIBPLDM_ABI_STABLE
encode_event_message_buffer_size_req(uint8_t instance_id,uint16_t event_receiver_max_buffer_size,struct pldm_msg * msg)1415 int encode_event_message_buffer_size_req(uint8_t instance_id,
1416 					 uint16_t event_receiver_max_buffer_size,
1417 					 struct pldm_msg *msg)
1418 {
1419 	struct pldm_header_info header = { 0 };
1420 	header.msg_type = PLDM_REQUEST;
1421 	header.instance = instance_id;
1422 	header.pldm_type = PLDM_PLATFORM;
1423 	header.command = PLDM_EVENT_MESSAGE_BUFFER_SIZE;
1424 
1425 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1426 	if (rc != PLDM_SUCCESS) {
1427 		return rc;
1428 	}
1429 
1430 	struct pldm_event_message_buffer_size_req *request =
1431 		(struct pldm_event_message_buffer_size_req *)msg->payload;
1432 	request->event_receiver_max_buffer_size =
1433 		event_receiver_max_buffer_size;
1434 
1435 	return PLDM_SUCCESS;
1436 }
1437 
1438 LIBPLDM_ABI_STABLE
decode_event_message_buffer_size_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint16_t * terminus_max_buffer_size)1439 int decode_event_message_buffer_size_resp(const struct pldm_msg *msg,
1440 					  size_t payload_length,
1441 					  uint8_t *completion_code,
1442 					  uint16_t *terminus_max_buffer_size)
1443 {
1444 	PLDM_MSGBUF_DEFINE_P(buf);
1445 	int rc;
1446 
1447 	if (msg == NULL || completion_code == NULL ||
1448 	    terminus_max_buffer_size == NULL) {
1449 		return PLDM_ERROR_INVALID_DATA;
1450 	}
1451 
1452 	rc = pldm_msgbuf_init_errno(buf,
1453 				    PLDM_EVENT_MESSAGE_BUFFER_SIZE_RESP_BYTES,
1454 				    msg->payload, payload_length);
1455 	if (rc) {
1456 		return pldm_xlate_errno(rc);
1457 	}
1458 
1459 	rc = pldm_msgbuf_extract_p(buf, completion_code);
1460 	if (rc) {
1461 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1462 	}
1463 
1464 	if (PLDM_SUCCESS != *completion_code) {
1465 		return pldm_msgbuf_discard(buf, PLDM_SUCCESS);
1466 	}
1467 
1468 	pldm_msgbuf_extract_p(buf, terminus_max_buffer_size);
1469 
1470 	rc = pldm_msgbuf_complete_consumed(buf);
1471 	if (rc) {
1472 		return pldm_xlate_errno(rc);
1473 	}
1474 
1475 	return PLDM_SUCCESS;
1476 }
1477 
1478 LIBPLDM_ABI_STABLE
encode_event_message_supported_req(uint8_t instance_id,uint8_t format_version,struct pldm_msg * msg)1479 int encode_event_message_supported_req(uint8_t instance_id,
1480 				       uint8_t format_version,
1481 				       struct pldm_msg *msg)
1482 {
1483 	if (format_version != 1) {
1484 		return PLDM_ERROR_INVALID_DATA;
1485 	}
1486 
1487 	if (msg == NULL) {
1488 		return PLDM_ERROR_INVALID_DATA;
1489 	}
1490 
1491 	struct pldm_header_info header = { 0 };
1492 	header.msg_type = PLDM_REQUEST;
1493 	header.instance = instance_id;
1494 	header.pldm_type = PLDM_PLATFORM;
1495 	header.command = PLDM_EVENT_MESSAGE_SUPPORTED;
1496 
1497 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1498 	if (rc != PLDM_SUCCESS) {
1499 		return rc;
1500 	}
1501 
1502 	struct pldm_event_message_supported_req *request =
1503 		(struct pldm_event_message_supported_req *)msg->payload;
1504 	request->format_version = format_version;
1505 
1506 	return PLDM_SUCCESS;
1507 }
1508 
1509 LIBPLDM_ABI_STABLE
decode_event_message_supported_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * synchrony_config,bitfield8_t * synchrony_config_support,uint8_t * number_event_class_returned,uint8_t * event_class,uint8_t event_class_count)1510 int decode_event_message_supported_resp(const struct pldm_msg *msg,
1511 					size_t payload_length,
1512 					uint8_t *completion_code,
1513 					uint8_t *synchrony_config,
1514 					bitfield8_t *synchrony_config_support,
1515 					uint8_t *number_event_class_returned,
1516 					uint8_t *event_class,
1517 					uint8_t event_class_count)
1518 {
1519 	PLDM_MSGBUF_DEFINE_P(buf);
1520 	int i;
1521 	int rc;
1522 
1523 	if (msg == NULL || completion_code == NULL ||
1524 	    synchrony_config == NULL || synchrony_config_support == NULL ||
1525 	    number_event_class_returned == NULL || event_class == NULL) {
1526 		return PLDM_ERROR_INVALID_DATA;
1527 	}
1528 
1529 	rc = pldm_msgbuf_init_errno(buf,
1530 				    PLDM_EVENT_MESSAGE_SUPPORTED_MIN_RESP_BYTES,
1531 				    msg->payload, payload_length);
1532 	if (rc) {
1533 		return pldm_xlate_errno(rc);
1534 	}
1535 
1536 	rc = pldm_msgbuf_extract_p(buf, completion_code);
1537 	if (rc) {
1538 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1539 	}
1540 
1541 	if (PLDM_SUCCESS != *completion_code) {
1542 		return pldm_msgbuf_discard(buf, PLDM_SUCCESS);
1543 	}
1544 
1545 	rc = pldm_msgbuf_extract_p(buf, synchrony_config);
1546 	if (rc) {
1547 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1548 	}
1549 
1550 	if (*synchrony_config > PLDM_MESSAGE_TYPE_ASYNCHRONOUS_WITH_HEARTBEAT) {
1551 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1552 	}
1553 
1554 	pldm_msgbuf_extract_p(buf, &synchrony_config_support->byte);
1555 
1556 	rc = pldm_msgbuf_extract_p(buf, number_event_class_returned);
1557 	if (rc) {
1558 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1559 	}
1560 
1561 	if (*number_event_class_returned == 0) {
1562 		rc = pldm_msgbuf_complete(buf);
1563 		if (rc) {
1564 			return pldm_xlate_errno(rc);
1565 		}
1566 
1567 		return PLDM_SUCCESS;
1568 	}
1569 
1570 	if (event_class_count < *number_event_class_returned) {
1571 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_LENGTH);
1572 	}
1573 
1574 	for (i = 0; i < *number_event_class_returned; i++) {
1575 		pldm_msgbuf_extract(buf, event_class[i]);
1576 	}
1577 
1578 	rc = pldm_msgbuf_complete_consumed(buf);
1579 	if (rc) {
1580 		return pldm_xlate_errno(rc);
1581 	}
1582 
1583 	return PLDM_SUCCESS;
1584 }
1585 
1586 LIBPLDM_ABI_STABLE
decode_sensor_event_data(const uint8_t * event_data,size_t event_data_length,uint16_t * sensor_id,uint8_t * sensor_event_class_type,size_t * event_class_data_offset)1587 int decode_sensor_event_data(const uint8_t *event_data,
1588 			     size_t event_data_length, uint16_t *sensor_id,
1589 			     uint8_t *sensor_event_class_type,
1590 			     size_t *event_class_data_offset)
1591 {
1592 	PLDM_MSGBUF_DEFINE_P(buf);
1593 	int rc;
1594 
1595 	if (event_data == NULL || sensor_id == NULL ||
1596 	    sensor_event_class_type == NULL ||
1597 	    event_class_data_offset == NULL) {
1598 		return PLDM_ERROR_INVALID_DATA;
1599 	}
1600 
1601 	rc = pldm_msgbuf_init_errno(buf, PLDM_SENSOR_EVENT_DATA_MIN_LENGTH,
1602 				    event_data, event_data_length);
1603 	if (rc) {
1604 		return pldm_xlate_errno(rc);
1605 	}
1606 
1607 	if (event_data_length < PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES) {
1608 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_LENGTH);
1609 	}
1610 
1611 	size_t event_class_data_length =
1612 		event_data_length - PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES;
1613 
1614 	pldm_msgbuf_extract_p(buf, sensor_id);
1615 	rc = pldm_msgbuf_extract_p(buf, sensor_event_class_type);
1616 	if (rc) {
1617 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1618 	}
1619 
1620 	if (*sensor_event_class_type == PLDM_SENSOR_OP_STATE) {
1621 		if (event_class_data_length !=
1622 		    PLDM_SENSOR_EVENT_SENSOR_OP_STATE_DATA_LENGTH) {
1623 			return pldm_msgbuf_discard(buf,
1624 						   PLDM_ERROR_INVALID_LENGTH);
1625 		}
1626 	} else if (*sensor_event_class_type == PLDM_STATE_SENSOR_STATE) {
1627 		if (event_class_data_length !=
1628 		    PLDM_SENSOR_EVENT_STATE_SENSOR_STATE_DATA_LENGTH) {
1629 			return pldm_msgbuf_discard(buf,
1630 						   PLDM_ERROR_INVALID_LENGTH);
1631 		}
1632 	} else if (*sensor_event_class_type == PLDM_NUMERIC_SENSOR_STATE) {
1633 		if (event_class_data_length <
1634 			    PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MIN_DATA_LENGTH ||
1635 		    event_class_data_length >
1636 			    PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MAX_DATA_LENGTH) {
1637 			return pldm_msgbuf_discard(buf,
1638 						   PLDM_ERROR_INVALID_LENGTH);
1639 		}
1640 	} else {
1641 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1642 	}
1643 
1644 	*event_class_data_offset =
1645 		sizeof(*sensor_id) + sizeof(*sensor_event_class_type);
1646 
1647 	rc = pldm_msgbuf_complete(buf);
1648 	if (rc) {
1649 		return pldm_xlate_errno(rc);
1650 	}
1651 
1652 	return PLDM_SUCCESS;
1653 }
1654 
1655 LIBPLDM_ABI_STABLE
decode_sensor_op_data(const uint8_t * sensor_data,size_t sensor_data_length,uint8_t * present_op_state,uint8_t * previous_op_state)1656 int decode_sensor_op_data(const uint8_t *sensor_data, size_t sensor_data_length,
1657 			  uint8_t *present_op_state, uint8_t *previous_op_state)
1658 {
1659 	PLDM_MSGBUF_DEFINE_P(buf);
1660 	int rc;
1661 
1662 	if (sensor_data == NULL || present_op_state == NULL ||
1663 	    previous_op_state == NULL) {
1664 		return PLDM_ERROR_INVALID_DATA;
1665 	}
1666 
1667 	rc = pldm_msgbuf_init_errno(
1668 		buf, PLDM_SENSOR_EVENT_SENSOR_OP_STATE_DATA_LENGTH, sensor_data,
1669 		sensor_data_length);
1670 	if (rc) {
1671 		return pldm_xlate_errno(rc);
1672 	}
1673 
1674 	pldm_msgbuf_extract_p(buf, present_op_state);
1675 	pldm_msgbuf_extract_p(buf, previous_op_state);
1676 
1677 	rc = pldm_msgbuf_complete_consumed(buf);
1678 	if (rc) {
1679 		return pldm_xlate_errno(rc);
1680 	}
1681 
1682 	return PLDM_SUCCESS;
1683 }
1684 
1685 LIBPLDM_ABI_STABLE
decode_state_sensor_data(const uint8_t * sensor_data,size_t sensor_data_length,uint8_t * sensor_offset,uint8_t * event_state,uint8_t * previous_event_state)1686 int decode_state_sensor_data(const uint8_t *sensor_data,
1687 			     size_t sensor_data_length, uint8_t *sensor_offset,
1688 			     uint8_t *event_state,
1689 			     uint8_t *previous_event_state)
1690 {
1691 	PLDM_MSGBUF_DEFINE_P(buf);
1692 	int rc;
1693 
1694 	if (sensor_data == NULL || sensor_offset == NULL ||
1695 	    event_state == NULL || previous_event_state == NULL) {
1696 		return PLDM_ERROR_INVALID_DATA;
1697 	}
1698 
1699 	rc = pldm_msgbuf_init_errno(
1700 		buf, PLDM_SENSOR_EVENT_STATE_SENSOR_STATE_DATA_LENGTH,
1701 		sensor_data, sensor_data_length);
1702 	if (rc) {
1703 		return pldm_xlate_errno(rc);
1704 	}
1705 
1706 	pldm_msgbuf_extract_p(buf, sensor_offset);
1707 	pldm_msgbuf_extract_p(buf, event_state);
1708 	pldm_msgbuf_extract_p(buf, previous_event_state);
1709 
1710 	rc = pldm_msgbuf_complete_consumed(buf);
1711 	if (rc) {
1712 		return pldm_xlate_errno(rc);
1713 	}
1714 
1715 	return PLDM_SUCCESS;
1716 }
1717 
1718 LIBPLDM_ABI_STABLE
decode_numeric_sensor_data(const uint8_t * sensor_data,size_t sensor_data_length,uint8_t * event_state,uint8_t * previous_event_state,uint8_t * sensor_data_size,uint32_t * present_reading)1719 int decode_numeric_sensor_data(const uint8_t *sensor_data,
1720 			       size_t sensor_data_length, uint8_t *event_state,
1721 			       uint8_t *previous_event_state,
1722 			       uint8_t *sensor_data_size,
1723 			       uint32_t *present_reading)
1724 {
1725 	PLDM_MSGBUF_DEFINE_P(buf);
1726 	int rc;
1727 
1728 	if (sensor_data == NULL || sensor_data_size == NULL ||
1729 	    event_state == NULL || previous_event_state == NULL ||
1730 	    present_reading == NULL) {
1731 		return PLDM_ERROR_INVALID_DATA;
1732 	}
1733 
1734 	if (sensor_data_length >
1735 	    PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MAX_DATA_LENGTH) {
1736 		return PLDM_ERROR_INVALID_LENGTH;
1737 	}
1738 
1739 	rc = pldm_msgbuf_init_errno(
1740 		buf, PLDM_SENSOR_EVENT_NUMERIC_SENSOR_STATE_MIN_DATA_LENGTH,
1741 		sensor_data, sensor_data_length);
1742 	if (rc) {
1743 		return pldm_xlate_errno(rc);
1744 	}
1745 
1746 	pldm_msgbuf_extract_p(buf, event_state);
1747 	pldm_msgbuf_extract_p(buf, previous_event_state);
1748 	rc = pldm_msgbuf_extract_p(buf, sensor_data_size);
1749 	if (rc) {
1750 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1751 	}
1752 
1753 	/*
1754 	 * The implementation below is bonkers, but it's because the function
1755 	 * prototype is bonkers. The `present_reading` argument should have been
1756 	 * a tagged union.
1757 	 */
1758 	switch (*sensor_data_size) {
1759 	case PLDM_SENSOR_DATA_SIZE_UINT8: {
1760 		uint8_t val;
1761 		if (!pldm_msgbuf_extract(buf, val)) {
1762 			*present_reading = (uint32_t)val;
1763 		}
1764 		break;
1765 	}
1766 	case PLDM_SENSOR_DATA_SIZE_SINT8: {
1767 		int8_t val;
1768 		if (!pldm_msgbuf_extract(buf, val)) {
1769 			*present_reading = (uint32_t)(int32_t)val;
1770 		}
1771 		break;
1772 	}
1773 	case PLDM_SENSOR_DATA_SIZE_UINT16: {
1774 		uint16_t val;
1775 		if (!pldm_msgbuf_extract(buf, val)) {
1776 			*present_reading = (uint32_t)val;
1777 		}
1778 		break;
1779 	}
1780 	case PLDM_SENSOR_DATA_SIZE_SINT16: {
1781 		int16_t val;
1782 		if (!pldm_msgbuf_extract(buf, val)) {
1783 			*present_reading = (uint32_t)(int32_t)val;
1784 		}
1785 		break;
1786 	}
1787 	case PLDM_SENSOR_DATA_SIZE_UINT32: {
1788 		uint32_t val;
1789 		if (!pldm_msgbuf_extract(buf, val)) {
1790 			*present_reading = (uint32_t)val;
1791 		}
1792 		break;
1793 	}
1794 	case PLDM_SENSOR_DATA_SIZE_SINT32: {
1795 		int32_t val;
1796 		if (!pldm_msgbuf_extract(buf, val)) {
1797 			*present_reading = (uint32_t)val;
1798 		}
1799 		break;
1800 	}
1801 	default:
1802 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1803 	}
1804 
1805 	rc = pldm_msgbuf_complete_consumed(buf);
1806 	if (rc) {
1807 		return pldm_xlate_errno(rc);
1808 	}
1809 
1810 	return PLDM_SUCCESS;
1811 }
1812 
1813 LIBPLDM_ABI_STABLE
decode_numeric_sensor_pdr_data(const void * pdr_data,size_t pdr_data_length,struct pldm_numeric_sensor_value_pdr * pdr_value)1814 int decode_numeric_sensor_pdr_data(
1815 	const void *pdr_data, size_t pdr_data_length,
1816 	struct pldm_numeric_sensor_value_pdr *pdr_value)
1817 {
1818 	PLDM_MSGBUF_DEFINE_P(buf);
1819 	int rc;
1820 
1821 	if (!pdr_data || !pdr_value) {
1822 		return PLDM_ERROR_INVALID_DATA;
1823 	}
1824 
1825 	rc = pldm_msgbuf_init_errno(buf, PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
1826 				    pdr_data, pdr_data_length);
1827 	if (rc) {
1828 		return pldm_xlate_errno(rc);
1829 	}
1830 
1831 	rc = pldm_msgbuf_extract_value_pdr_hdr(
1832 		buf, &pdr_value->hdr, PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
1833 		pdr_data_length);
1834 	if (rc) {
1835 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1836 	}
1837 
1838 	pldm_msgbuf_extract(buf, pdr_value->terminus_handle);
1839 	pldm_msgbuf_extract(buf, pdr_value->sensor_id);
1840 	pldm_msgbuf_extract(buf, pdr_value->entity_type);
1841 	pldm_msgbuf_extract(buf, pdr_value->entity_instance_num);
1842 	pldm_msgbuf_extract(buf, pdr_value->container_id);
1843 	pldm_msgbuf_extract(buf, pdr_value->sensor_init);
1844 	pldm_msgbuf_extract(buf, pdr_value->sensor_auxiliary_names_pdr);
1845 	pldm_msgbuf_extract(buf, pdr_value->base_unit);
1846 	pldm_msgbuf_extract(buf, pdr_value->unit_modifier);
1847 	pldm_msgbuf_extract(buf, pdr_value->rate_unit);
1848 	pldm_msgbuf_extract(buf, pdr_value->base_oem_unit_handle);
1849 	pldm_msgbuf_extract(buf, pdr_value->aux_unit);
1850 	pldm_msgbuf_extract(buf, pdr_value->aux_unit_modifier);
1851 	pldm_msgbuf_extract(buf, pdr_value->aux_rate_unit);
1852 	pldm_msgbuf_extract(buf, pdr_value->rel);
1853 	pldm_msgbuf_extract(buf, pdr_value->aux_oem_unit_handle);
1854 	pldm_msgbuf_extract(buf, pdr_value->is_linear);
1855 
1856 	rc = pldm_msgbuf_extract(buf, pdr_value->sensor_data_size);
1857 	if (rc) {
1858 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1859 	}
1860 	if (pdr_value->sensor_data_size > PLDM_SENSOR_DATA_SIZE_MAX) {
1861 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1862 	}
1863 
1864 	pldm_msgbuf_extract(buf, pdr_value->resolution);
1865 	pldm_msgbuf_extract(buf, pdr_value->offset);
1866 	pldm_msgbuf_extract(buf, pdr_value->accuracy);
1867 	pldm_msgbuf_extract(buf, pdr_value->plus_tolerance);
1868 	pldm_msgbuf_extract(buf, pdr_value->minus_tolerance);
1869 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
1870 					&pdr_value->hysteresis);
1871 	pldm_msgbuf_extract(buf, pdr_value->supported_thresholds.byte);
1872 	pldm_msgbuf_extract(
1873 		buf, pdr_value->threshold_and_hysteresis_volatility.byte);
1874 	pldm_msgbuf_extract(buf, pdr_value->state_transition_interval);
1875 	pldm_msgbuf_extract(buf, pdr_value->update_interval);
1876 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
1877 					&pdr_value->max_readable);
1878 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
1879 					&pdr_value->min_readable);
1880 
1881 	rc = pldm_msgbuf_extract(buf, pdr_value->range_field_format);
1882 	if (rc) {
1883 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
1884 	}
1885 	if (pdr_value->range_field_format > PLDM_RANGE_FIELD_FORMAT_MAX) {
1886 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
1887 	}
1888 
1889 	pldm_msgbuf_extract(buf, pdr_value->range_field_support.byte);
1890 	pldm_msgbuf_extract_range_field_format(
1891 		buf, pdr_value->range_field_format, pdr_value->nominal_value);
1892 	pldm_msgbuf_extract_range_field_format(
1893 		buf, pdr_value->range_field_format, pdr_value->normal_max);
1894 	pldm_msgbuf_extract_range_field_format(
1895 		buf, pdr_value->range_field_format, pdr_value->normal_min);
1896 	pldm_msgbuf_extract_range_field_format(
1897 		buf, pdr_value->range_field_format, pdr_value->warning_high);
1898 	pldm_msgbuf_extract_range_field_format(
1899 		buf, pdr_value->range_field_format, pdr_value->warning_low);
1900 	pldm_msgbuf_extract_range_field_format(
1901 		buf, pdr_value->range_field_format, pdr_value->critical_high);
1902 	pldm_msgbuf_extract_range_field_format(
1903 		buf, pdr_value->range_field_format, pdr_value->critical_low);
1904 	pldm_msgbuf_extract_range_field_format(
1905 		buf, pdr_value->range_field_format, pdr_value->fatal_high);
1906 	pldm_msgbuf_extract_range_field_format(
1907 		buf, pdr_value->range_field_format, pdr_value->fatal_low);
1908 
1909 	rc = pldm_msgbuf_complete(buf);
1910 	if (rc) {
1911 		return pldm_xlate_errno(rc);
1912 	}
1913 
1914 	return PLDM_SUCCESS;
1915 }
1916 
1917 LIBPLDM_ABI_STABLE
encode_get_numeric_effecter_value_req(uint8_t instance_id,uint16_t effecter_id,struct pldm_msg * msg)1918 int encode_get_numeric_effecter_value_req(uint8_t instance_id,
1919 					  uint16_t effecter_id,
1920 					  struct pldm_msg *msg)
1921 {
1922 	if (msg == NULL) {
1923 		return PLDM_ERROR_INVALID_DATA;
1924 	}
1925 
1926 	struct pldm_header_info header = { 0 };
1927 	header.msg_type = PLDM_REQUEST;
1928 	header.instance = instance_id;
1929 	header.pldm_type = PLDM_PLATFORM;
1930 	header.command = PLDM_GET_NUMERIC_EFFECTER_VALUE;
1931 
1932 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1933 	if (rc != PLDM_SUCCESS) {
1934 		return rc;
1935 	}
1936 
1937 	struct pldm_get_numeric_effecter_value_req *request =
1938 		(struct pldm_get_numeric_effecter_value_req *)msg->payload;
1939 	request->effecter_id = htole16(effecter_id);
1940 
1941 	return PLDM_SUCCESS;
1942 }
1943 
1944 LIBPLDM_ABI_STABLE
encode_get_numeric_effecter_value_resp(uint8_t instance_id,uint8_t completion_code,uint8_t effecter_data_size,uint8_t effecter_oper_state,const uint8_t * pending_value,const uint8_t * present_value,struct pldm_msg * msg,size_t payload_length)1945 int encode_get_numeric_effecter_value_resp(
1946 	uint8_t instance_id, uint8_t completion_code,
1947 	uint8_t effecter_data_size, uint8_t effecter_oper_state,
1948 	const uint8_t *pending_value, const uint8_t *present_value,
1949 	struct pldm_msg *msg, size_t payload_length)
1950 {
1951 	if (msg == NULL || pending_value == NULL || present_value == NULL) {
1952 		return PLDM_ERROR_INVALID_DATA;
1953 	}
1954 
1955 	if (effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
1956 		return PLDM_ERROR_INVALID_DATA;
1957 	}
1958 
1959 	if (effecter_oper_state > EFFECTER_OPER_STATE_INTEST) {
1960 		return PLDM_ERROR_INVALID_DATA;
1961 	}
1962 
1963 	struct pldm_header_info header = { 0 };
1964 	header.msg_type = PLDM_RESPONSE;
1965 	header.instance = instance_id;
1966 	header.pldm_type = PLDM_PLATFORM;
1967 	header.command = PLDM_GET_NUMERIC_EFFECTER_VALUE;
1968 
1969 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1970 	if (rc != PLDM_SUCCESS) {
1971 		return rc;
1972 	}
1973 
1974 	struct pldm_get_numeric_effecter_value_resp *response =
1975 		(struct pldm_get_numeric_effecter_value_resp *)msg->payload;
1976 
1977 	response->completion_code = completion_code;
1978 	response->effecter_data_size = effecter_data_size;
1979 	response->effecter_oper_state = effecter_oper_state;
1980 
1981 	if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
1982 	    effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
1983 		if (payload_length !=
1984 		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES) {
1985 			return PLDM_ERROR_INVALID_LENGTH;
1986 		}
1987 		response->pending_and_present_values[0] = *pending_value;
1988 		response->pending_and_present_values[1] = *present_value;
1989 
1990 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
1991 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
1992 		if (payload_length !=
1993 		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 2) {
1994 			return PLDM_ERROR_INVALID_LENGTH;
1995 		}
1996 		uint16_t val_pending = *(uint16_t *)pending_value;
1997 		val_pending = htole16(val_pending);
1998 		memcpy(response->pending_and_present_values, &val_pending,
1999 		       sizeof(uint16_t));
2000 		uint16_t val_present = *(uint16_t *)present_value;
2001 		val_present = htole16(val_present);
2002 		memcpy((response->pending_and_present_values +
2003 			sizeof(uint16_t)),
2004 		       &val_present, sizeof(uint16_t));
2005 
2006 	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
2007 		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
2008 		if (payload_length !=
2009 		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 6) {
2010 			return PLDM_ERROR_INVALID_LENGTH;
2011 		}
2012 		uint32_t val_pending = *(uint32_t *)pending_value;
2013 		val_pending = htole32(val_pending);
2014 		memcpy(response->pending_and_present_values, &val_pending,
2015 		       sizeof(uint32_t));
2016 		uint32_t val_present = *(uint32_t *)present_value;
2017 		val_present = htole32(val_present);
2018 		memcpy((response->pending_and_present_values +
2019 			sizeof(uint32_t)),
2020 		       &val_present, sizeof(uint32_t));
2021 	}
2022 	return PLDM_SUCCESS;
2023 }
2024 
2025 LIBPLDM_ABI_STABLE
decode_get_numeric_effecter_value_req(const struct pldm_msg * msg,size_t payload_length,uint16_t * effecter_id)2026 int decode_get_numeric_effecter_value_req(const struct pldm_msg *msg,
2027 					  size_t payload_length,
2028 					  uint16_t *effecter_id)
2029 {
2030 	PLDM_MSGBUF_DEFINE_P(buf);
2031 	int rc;
2032 
2033 	if (msg == NULL || effecter_id == NULL) {
2034 		return PLDM_ERROR_INVALID_DATA;
2035 	}
2036 
2037 	rc = pldm_msgbuf_init_errno(buf,
2038 				    PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES,
2039 				    msg->payload, payload_length);
2040 	if (rc) {
2041 		return pldm_xlate_errno(rc);
2042 	}
2043 
2044 	pldm_msgbuf_extract_p(buf, effecter_id);
2045 
2046 	rc = pldm_msgbuf_complete_consumed(buf);
2047 	if (rc) {
2048 		return pldm_xlate_errno(rc);
2049 	}
2050 
2051 	return PLDM_SUCCESS;
2052 }
2053 
2054 LIBPLDM_ABI_STABLE
decode_get_numeric_effecter_value_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * effecter_data_size,uint8_t * effecter_oper_state,uint8_t * pending_value,uint8_t * present_value)2055 int decode_get_numeric_effecter_value_resp(const struct pldm_msg *msg,
2056 					   size_t payload_length,
2057 					   uint8_t *completion_code,
2058 					   uint8_t *effecter_data_size,
2059 					   uint8_t *effecter_oper_state,
2060 					   uint8_t *pending_value,
2061 					   uint8_t *present_value)
2062 {
2063 	PLDM_MSGBUF_DEFINE_P(buf);
2064 	int rc;
2065 
2066 	if (msg == NULL || effecter_data_size == NULL ||
2067 	    effecter_oper_state == NULL || pending_value == NULL ||
2068 	    present_value == NULL) {
2069 		return PLDM_ERROR_INVALID_DATA;
2070 	}
2071 
2072 	rc = pldm_msgbuf_init_errno(
2073 		buf, PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES,
2074 		msg->payload, payload_length);
2075 	if (rc) {
2076 		return pldm_xlate_errno(rc);
2077 	}
2078 
2079 	rc = pldm_msgbuf_extract_p(buf, completion_code);
2080 	if (rc) {
2081 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2082 	}
2083 
2084 	if (PLDM_SUCCESS != *completion_code) {
2085 		return pldm_msgbuf_discard(buf, PLDM_SUCCESS);
2086 	}
2087 
2088 	rc = pldm_msgbuf_extract_p(buf, effecter_data_size);
2089 	if (rc) {
2090 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2091 	}
2092 
2093 	if (*effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
2094 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
2095 	}
2096 
2097 	rc = pldm_msgbuf_extract_p(buf, effecter_oper_state);
2098 	if (rc) {
2099 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2100 	}
2101 
2102 	if (*effecter_oper_state > EFFECTER_OPER_STATE_INTEST) {
2103 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
2104 	}
2105 
2106 	pldm_msgbuf_extract_effecter_value(buf, *effecter_data_size,
2107 					   pending_value);
2108 	pldm_msgbuf_extract_effecter_value(buf, *effecter_data_size,
2109 					   present_value);
2110 
2111 	rc = pldm_msgbuf_complete_consumed(buf);
2112 	if (rc) {
2113 		return pldm_xlate_errno(rc);
2114 	}
2115 
2116 	return PLDM_SUCCESS;
2117 }
2118 
2119 LIBPLDM_ABI_STABLE
encode_pldm_pdr_repository_chg_event_data(uint8_t event_data_format,uint8_t number_of_change_records,const uint8_t * event_data_operations,const uint8_t * numbers_of_change_entries,const uint32_t * const * change_entries,struct pldm_pdr_repository_chg_event_data * event_data,size_t * actual_change_records_size,size_t max_change_records_size)2120 int encode_pldm_pdr_repository_chg_event_data(
2121 	uint8_t event_data_format, uint8_t number_of_change_records,
2122 	const uint8_t *event_data_operations,
2123 	const uint8_t *numbers_of_change_entries,
2124 	const uint32_t *const *change_entries,
2125 	struct pldm_pdr_repository_chg_event_data *event_data,
2126 	size_t *actual_change_records_size, size_t max_change_records_size)
2127 {
2128 	if (event_data_operations == NULL ||
2129 	    numbers_of_change_entries == NULL || change_entries == NULL) {
2130 		return PLDM_ERROR_INVALID_DATA;
2131 	}
2132 
2133 	size_t expected_size =
2134 		sizeof(event_data_format) + sizeof(number_of_change_records);
2135 
2136 	expected_size +=
2137 		sizeof(*event_data_operations) * number_of_change_records;
2138 	expected_size +=
2139 		sizeof(*numbers_of_change_entries) * number_of_change_records;
2140 
2141 	for (uint8_t i = 0; i < number_of_change_records; ++i) {
2142 		expected_size += sizeof(*change_entries[0]) *
2143 				 numbers_of_change_entries[i];
2144 	}
2145 
2146 	*actual_change_records_size = expected_size;
2147 
2148 	if (event_data == NULL) {
2149 		return PLDM_SUCCESS;
2150 	}
2151 
2152 	if (max_change_records_size < expected_size) {
2153 		return PLDM_ERROR_INVALID_LENGTH;
2154 	}
2155 
2156 	event_data->event_data_format = event_data_format;
2157 	event_data->number_of_change_records = number_of_change_records;
2158 
2159 	struct pldm_pdr_repository_change_record_data *record_data =
2160 		(struct pldm_pdr_repository_change_record_data *)
2161 			event_data->change_records;
2162 
2163 	for (uint8_t i = 0; i < number_of_change_records; ++i) {
2164 		record_data->event_data_operation = event_data_operations[i];
2165 		record_data->number_of_change_entries =
2166 			numbers_of_change_entries[i];
2167 
2168 		for (uint8_t j = 0; j < record_data->number_of_change_entries;
2169 		     ++j) {
2170 			record_data->change_entry[j] =
2171 				htole32(change_entries[i][j]);
2172 		}
2173 
2174 		record_data =
2175 			(struct pldm_pdr_repository_change_record_data
2176 				 *)(record_data->change_entry +
2177 				    record_data->number_of_change_entries);
2178 	}
2179 
2180 	return PLDM_SUCCESS;
2181 }
2182 
2183 LIBPLDM_ABI_STABLE
decode_pldm_pdr_repository_chg_event_data(const uint8_t * event_data,size_t event_data_size,uint8_t * event_data_format,uint8_t * number_of_change_records,size_t * change_record_data_offset)2184 int decode_pldm_pdr_repository_chg_event_data(const uint8_t *event_data,
2185 					      size_t event_data_size,
2186 					      uint8_t *event_data_format,
2187 					      uint8_t *number_of_change_records,
2188 					      size_t *change_record_data_offset)
2189 {
2190 	PLDM_MSGBUF_DEFINE_P(buf);
2191 	int rc;
2192 
2193 	if (event_data == NULL || event_data_format == NULL ||
2194 	    number_of_change_records == NULL ||
2195 	    change_record_data_offset == NULL) {
2196 		return PLDM_ERROR_INVALID_DATA;
2197 	}
2198 
2199 	rc = pldm_msgbuf_init_errno(buf,
2200 				    PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH,
2201 				    event_data, event_data_size);
2202 	if (rc) {
2203 		return pldm_xlate_errno(rc);
2204 	}
2205 
2206 	pldm_msgbuf_extract_p(buf, event_data_format);
2207 	pldm_msgbuf_extract_p(buf, number_of_change_records);
2208 
2209 	*change_record_data_offset =
2210 		sizeof(*event_data_format) + sizeof(*number_of_change_records);
2211 
2212 	rc = pldm_msgbuf_complete(buf);
2213 	if (rc) {
2214 		return pldm_xlate_errno(rc);
2215 	}
2216 
2217 	return PLDM_SUCCESS;
2218 }
2219 
2220 LIBPLDM_ABI_STABLE
decode_pldm_message_poll_event_data(const void * event_data,size_t event_data_length,struct pldm_message_poll_event * poll_event)2221 int decode_pldm_message_poll_event_data(
2222 	const void *event_data, size_t event_data_length,
2223 	struct pldm_message_poll_event *poll_event)
2224 {
2225 	PLDM_MSGBUF_DEFINE_P(buf);
2226 	int rc;
2227 
2228 	if (!event_data || !poll_event) {
2229 		return -EINVAL;
2230 	}
2231 
2232 	rc = pldm_msgbuf_init_errno(buf, PLDM_MSG_POLL_EVENT_LENGTH, event_data,
2233 				    event_data_length);
2234 	if (rc) {
2235 		return rc;
2236 	}
2237 
2238 	pldm_msgbuf_extract(buf, poll_event->format_version);
2239 	rc = pldm_msgbuf_extract(buf, poll_event->event_id);
2240 	if (rc) {
2241 		return pldm_msgbuf_discard(buf, rc);
2242 	}
2243 
2244 	if (poll_event->event_id == 0x0000 || poll_event->event_id == 0xffff) {
2245 		return pldm_msgbuf_discard(buf, -EPROTO);
2246 	}
2247 
2248 	pldm_msgbuf_extract(buf, poll_event->data_transfer_handle);
2249 
2250 	return pldm_msgbuf_complete_consumed(buf);
2251 }
2252 
2253 LIBPLDM_ABI_TESTING
encode_pldm_message_poll_event_data(const struct pldm_message_poll_event * poll_event,void * event_data,size_t event_data_length)2254 int encode_pldm_message_poll_event_data(
2255 	const struct pldm_message_poll_event *poll_event, void *event_data,
2256 	size_t event_data_length)
2257 {
2258 	PLDM_MSGBUF_DEFINE_P(buf);
2259 	int rc;
2260 
2261 	if (poll_event == NULL || event_data == NULL) {
2262 		return -EINVAL;
2263 	}
2264 
2265 	if (poll_event->event_id == 0x0000 || poll_event->event_id == 0xffff) {
2266 		return -EPROTO;
2267 	}
2268 
2269 	rc = pldm_msgbuf_init_errno(buf, PLDM_MSG_POLL_EVENT_LENGTH, event_data,
2270 				    event_data_length);
2271 	if (rc) {
2272 		return rc;
2273 	}
2274 	pldm_msgbuf_insert(buf, poll_event->format_version);
2275 	pldm_msgbuf_insert(buf, poll_event->event_id);
2276 	pldm_msgbuf_insert(buf, poll_event->data_transfer_handle);
2277 
2278 	return pldm_msgbuf_complete_consumed(buf);
2279 }
2280 
2281 LIBPLDM_ABI_STABLE
decode_pldm_pdr_repository_change_record_data(const uint8_t * change_record_data,size_t change_record_data_size,uint8_t * event_data_operation,uint8_t * number_of_change_entries,size_t * change_entry_data_offset)2282 int decode_pldm_pdr_repository_change_record_data(
2283 	const uint8_t *change_record_data, size_t change_record_data_size,
2284 	uint8_t *event_data_operation, uint8_t *number_of_change_entries,
2285 	size_t *change_entry_data_offset)
2286 {
2287 	PLDM_MSGBUF_DEFINE_P(buf);
2288 	int rc;
2289 
2290 	if (change_record_data == NULL || event_data_operation == NULL ||
2291 	    number_of_change_entries == NULL ||
2292 	    change_entry_data_offset == NULL) {
2293 		return PLDM_ERROR_INVALID_DATA;
2294 	}
2295 
2296 	rc = pldm_msgbuf_init_errno(
2297 		buf, PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH,
2298 		change_record_data, change_record_data_size);
2299 	if (rc) {
2300 		return pldm_xlate_errno(rc);
2301 	}
2302 
2303 	pldm_msgbuf_extract_p(buf, event_data_operation);
2304 	pldm_msgbuf_extract_p(buf, number_of_change_entries);
2305 
2306 	*change_entry_data_offset = sizeof(*event_data_operation) +
2307 				    sizeof(*number_of_change_entries);
2308 
2309 	rc = pldm_msgbuf_complete(buf);
2310 	if (rc) {
2311 		return pldm_xlate_errno(rc);
2312 	}
2313 
2314 	return PLDM_SUCCESS;
2315 }
2316 
2317 LIBPLDM_ABI_STABLE
encode_get_sensor_reading_req(uint8_t instance_id,uint16_t sensor_id,uint8_t rearm_event_state,struct pldm_msg * msg)2318 int encode_get_sensor_reading_req(uint8_t instance_id, uint16_t sensor_id,
2319 				  uint8_t rearm_event_state,
2320 				  struct pldm_msg *msg)
2321 {
2322 	if (msg == NULL) {
2323 		return PLDM_ERROR_INVALID_DATA;
2324 	}
2325 
2326 	struct pldm_header_info header = { 0 };
2327 	header.msg_type = PLDM_REQUEST;
2328 	header.instance = instance_id;
2329 	header.pldm_type = PLDM_PLATFORM;
2330 	header.command = PLDM_GET_SENSOR_READING;
2331 
2332 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2333 	if (rc != PLDM_SUCCESS) {
2334 		return rc;
2335 	}
2336 
2337 	struct pldm_get_sensor_reading_req *request =
2338 		(struct pldm_get_sensor_reading_req *)msg->payload;
2339 
2340 	request->sensor_id = htole16(sensor_id);
2341 	request->rearm_event_state = rearm_event_state;
2342 
2343 	return PLDM_SUCCESS;
2344 }
2345 
2346 LIBPLDM_ABI_STABLE
decode_get_sensor_reading_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * sensor_data_size,uint8_t * sensor_operational_state,uint8_t * sensor_event_message_enable,uint8_t * present_state,uint8_t * previous_state,uint8_t * event_state,uint8_t * present_reading)2347 int decode_get_sensor_reading_resp(
2348 	const struct pldm_msg *msg, size_t payload_length,
2349 	uint8_t *completion_code, uint8_t *sensor_data_size,
2350 	uint8_t *sensor_operational_state, uint8_t *sensor_event_message_enable,
2351 	uint8_t *present_state, uint8_t *previous_state, uint8_t *event_state,
2352 	uint8_t *present_reading)
2353 {
2354 	PLDM_MSGBUF_DEFINE_P(buf);
2355 	int rc;
2356 
2357 	if (msg == NULL || completion_code == NULL ||
2358 	    sensor_data_size == NULL || sensor_operational_state == NULL ||
2359 	    sensor_event_message_enable == NULL || present_state == NULL ||
2360 	    previous_state == NULL || event_state == NULL ||
2361 	    present_reading == NULL) {
2362 		return PLDM_ERROR_INVALID_DATA;
2363 	}
2364 
2365 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_SENSOR_READING_MIN_RESP_BYTES,
2366 				    msg->payload, payload_length);
2367 	if (rc) {
2368 		return pldm_xlate_errno(rc);
2369 	}
2370 
2371 	rc = pldm_msgbuf_extract_p(buf, completion_code);
2372 	if (rc) {
2373 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2374 	}
2375 
2376 	if (PLDM_SUCCESS != *completion_code) {
2377 		return pldm_msgbuf_discard(buf, PLDM_SUCCESS);
2378 	}
2379 
2380 	rc = pldm_msgbuf_extract_p(buf, sensor_data_size);
2381 	if (rc) {
2382 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2383 	}
2384 
2385 	if (*sensor_data_size > PLDM_SENSOR_DATA_SIZE_SINT32) {
2386 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
2387 	}
2388 
2389 	pldm_msgbuf_extract_p(buf, sensor_operational_state);
2390 	pldm_msgbuf_extract_p(buf, sensor_event_message_enable);
2391 	pldm_msgbuf_extract_p(buf, present_state);
2392 	pldm_msgbuf_extract_p(buf, previous_state);
2393 	pldm_msgbuf_extract_p(buf, event_state);
2394 
2395 	pldm_msgbuf_extract_sensor_value(buf, *sensor_data_size,
2396 					 present_reading);
2397 
2398 	rc = pldm_msgbuf_complete_consumed(buf);
2399 	if (rc) {
2400 		return pldm_xlate_errno(rc);
2401 	}
2402 
2403 	return PLDM_SUCCESS;
2404 }
2405 
2406 LIBPLDM_ABI_STABLE
encode_get_sensor_reading_resp(uint8_t instance_id,uint8_t completion_code,uint8_t sensor_data_size,uint8_t sensor_operational_state,uint8_t sensor_event_message_enable,uint8_t present_state,uint8_t previous_state,uint8_t event_state,const uint8_t * present_reading,struct pldm_msg * msg,size_t payload_length)2407 int encode_get_sensor_reading_resp(uint8_t instance_id, uint8_t completion_code,
2408 				   uint8_t sensor_data_size,
2409 				   uint8_t sensor_operational_state,
2410 				   uint8_t sensor_event_message_enable,
2411 				   uint8_t present_state,
2412 				   uint8_t previous_state, uint8_t event_state,
2413 				   const uint8_t *present_reading,
2414 				   struct pldm_msg *msg, size_t payload_length)
2415 {
2416 	if (msg == NULL || present_reading == NULL) {
2417 		return PLDM_ERROR_INVALID_DATA;
2418 	}
2419 
2420 	if (sensor_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
2421 		return PLDM_ERROR_INVALID_DATA;
2422 	}
2423 
2424 	struct pldm_header_info header = { 0 };
2425 	header.msg_type = PLDM_RESPONSE;
2426 	header.instance = instance_id;
2427 	header.pldm_type = PLDM_PLATFORM;
2428 	header.command = PLDM_GET_SENSOR_READING;
2429 
2430 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2431 	if (rc != PLDM_SUCCESS) {
2432 		return rc;
2433 	}
2434 
2435 	struct pldm_get_sensor_reading_resp *response =
2436 		(struct pldm_get_sensor_reading_resp *)msg->payload;
2437 
2438 	response->completion_code = completion_code;
2439 	response->sensor_data_size = sensor_data_size;
2440 	response->sensor_operational_state = sensor_operational_state;
2441 	response->sensor_event_message_enable = sensor_event_message_enable;
2442 	response->present_state = present_state;
2443 	response->previous_state = previous_state;
2444 	response->event_state = event_state;
2445 
2446 	if (sensor_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
2447 	    sensor_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
2448 		if (payload_length != PLDM_GET_SENSOR_READING_MIN_RESP_BYTES) {
2449 			return PLDM_ERROR_INVALID_LENGTH;
2450 		}
2451 		response->present_reading[0] = *present_reading;
2452 
2453 	} else if (sensor_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
2454 		   sensor_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
2455 		if (payload_length !=
2456 		    PLDM_GET_SENSOR_READING_MIN_RESP_BYTES + 1) {
2457 			return PLDM_ERROR_INVALID_LENGTH;
2458 		}
2459 		uint16_t val = *(uint16_t *)present_reading;
2460 		val = htole16(val);
2461 		memcpy(response->present_reading, &val, 2);
2462 
2463 	} else if (sensor_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
2464 		   sensor_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
2465 		if (payload_length !=
2466 		    PLDM_GET_SENSOR_READING_MIN_RESP_BYTES + 3) {
2467 			return PLDM_ERROR_INVALID_LENGTH;
2468 		}
2469 		uint32_t val = *(uint32_t *)present_reading;
2470 		val = htole32(val);
2471 		memcpy(response->present_reading, &val, 4);
2472 	}
2473 
2474 	return PLDM_SUCCESS;
2475 }
2476 
2477 LIBPLDM_ABI_STABLE
decode_get_sensor_reading_req(const struct pldm_msg * msg,size_t payload_length,uint16_t * sensor_id,uint8_t * rearm_event_state)2478 int decode_get_sensor_reading_req(const struct pldm_msg *msg,
2479 				  size_t payload_length, uint16_t *sensor_id,
2480 				  uint8_t *rearm_event_state)
2481 {
2482 	PLDM_MSGBUF_DEFINE_P(buf);
2483 	int rc;
2484 
2485 	if (msg == NULL || sensor_id == NULL || rearm_event_state == NULL) {
2486 		return PLDM_ERROR_INVALID_DATA;
2487 	}
2488 
2489 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_SENSOR_READING_REQ_BYTES,
2490 				    msg->payload, payload_length);
2491 	if (rc) {
2492 		return pldm_xlate_errno(rc);
2493 	}
2494 
2495 	pldm_msgbuf_extract_p(buf, sensor_id);
2496 	pldm_msgbuf_extract_p(buf, rearm_event_state);
2497 
2498 	rc = pldm_msgbuf_complete(buf);
2499 	if (rc) {
2500 		return pldm_xlate_errno(rc);
2501 	}
2502 
2503 	return PLDM_SUCCESS;
2504 }
2505 
2506 LIBPLDM_ABI_TESTING
encode_get_event_receiver_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length LIBPLDM_CC_UNUSED)2507 int encode_get_event_receiver_req(uint8_t instance_id, struct pldm_msg *msg,
2508 				  size_t payload_length LIBPLDM_CC_UNUSED)
2509 {
2510 	struct pldm_header_info header;
2511 	header.msg_type = PLDM_REQUEST;
2512 	header.instance = instance_id;
2513 	header.pldm_type = PLDM_PLATFORM;
2514 	header.command = PLDM_GET_EVENT_RECEIVER;
2515 
2516 	if (!msg) {
2517 		return -EINVAL;
2518 	}
2519 
2520 	return pack_pldm_header_errno(&header, &(msg->hdr));
2521 }
2522 
2523 LIBPLDM_ABI_TESTING
encode_get_event_receiver_resp(uint8_t instance_id,struct pldm_get_event_receiver_resp * event_receiver_info,struct pldm_msg * msg,size_t * payload_length)2524 int encode_get_event_receiver_resp(
2525 	uint8_t instance_id,
2526 	struct pldm_get_event_receiver_resp *event_receiver_info,
2527 	struct pldm_msg *msg, size_t *payload_length)
2528 {
2529 	PLDM_MSGBUF_DEFINE_P(buf);
2530 	int rc;
2531 	if (!msg || !event_receiver_info) {
2532 		return -EINVAL;
2533 	}
2534 
2535 	/* See Table 2, DSP0245 v1.4.0 */
2536 	if (event_receiver_info->transport_protocol_type !=
2537 	    PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP) {
2538 		return -ENOTSUP;
2539 	}
2540 
2541 	struct pldm_header_info header = { 0 };
2542 	header.msg_type = PLDM_RESPONSE;
2543 	header.instance = instance_id;
2544 	header.pldm_type = PLDM_PLATFORM;
2545 	header.command = PLDM_GET_EVENT_RECEIVER;
2546 
2547 	rc = pack_pldm_header_errno(&header, &(msg->hdr));
2548 	if (rc) {
2549 		return rc;
2550 	}
2551 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_EVENT_RECEIVER_MIN_RESP_BYTES,
2552 				    msg->payload, *payload_length);
2553 	if (rc) {
2554 		return rc;
2555 	}
2556 
2557 	pldm_msgbuf_insert(buf, event_receiver_info->completion_code);
2558 	pldm_msgbuf_insert(buf, event_receiver_info->transport_protocol_type);
2559 	pldm_msgbuf_insert(
2560 		buf, event_receiver_info->event_receiver_address.mctp_eid);
2561 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2562 }
2563 
2564 LIBPLDM_ABI_STABLE
decode_get_event_receiver_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_event_receiver_resp * resp)2565 int decode_get_event_receiver_resp(const struct pldm_msg *msg,
2566 				   size_t payload_length,
2567 				   struct pldm_get_event_receiver_resp *resp)
2568 {
2569 	PLDM_MSGBUF_DEFINE_P(buf);
2570 	int rc;
2571 	if (!msg) {
2572 		return -EINVAL;
2573 	}
2574 
2575 	rc = pldm_msg_has_error(msg, payload_length);
2576 	if (rc) {
2577 		resp->completion_code = rc;
2578 		return 0;
2579 	}
2580 
2581 	rc = pldm_msgbuf_init_errno(buf, PLDM_GET_EVENT_RECEIVER_MIN_RESP_BYTES,
2582 				    msg->payload, payload_length);
2583 	if (rc) {
2584 		return rc;
2585 	}
2586 	pldm_msgbuf_extract(buf, resp->completion_code);
2587 	rc = pldm_msgbuf_extract(buf, resp->transport_protocol_type);
2588 	if (rc) {
2589 		return pldm_msgbuf_discard(buf, rc);
2590 	}
2591 	if (resp->transport_protocol_type ==
2592 	    PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP) {
2593 		pldm_msgbuf_extract(buf, resp->event_receiver_address.mctp_eid);
2594 	} else {
2595 		return pldm_msgbuf_discard(buf, -ENOTSUP);
2596 	}
2597 	return pldm_msgbuf_complete_consumed(buf);
2598 }
2599 
2600 LIBPLDM_ABI_STABLE
encode_set_event_receiver_req(uint8_t instance_id,uint8_t event_message_global_enable,uint8_t transport_protocol_type,uint8_t event_receiver_address_info,uint16_t heartbeat_timer,struct pldm_msg * msg)2601 int encode_set_event_receiver_req(uint8_t instance_id,
2602 				  uint8_t event_message_global_enable,
2603 				  uint8_t transport_protocol_type,
2604 				  uint8_t event_receiver_address_info,
2605 				  uint16_t heartbeat_timer,
2606 				  struct pldm_msg *msg)
2607 {
2608 	if (msg == NULL) {
2609 		return PLDM_ERROR_INVALID_DATA;
2610 	}
2611 
2612 	if (transport_protocol_type != PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP) {
2613 		return PLDM_ERROR_INVALID_DATA;
2614 	}
2615 
2616 	struct pldm_header_info header = { 0 };
2617 	header.msg_type = PLDM_REQUEST;
2618 	header.instance = instance_id;
2619 	header.pldm_type = PLDM_PLATFORM;
2620 	header.command = PLDM_SET_EVENT_RECEIVER;
2621 
2622 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2623 	if (rc != PLDM_SUCCESS) {
2624 		return rc;
2625 	}
2626 
2627 	struct pldm_set_event_receiver_req *request =
2628 		(struct pldm_set_event_receiver_req *)msg->payload;
2629 	request->event_message_global_enable = event_message_global_enable;
2630 
2631 	request->transport_protocol_type = transport_protocol_type;
2632 	request->event_receiver_address_info = event_receiver_address_info;
2633 
2634 	if (event_message_global_enable ==
2635 	    PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE) {
2636 		if (heartbeat_timer == 0) {
2637 			return PLDM_ERROR_INVALID_DATA;
2638 		}
2639 		request->heartbeat_timer = htole16(heartbeat_timer);
2640 	}
2641 
2642 	return PLDM_SUCCESS;
2643 }
2644 
2645 LIBPLDM_ABI_STABLE
decode_set_event_receiver_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)2646 int decode_set_event_receiver_resp(const struct pldm_msg *msg,
2647 				   size_t payload_length,
2648 				   uint8_t *completion_code)
2649 {
2650 	PLDM_MSGBUF_DEFINE_P(buf);
2651 	int rc;
2652 
2653 	if (msg == NULL || completion_code == NULL) {
2654 		return PLDM_ERROR_INVALID_DATA;
2655 	}
2656 
2657 	rc = pldm_msgbuf_init_errno(buf, PLDM_SET_EVENT_RECEIVER_RESP_BYTES,
2658 				    msg->payload, payload_length);
2659 	if (rc) {
2660 		return pldm_xlate_errno(rc);
2661 	}
2662 
2663 	pldm_msgbuf_extract_p(buf, completion_code);
2664 
2665 	rc = pldm_msgbuf_complete(buf);
2666 	if (rc) {
2667 		return pldm_xlate_errno(rc);
2668 	}
2669 
2670 	return PLDM_SUCCESS;
2671 }
2672 
2673 LIBPLDM_ABI_STABLE
decode_set_event_receiver_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * event_message_global_enable,uint8_t * transport_protocol_type,uint8_t * event_receiver_address_info,uint16_t * heartbeat_timer)2674 int decode_set_event_receiver_req(const struct pldm_msg *msg,
2675 				  size_t payload_length,
2676 				  uint8_t *event_message_global_enable,
2677 				  uint8_t *transport_protocol_type,
2678 				  uint8_t *event_receiver_address_info,
2679 				  uint16_t *heartbeat_timer)
2680 
2681 {
2682 	PLDM_MSGBUF_DEFINE_P(buf);
2683 	int rc;
2684 
2685 	if (msg == NULL || event_message_global_enable == NULL ||
2686 	    transport_protocol_type == NULL ||
2687 	    event_receiver_address_info == NULL || heartbeat_timer == NULL) {
2688 		return PLDM_ERROR_INVALID_DATA;
2689 	}
2690 
2691 	rc = pldm_msgbuf_init_errno(buf, PLDM_SET_EVENT_RECEIVER_MIN_REQ_BYTES,
2692 				    msg->payload, payload_length);
2693 	if (rc) {
2694 		return pldm_xlate_errno(rc);
2695 	}
2696 
2697 	pldm_msgbuf_extract_p(buf, event_message_global_enable);
2698 	if (rc) {
2699 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2700 	}
2701 
2702 	pldm_msgbuf_extract_p(buf, transport_protocol_type);
2703 	pldm_msgbuf_extract_p(buf, event_receiver_address_info);
2704 	if (*event_message_global_enable ==
2705 	    PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE) {
2706 		pldm_msgbuf_extract_p(buf, heartbeat_timer);
2707 	}
2708 
2709 	rc = pldm_msgbuf_complete(buf);
2710 	if (rc) {
2711 		return pldm_xlate_errno(rc);
2712 	}
2713 
2714 	if ((*event_message_global_enable ==
2715 	     PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE) &&
2716 	    (*heartbeat_timer == 0)) {
2717 		return PLDM_ERROR_INVALID_DATA;
2718 	}
2719 
2720 	return PLDM_SUCCESS;
2721 }
2722 
2723 LIBPLDM_ABI_STABLE
encode_set_event_receiver_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg)2724 int encode_set_event_receiver_resp(uint8_t instance_id, uint8_t completion_code,
2725 				   struct pldm_msg *msg)
2726 
2727 {
2728 	if (msg == NULL) {
2729 		return PLDM_ERROR_INVALID_DATA;
2730 	}
2731 
2732 	struct pldm_header_info header = { 0 };
2733 	header.instance = instance_id;
2734 	header.msg_type = PLDM_RESPONSE;
2735 	header.pldm_type = PLDM_PLATFORM;
2736 	header.command = PLDM_SET_EVENT_RECEIVER;
2737 
2738 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2739 	if (rc != PLDM_SUCCESS) {
2740 		return rc;
2741 	}
2742 
2743 	msg->payload[0] = completion_code;
2744 
2745 	return PLDM_SUCCESS;
2746 }
2747 
2748 LIBPLDM_ABI_STABLE
encode_poll_for_platform_event_message_req(uint8_t instance_id,uint8_t format_version,uint8_t transfer_operation_flag,uint32_t data_transfer_handle,uint16_t event_id_to_acknowledge,struct pldm_msg * msg,size_t payload_length)2749 int encode_poll_for_platform_event_message_req(uint8_t instance_id,
2750 					       uint8_t format_version,
2751 					       uint8_t transfer_operation_flag,
2752 					       uint32_t data_transfer_handle,
2753 					       uint16_t event_id_to_acknowledge,
2754 					       struct pldm_msg *msg,
2755 					       size_t payload_length)
2756 {
2757 	PLDM_MSGBUF_DEFINE_P(buf);
2758 	int rc;
2759 
2760 	if (msg == NULL) {
2761 		return PLDM_ERROR_INVALID_DATA;
2762 	}
2763 
2764 	rc = pldm_platform_poll_for_platform_event_message_validate(
2765 		transfer_operation_flag, event_id_to_acknowledge);
2766 	if (rc < 0) {
2767 		return PLDM_ERROR_INVALID_DATA;
2768 	}
2769 
2770 	struct pldm_header_info header = { 0 };
2771 	header.msg_type = PLDM_REQUEST;
2772 	header.instance = instance_id;
2773 	header.pldm_type = PLDM_PLATFORM;
2774 	header.command = PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE;
2775 
2776 	rc = pack_pldm_header(&header, &(msg->hdr));
2777 	if (rc != PLDM_SUCCESS) {
2778 		return rc;
2779 	}
2780 
2781 	rc = pldm_msgbuf_init_errno(
2782 		buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
2783 		msg->payload, payload_length);
2784 	if (rc) {
2785 		return pldm_xlate_errno(rc);
2786 	}
2787 
2788 	pldm_msgbuf_insert(buf, format_version);
2789 	pldm_msgbuf_insert(buf, transfer_operation_flag);
2790 	pldm_msgbuf_insert(buf, data_transfer_handle);
2791 	pldm_msgbuf_insert(buf, event_id_to_acknowledge);
2792 
2793 	rc = pldm_msgbuf_complete(buf);
2794 	if (rc) {
2795 		return pldm_xlate_errno(rc);
2796 	}
2797 
2798 	return PLDM_SUCCESS;
2799 }
2800 
2801 LIBPLDM_ABI_STABLE
decode_poll_for_platform_event_message_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * tid,uint16_t * event_id,uint32_t * next_data_transfer_handle,uint8_t * transfer_flag,uint8_t * event_class,uint32_t * event_data_size,void ** event_data,uint32_t * event_data_integrity_checksum)2802 int decode_poll_for_platform_event_message_resp(
2803 	const struct pldm_msg *msg, size_t payload_length,
2804 	uint8_t *completion_code, uint8_t *tid, uint16_t *event_id,
2805 	uint32_t *next_data_transfer_handle, uint8_t *transfer_flag,
2806 	uint8_t *event_class, uint32_t *event_data_size, void **event_data,
2807 	uint32_t *event_data_integrity_checksum)
2808 {
2809 	PLDM_MSGBUF_DEFINE_P(buf);
2810 	int rc;
2811 
2812 	if (msg == NULL || completion_code == NULL || tid == NULL ||
2813 	    event_id == NULL || next_data_transfer_handle == NULL ||
2814 	    transfer_flag == NULL || event_class == NULL ||
2815 	    event_data_size == NULL || event_data == NULL ||
2816 	    event_data_integrity_checksum == NULL) {
2817 		return PLDM_ERROR_INVALID_DATA;
2818 	}
2819 
2820 	rc = pldm_msgbuf_init_errno(
2821 		buf, PLDM_POLL_FOR_PLATFORM_EVENT_MESSAGE_MIN_RESP_BYTES,
2822 		msg->payload, payload_length);
2823 	if (rc) {
2824 		return pldm_xlate_errno(rc);
2825 	}
2826 
2827 	rc = pldm_msgbuf_extract_p(buf, completion_code);
2828 	if (rc) {
2829 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2830 	}
2831 	if (PLDM_SUCCESS != *completion_code) {
2832 		return pldm_msgbuf_discard(buf, *completion_code);
2833 	}
2834 
2835 	pldm_msgbuf_extract_p(buf, tid);
2836 	rc = pldm_msgbuf_extract_p(buf, event_id);
2837 	if (rc) {
2838 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2839 	}
2840 	if ((*event_id == 0) || (*event_id == 0xffff)) {
2841 		return pldm_msgbuf_discard(buf, PLDM_SUCCESS);
2842 	}
2843 
2844 	pldm_msgbuf_extract_p(buf, next_data_transfer_handle);
2845 	rc = pldm_msgbuf_extract_p(buf, transfer_flag);
2846 	if (rc) {
2847 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2848 	}
2849 
2850 	pldm_msgbuf_extract_p(buf, event_class);
2851 	rc = pldm_msgbuf_extract_p(buf, event_data_size);
2852 	if (rc) {
2853 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2854 	}
2855 	if (*event_data_size > payload_length) {
2856 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
2857 	}
2858 
2859 	if (*event_data_size > 0) {
2860 		pldm_msgbuf_span_required(buf, *event_data_size, event_data);
2861 	}
2862 
2863 	if (*transfer_flag == PLDM_END ||
2864 	    *transfer_flag == PLDM_START_AND_END) {
2865 		pldm_msgbuf_extract_p(buf, event_data_integrity_checksum);
2866 	}
2867 
2868 	rc = pldm_msgbuf_complete_consumed(buf);
2869 	if (rc) {
2870 		return pldm_xlate_errno(rc);
2871 	}
2872 
2873 	return PLDM_SUCCESS;
2874 }
2875 
2876 LIBPLDM_ABI_TESTING
decode_numeric_effecter_pdr_data(const void * pdr_data,size_t pdr_data_length,struct pldm_numeric_effecter_value_pdr * pdr_value)2877 int decode_numeric_effecter_pdr_data(
2878 	const void *pdr_data, size_t pdr_data_length,
2879 	struct pldm_numeric_effecter_value_pdr *pdr_value)
2880 {
2881 	PLDM_MSGBUF_DEFINE_P(buf);
2882 	struct pldm_value_pdr_hdr hdr;
2883 	int rc;
2884 
2885 	if (!pdr_data || !pdr_value) {
2886 		return PLDM_ERROR_INVALID_DATA;
2887 	}
2888 
2889 	rc = pldm_msgbuf_init_errno(buf,
2890 				    PLDM_PDR_NUMERIC_EFFECTER_PDR_MIN_LENGTH,
2891 				    pdr_data, pdr_data_length);
2892 	if (rc) {
2893 		return pldm_xlate_errno(rc);
2894 	}
2895 
2896 	rc = pldm_msgbuf_extract_value_pdr_hdr(
2897 		buf, &hdr, PLDM_PDR_NUMERIC_EFFECTER_PDR_MIN_LENGTH,
2898 		pdr_data_length);
2899 	if (rc) {
2900 		return pldm_xlate_errno(rc);
2901 	}
2902 
2903 	memcpy(&pdr_value->hdr, &hdr, sizeof(hdr));
2904 
2905 	pldm_msgbuf_extract(buf, pdr_value->terminus_handle);
2906 	pldm_msgbuf_extract(buf, pdr_value->effecter_id);
2907 	pldm_msgbuf_extract(buf, pdr_value->entity_type);
2908 	pldm_msgbuf_extract(buf, pdr_value->entity_instance);
2909 	pldm_msgbuf_extract(buf, pdr_value->container_id);
2910 	pldm_msgbuf_extract(buf, pdr_value->effecter_semantic_id);
2911 	pldm_msgbuf_extract(buf, pdr_value->effecter_init);
2912 	pldm_msgbuf_extract(buf, pdr_value->effecter_auxiliary_names);
2913 	pldm_msgbuf_extract(buf, pdr_value->base_unit);
2914 	pldm_msgbuf_extract(buf, pdr_value->unit_modifier);
2915 	pldm_msgbuf_extract(buf, pdr_value->rate_unit);
2916 	pldm_msgbuf_extract(buf, pdr_value->base_oem_unit_handle);
2917 	pldm_msgbuf_extract(buf, pdr_value->aux_unit);
2918 	pldm_msgbuf_extract(buf, pdr_value->aux_unit_modifier);
2919 	pldm_msgbuf_extract(buf, pdr_value->aux_rate_unit);
2920 	pldm_msgbuf_extract(buf, pdr_value->aux_oem_unit_handle);
2921 	pldm_msgbuf_extract(buf, pdr_value->is_linear);
2922 
2923 	rc = pldm_msgbuf_extract(buf, pdr_value->effecter_data_size);
2924 	if (rc) {
2925 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2926 	}
2927 	if (pdr_value->effecter_data_size > PLDM_SENSOR_DATA_SIZE_MAX) {
2928 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
2929 	}
2930 
2931 	pldm_msgbuf_extract(buf, pdr_value->resolution);
2932 	pldm_msgbuf_extract(buf, pdr_value->offset);
2933 	pldm_msgbuf_extract(buf, pdr_value->accuracy);
2934 	pldm_msgbuf_extract(buf, pdr_value->plus_tolerance);
2935 	pldm_msgbuf_extract(buf, pdr_value->minus_tolerance);
2936 	pldm_msgbuf_extract(buf, pdr_value->state_transition_interval);
2937 	pldm_msgbuf_extract(buf, pdr_value->transition_interval);
2938 	pldm_msgbuf_extract_effecter_data(buf, pdr_value->effecter_data_size,
2939 					  pdr_value->max_settable);
2940 	pldm_msgbuf_extract_effecter_data(buf, pdr_value->effecter_data_size,
2941 					  pdr_value->min_settable);
2942 
2943 	rc = pldm_msgbuf_extract(buf, pdr_value->range_field_format);
2944 	if (rc) {
2945 		return pldm_xlate_errno(pldm_msgbuf_discard(buf, rc));
2946 	}
2947 	if (pdr_value->range_field_format > PLDM_RANGE_FIELD_FORMAT_MAX) {
2948 		return pldm_msgbuf_discard(buf, PLDM_ERROR_INVALID_DATA);
2949 	}
2950 
2951 	pldm_msgbuf_extract(buf, pdr_value->range_field_support.byte);
2952 	pldm_msgbuf_extract_range_field_format(
2953 		buf, pdr_value->range_field_format, pdr_value->nominal_value);
2954 	pldm_msgbuf_extract_range_field_format(
2955 		buf, pdr_value->range_field_format, pdr_value->normal_max);
2956 	pldm_msgbuf_extract_range_field_format(
2957 		buf, pdr_value->range_field_format, pdr_value->normal_min);
2958 	pldm_msgbuf_extract_range_field_format(
2959 		buf, pdr_value->range_field_format, pdr_value->rated_max);
2960 	pldm_msgbuf_extract_range_field_format(
2961 		buf, pdr_value->range_field_format, pdr_value->rated_min);
2962 
2963 	rc = pldm_msgbuf_complete_consumed(buf);
2964 	if (rc) {
2965 		return pldm_xlate_errno(rc);
2966 	}
2967 
2968 	return PLDM_SUCCESS;
2969 }
2970 
2971 LIBPLDM_ABI_STABLE
encode_get_state_effecter_states_req(uint8_t instance_id,uint16_t effecter_id,struct pldm_msg * msg,size_t payload_length)2972 int encode_get_state_effecter_states_req(uint8_t instance_id,
2973 					 uint16_t effecter_id,
2974 					 struct pldm_msg *msg,
2975 					 size_t payload_length)
2976 {
2977 	PLDM_MSGBUF_DEFINE_P(buf);
2978 	int rc;
2979 
2980 	if (msg == NULL) {
2981 		return -EINVAL;
2982 	}
2983 
2984 	struct pldm_header_info header = { 0 };
2985 	header.msg_type = PLDM_REQUEST;
2986 	header.instance = instance_id;
2987 	header.pldm_type = PLDM_PLATFORM;
2988 	header.command = PLDM_GET_STATE_EFFECTER_STATES;
2989 
2990 	rc = pack_pldm_header_errno(&header, &msg->hdr);
2991 	if (rc < 0) {
2992 		return rc;
2993 	}
2994 
2995 	rc = pldm_msgbuf_init_errno(buf,
2996 				    PLDM_GET_STATE_EFFECTER_STATES_REQ_BYTES,
2997 				    msg->payload, payload_length);
2998 	if (rc) {
2999 		return rc;
3000 	}
3001 
3002 	pldm_msgbuf_insert(buf, effecter_id);
3003 
3004 	return pldm_msgbuf_complete_consumed(buf);
3005 }
3006 
3007 LIBPLDM_ABI_STABLE
decode_get_state_effecter_states_req(const struct pldm_msg * msg,size_t payload_length,uint16_t * effecter_id)3008 int decode_get_state_effecter_states_req(const struct pldm_msg *msg,
3009 					 size_t payload_length,
3010 					 uint16_t *effecter_id)
3011 {
3012 	PLDM_MSGBUF_DEFINE_P(buf);
3013 	int rc;
3014 
3015 	if (msg == NULL || effecter_id == NULL) {
3016 		return -EINVAL;
3017 	}
3018 
3019 	rc = pldm_msgbuf_init_errno(
3020 		buf, PLDM_GET_STATE_EFFECTER_STATES_MIN_RESP_BYTES,
3021 		msg->payload, payload_length);
3022 	if (rc) {
3023 		return rc;
3024 	}
3025 
3026 	pldm_msgbuf_extract_p(buf, effecter_id);
3027 
3028 	return pldm_msgbuf_complete_consumed(buf);
3029 }
3030 
3031 LIBPLDM_ABI_STABLE
decode_get_state_effecter_states_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_state_effecter_states_resp * resp)3032 int decode_get_state_effecter_states_resp(
3033 	const struct pldm_msg *msg, size_t payload_length,
3034 	struct pldm_get_state_effecter_states_resp *resp)
3035 {
3036 	PLDM_MSGBUF_DEFINE_P(buf);
3037 	get_effecter_state_field *field;
3038 	int rc;
3039 	int i;
3040 
3041 	if (msg == NULL || resp == NULL) {
3042 		return -EINVAL;
3043 	}
3044 
3045 	rc = pldm_msgbuf_init_errno(
3046 		buf, PLDM_GET_STATE_EFFECTER_STATES_MIN_RESP_BYTES,
3047 		msg->payload, payload_length);
3048 	if (rc) {
3049 		return rc;
3050 	}
3051 
3052 	rc = pldm_msgbuf_extract(buf, resp->completion_code);
3053 	if (rc) {
3054 		return pldm_msgbuf_discard(buf, rc);
3055 	}
3056 
3057 	if (PLDM_SUCCESS != resp->completion_code) {
3058 		return pldm_msgbuf_complete(buf);
3059 	}
3060 
3061 	rc = pldm_msgbuf_extract(buf, resp->comp_effecter_count);
3062 	if (rc) {
3063 		return pldm_msgbuf_discard(buf, rc);
3064 	}
3065 
3066 	uint8_t comp_effecter_count = resp->comp_effecter_count;
3067 
3068 	if (comp_effecter_count < PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MIN ||
3069 	    comp_effecter_count > PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MAX) {
3070 		return pldm_msgbuf_discard(buf, -EBADMSG);
3071 	}
3072 
3073 	for (i = 0, field = resp->field; i < comp_effecter_count;
3074 	     i++, field++) {
3075 		pldm_msgbuf_extract(buf, field->effecter_op_state);
3076 		pldm_msgbuf_extract(buf, field->pending_state);
3077 		pldm_msgbuf_extract(buf, field->present_state);
3078 	}
3079 
3080 	return pldm_msgbuf_complete_consumed(buf);
3081 }
3082 
3083 LIBPLDM_ABI_STABLE
encode_get_state_effecter_states_resp(uint8_t instance_id,struct pldm_get_state_effecter_states_resp * resp,struct pldm_msg * msg,size_t payload_length)3084 int encode_get_state_effecter_states_resp(
3085 	uint8_t instance_id, struct pldm_get_state_effecter_states_resp *resp,
3086 	struct pldm_msg *msg, size_t payload_length)
3087 {
3088 	PLDM_MSGBUF_DEFINE_P(buf);
3089 	get_effecter_state_field *field;
3090 	int rc;
3091 	int i;
3092 
3093 	if (msg == NULL || resp == NULL) {
3094 		return -EINVAL;
3095 	}
3096 
3097 	uint8_t comp_effecter_count = resp->comp_effecter_count;
3098 
3099 	if (comp_effecter_count < PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MIN ||
3100 	    comp_effecter_count > PLDM_GET_EFFECTER_STATE_FIELD_COUNT_MAX) {
3101 		return -EBADMSG;
3102 	}
3103 
3104 	struct pldm_header_info header = { 0 };
3105 	header.msg_type = PLDM_RESPONSE;
3106 	header.instance = instance_id;
3107 	header.pldm_type = PLDM_PLATFORM;
3108 	header.command = PLDM_GET_STATE_EFFECTER_STATES;
3109 
3110 	rc = pack_pldm_header_errno(&header, &msg->hdr);
3111 	if (rc < 0) {
3112 		return rc;
3113 	}
3114 
3115 	rc = pldm_msgbuf_init_errno(
3116 		buf, PLDM_GET_STATE_EFFECTER_STATES_MIN_RESP_BYTES,
3117 		msg->payload, payload_length);
3118 	if (rc) {
3119 		return rc;
3120 	}
3121 
3122 	pldm_msgbuf_insert(buf, resp->completion_code);
3123 	pldm_msgbuf_insert(buf, comp_effecter_count);
3124 
3125 	for (i = 0, field = resp->field; i < comp_effecter_count;
3126 	     i++, field++) {
3127 		pldm_msgbuf_insert(buf, field->effecter_op_state);
3128 		pldm_msgbuf_insert(buf, field->pending_state);
3129 		pldm_msgbuf_insert(buf, field->present_state);
3130 	}
3131 
3132 	return pldm_msgbuf_complete_consumed(buf);
3133 }
3134 
3135 LIBPLDM_ABI_STABLE
decode_entity_auxiliary_names_pdr(const void * data,size_t data_length,struct pldm_entity_auxiliary_names_pdr * pdr,size_t pdr_length)3136 int decode_entity_auxiliary_names_pdr(
3137 	const void *data, size_t data_length,
3138 	struct pldm_entity_auxiliary_names_pdr *pdr, size_t pdr_length)
3139 {
3140 	PLDM_MSGBUF_DEFINE_P(buf);
3141 	PLDM_MSGBUF_DEFINE_P(src);
3142 	PLDM_MSGBUF_DEFINE_P(dst);
3143 	size_t names_len = 0;
3144 	void *names = NULL;
3145 	int rc;
3146 	int i;
3147 
3148 	if (!data || !pdr) {
3149 		return -EINVAL;
3150 	}
3151 
3152 	/*
3153 	 * Alignment of auxiliary_name_data is an invariant as we statically assert
3154 	 * its behaviour in the header.
3155 	 */
3156 	assert(!((uintptr_t)pdr->auxiliary_name_data &
3157 		 (alignof(pldm_utf16be) - 1)));
3158 
3159 	/* Reject any lengths that are obviously invalid */
3160 	if (pdr_length < data_length || pdr_length < sizeof(*pdr)) {
3161 		return -EINVAL;
3162 	}
3163 
3164 	rc = pldm_msgbuf_init_errno(
3165 		buf, PLDM_PDR_ENTITY_AUXILIARY_NAME_PDR_MIN_LENGTH, data,
3166 		data_length);
3167 	if (rc) {
3168 		return rc;
3169 	}
3170 
3171 	rc = pldm_msgbuf_extract_value_pdr_hdr(
3172 		buf, &pdr->hdr, PLDM_PDR_ENTITY_AUXILIARY_NAME_PDR_MIN_LENGTH,
3173 		data_length);
3174 	if (rc) {
3175 		return pldm_msgbuf_discard(buf, rc);
3176 	}
3177 
3178 	pldm_msgbuf_extract(buf, pdr->container.entity_type);
3179 	pldm_msgbuf_extract(buf, pdr->container.entity_instance_num);
3180 	pldm_msgbuf_extract(buf, pdr->container.entity_container_id);
3181 	pldm_msgbuf_extract(buf, pdr->shared_name_count);
3182 	rc = pldm_msgbuf_extract(buf, pdr->name_string_count);
3183 	if (rc < 0) {
3184 		return pldm_msgbuf_discard(buf, rc);
3185 	}
3186 
3187 	rc = pldm_msgbuf_span_remaining(buf, &names, &names_len);
3188 	if (rc < 0) {
3189 		return rc;
3190 	}
3191 	assert(names);
3192 
3193 	rc = pldm_msgbuf_complete_consumed(buf);
3194 	if (rc) {
3195 		return rc;
3196 	}
3197 
3198 	pdr->auxiliary_name_data_size = pdr_length - sizeof(*pdr);
3199 
3200 	rc = pldm_msgbuf_init_errno(dst, pdr->auxiliary_name_data_size,
3201 				    pdr->auxiliary_name_data,
3202 				    pdr->auxiliary_name_data_size);
3203 	if (rc < 0) {
3204 		return rc;
3205 	}
3206 
3207 	/*
3208 	 * Below we do two passes over the same region. This is to first pack the
3209 	 * UTF16-BE strings into auxiliary_name_data, followed by the ASCII strings,
3210 	 * to maintain appropriate alignment.
3211 	 */
3212 
3213 	/* Initialise for the first pass to extract the UTF16-BE name strings */
3214 	rc = pldm_msgbuf_init_errno(src, names_len, names, names_len);
3215 	if (rc < 0) {
3216 		goto cleanup_msgbuf_dst;
3217 	}
3218 
3219 	for (i = 0; i < pdr->name_string_count; i++) {
3220 		pldm_msgbuf_span_string_ascii(src, NULL, NULL);
3221 		rc = pldm_msgbuf_copy_string_utf16(dst, src);
3222 		if (rc) {
3223 			goto cleanup_msgbuf_src;
3224 		}
3225 	}
3226 
3227 	rc = pldm_msgbuf_complete_consumed(src);
3228 	if (rc < 0) {
3229 		goto cleanup_msgbuf_dst;
3230 	}
3231 
3232 	/* Reinitialise for the second pass to extract the ASCII tag strings */
3233 	rc = pldm_msgbuf_init_errno(src, names_len, names, names_len);
3234 	if (rc < 0) {
3235 		goto cleanup_msgbuf_dst;
3236 	}
3237 
3238 	for (i = 0; i < pdr->name_string_count; i++) {
3239 		rc = pldm_msgbuf_copy_string_ascii(dst, src);
3240 		if (rc) {
3241 			goto cleanup_msgbuf_src;
3242 		}
3243 		pldm_msgbuf_span_string_utf16(src, NULL, NULL);
3244 	}
3245 
3246 	rc = pldm_msgbuf_complete(src);
3247 	if (rc) {
3248 		goto cleanup_msgbuf_dst;
3249 	}
3250 
3251 	return pldm_msgbuf_complete(dst);
3252 
3253 cleanup_msgbuf_src:
3254 	rc = pldm_msgbuf_discard(src, rc);
3255 cleanup_msgbuf_dst:
3256 	return pldm_msgbuf_discard(dst, rc);
3257 }
3258 
3259 LIBPLDM_ABI_STABLE
decode_pldm_entity_auxiliary_names_pdr_index(struct pldm_entity_auxiliary_names_pdr * pdr)3260 int decode_pldm_entity_auxiliary_names_pdr_index(
3261 	struct pldm_entity_auxiliary_names_pdr *pdr)
3262 {
3263 	PLDM_MSGBUF_DEFINE_P(buf);
3264 	int rc;
3265 	int i;
3266 
3267 	if (!pdr) {
3268 		return -EINVAL;
3269 	}
3270 
3271 	if (pdr->name_string_count == 0 && pdr->names) {
3272 		return -EINVAL;
3273 	}
3274 
3275 	if (pdr->name_string_count > 0 && !pdr->names) {
3276 		return -EINVAL;
3277 	}
3278 
3279 	if (pdr->name_string_count == 0) {
3280 		return 0;
3281 	}
3282 
3283 	/*
3284 	 * Minimum size is one NUL for each member of each entry
3285 	 *
3286 	 * Note that the definition of nameLanguageTag in DSP0248 v1.2.2
3287 	 * states the following:
3288 	 *
3289 	 * > A null-terminated ISO646 ASCII string ...
3290 	 * >
3291 	 * > special value: null string = 0x0000 = unspecified.
3292 	 *
3293 	 * Until proven otherwise we will assume the "0x0000" is a
3294 	 * misrepresentation of an ASCII NUL, and that ASCII NUL is
3295 	 * represented by a single byte.
3296 	 */
3297 	rc = pldm_msgbuf_init_errno(
3298 		buf, pdr->name_string_count * (sizeof(char) + sizeof(char16_t)),
3299 		pdr->auxiliary_name_data, pdr->auxiliary_name_data_size);
3300 	if (rc) {
3301 		return rc;
3302 	}
3303 
3304 	for (i = 0; i < pdr->name_string_count; i++) {
3305 		void *loc = NULL;
3306 		pldm_msgbuf_span_string_utf16(buf, &loc, NULL);
3307 		pdr->names[i].name = loc;
3308 	}
3309 
3310 	for (i = 0; i < pdr->name_string_count; i++) {
3311 		void *loc = NULL;
3312 		pldm_msgbuf_span_string_ascii(buf, &loc, NULL);
3313 		pdr->names[i].tag = loc;
3314 	}
3315 
3316 	return pldm_msgbuf_complete_consumed(buf);
3317 }
3318 
3319 LIBPLDM_ABI_STABLE
decode_pldm_platform_cper_event(const void * event_data,size_t event_data_length,struct pldm_platform_cper_event * cper_event,size_t cper_event_length)3320 int decode_pldm_platform_cper_event(const void *event_data,
3321 				    size_t event_data_length,
3322 				    struct pldm_platform_cper_event *cper_event,
3323 				    size_t cper_event_length)
3324 {
3325 	PLDM_MSGBUF_DEFINE_P(buf);
3326 	int rc;
3327 
3328 	if (!cper_event || !event_data) {
3329 		return -EINVAL;
3330 	}
3331 
3332 	if (cper_event_length < sizeof(*cper_event)) {
3333 		return -EINVAL;
3334 	}
3335 
3336 	rc = pldm_msgbuf_init_errno(buf, PLDM_PLATFORM_CPER_EVENT_MIN_LENGTH,
3337 				    event_data, event_data_length);
3338 	if (rc) {
3339 		return rc;
3340 	}
3341 
3342 	pldm_msgbuf_extract(buf, cper_event->format_version);
3343 	rc = pldm_msgbuf_extract(buf, cper_event->format_type);
3344 	if (rc) {
3345 		return pldm_msgbuf_discard(buf, rc);
3346 	}
3347 	if (cper_event->format_type != PLDM_PLATFORM_CPER_EVENT_WITH_HEADER &&
3348 	    cper_event->format_type !=
3349 		    PLDM_PLATFORM_CPER_EVENT_WITHOUT_HEADER) {
3350 		return pldm_msgbuf_discard(buf, -EPROTO);
3351 	}
3352 
3353 	rc = pldm_msgbuf_extract(buf, cper_event->event_data_length);
3354 	if (rc) {
3355 		return pldm_msgbuf_discard(buf, rc);
3356 	}
3357 
3358 	if (cper_event->event_data_length >
3359 	    (cper_event_length - sizeof(*cper_event))) {
3360 		return pldm_msgbuf_discard(buf, -EOVERFLOW);
3361 	}
3362 
3363 	rc = pldm_msgbuf_extract_array_uint8(
3364 		buf, cper_event->event_data_length, cper_event->event_data,
3365 		cper_event_length - sizeof(*cper_event));
3366 	if (rc) {
3367 		return pldm_msgbuf_discard(buf, rc);
3368 	}
3369 
3370 	return pldm_msgbuf_complete_consumed(buf);
3371 }
3372 
3373 LIBPLDM_ABI_STABLE
3374 uint8_t *
pldm_platform_cper_event_event_data(struct pldm_platform_cper_event * event)3375 pldm_platform_cper_event_event_data(struct pldm_platform_cper_event *event)
3376 {
3377 	return event->event_data;
3378 }
3379 
3380 LIBPLDM_ABI_TESTING
decode_pldm_file_descriptor_pdr(const void * data,size_t data_length,struct pldm_file_descriptor_pdr * pdr)3381 int decode_pldm_file_descriptor_pdr(const void *data, size_t data_length,
3382 				    struct pldm_file_descriptor_pdr *pdr)
3383 {
3384 	PLDM_MSGBUF_DEFINE_P(buf);
3385 	int rc;
3386 
3387 	if (!data || !pdr) {
3388 		return -EINVAL;
3389 	}
3390 
3391 	rc = pldm_msgbuf_init_errno(buf,
3392 				    PLDM_PDR_FILE_DESCRIPTOR_PDR_MIN_LENGTH,
3393 				    data, data_length);
3394 	if (rc) {
3395 		return rc;
3396 	}
3397 
3398 	rc = pldm_msgbuf_extract_value_pdr_hdr(
3399 		buf, &pdr->hdr, PLDM_PDR_FILE_DESCRIPTOR_PDR_MIN_LENGTH,
3400 		data_length);
3401 	if (rc) {
3402 		return pldm_msgbuf_discard(buf, rc);
3403 	}
3404 
3405 	pldm_msgbuf_extract(buf, pdr->terminus_handle);
3406 	pldm_msgbuf_extract(buf, pdr->file_identifier);
3407 	pldm_msgbuf_extract(buf, pdr->container.entity_type);
3408 	pldm_msgbuf_extract(buf, pdr->container.entity_instance_num);
3409 	pldm_msgbuf_extract(buf, pdr->container.entity_container_id);
3410 	pldm_msgbuf_extract(buf, pdr->superior_directory_file_identifier);
3411 	pldm_msgbuf_extract(buf, pdr->file_classification);
3412 	pldm_msgbuf_extract(buf, pdr->oem_file_classification);
3413 	pldm_msgbuf_extract(buf, pdr->file_capabilities.value);
3414 	pldm_msgbuf_extract(buf, pdr->file_version.alpha);
3415 	pldm_msgbuf_extract(buf, pdr->file_version.update);
3416 	pldm_msgbuf_extract(buf, pdr->file_version.minor);
3417 	pldm_msgbuf_extract(buf, pdr->file_version.major);
3418 	pldm_msgbuf_extract(buf, pdr->file_maximum_size);
3419 	pldm_msgbuf_extract(buf, pdr->file_maximum_file_descriptor_count);
3420 	rc = pldm_msgbuf_extract_uint8_to_size(buf, pdr->file_name.length);
3421 	if (rc) {
3422 		return pldm_msgbuf_discard(buf, rc);
3423 	}
3424 
3425 	pldm_msgbuf_span_required(buf, pdr->file_name.length,
3426 				  (void **)&pdr->file_name.ptr);
3427 
3428 	pdr->oem_file_classification_name.length = 0;
3429 
3430 	if (pdr->oem_file_classification) {
3431 		rc = pldm_msgbuf_extract_uint8_to_size(
3432 			buf, pdr->oem_file_classification_name.length);
3433 		if (rc) {
3434 			return pldm_msgbuf_discard(buf, rc);
3435 		}
3436 
3437 		pldm_msgbuf_span_required(
3438 			buf, pdr->oem_file_classification_name.length,
3439 			(void **)&pdr->oem_file_classification_name.ptr);
3440 	}
3441 
3442 	return pldm_msgbuf_complete_consumed(buf);
3443 }
3444