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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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_HEARTBEAT_TIMER_ELAPSED_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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 3097 pldm_platform_cper_event_event_data(struct pldm_platform_cper_event *event) 3098 { 3099 return event->event_data; 3100 } 3101