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