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