1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 #include "api.h" 3 #include "dsp/base.h" 4 #include "msgbuf.h" 5 6 #include <assert.h> 7 #include <libpldm/base.h> 8 #include <libpldm/pldm_types.h> 9 10 #include <endian.h> 11 #include <errno.h> 12 #include <stdint.h> 13 #include <string.h> 14 15 int pack_pldm_header_errno(const struct pldm_header_info *hdr, 16 struct pldm_msg_hdr *msg) 17 { 18 if (msg == NULL || hdr == NULL) { 19 return -EINVAL; 20 } 21 22 if (hdr->msg_type != PLDM_RESPONSE && hdr->msg_type != PLDM_REQUEST && 23 hdr->msg_type != PLDM_ASYNC_REQUEST_NOTIFY) { 24 return -EINVAL; 25 } 26 27 if (hdr->instance > PLDM_INSTANCE_MAX) { 28 return -EINVAL; 29 } 30 31 if (hdr->pldm_type > (PLDM_MAX_TYPES - 1)) { 32 return -ENOMSG; 33 } 34 35 uint8_t datagram = (hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) ? 1 : 0; 36 37 if (hdr->msg_type == PLDM_RESPONSE) { 38 msg->request = PLDM_RESPONSE; 39 } else if (hdr->msg_type == PLDM_REQUEST || 40 hdr->msg_type == PLDM_ASYNC_REQUEST_NOTIFY) { 41 msg->request = PLDM_REQUEST; 42 } 43 msg->datagram = datagram; 44 msg->reserved = 0; 45 msg->instance_id = hdr->instance; 46 msg->header_ver = PLDM_CURRENT_VERSION; 47 msg->type = hdr->pldm_type; 48 msg->command = hdr->command; 49 50 return 0; 51 } 52 53 int unpack_pldm_header_errno(const struct pldm_msg_hdr *msg, 54 struct pldm_header_info *hdr) 55 { 56 if (msg == NULL) { 57 return -EINVAL; 58 } 59 60 if (msg->request == PLDM_RESPONSE) { 61 hdr->msg_type = PLDM_RESPONSE; 62 } else { 63 hdr->msg_type = msg->datagram ? PLDM_ASYNC_REQUEST_NOTIFY : 64 PLDM_REQUEST; 65 } 66 67 hdr->instance = msg->instance_id; 68 hdr->pldm_type = msg->type; 69 hdr->command = msg->command; 70 71 return 0; 72 } 73 74 LIBPLDM_ABI_STABLE 75 uint8_t pack_pldm_header(const struct pldm_header_info *hdr, 76 struct pldm_msg_hdr *msg) 77 { 78 enum pldm_completion_codes cc; 79 int rc; 80 81 rc = pack_pldm_header_errno(hdr, msg); 82 if (!rc) { 83 return PLDM_SUCCESS; 84 } 85 86 cc = pldm_xlate_errno(rc); 87 assert(cc < UINT8_MAX); 88 if (cc > UINT8_MAX) { 89 static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error"); 90 return PLDM_ERROR; 91 } 92 93 return cc; 94 } 95 96 LIBPLDM_ABI_STABLE 97 uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg, 98 struct pldm_header_info *hdr) 99 { 100 enum pldm_completion_codes cc; 101 int rc; 102 103 rc = unpack_pldm_header_errno(msg, hdr); 104 if (!rc) { 105 return PLDM_SUCCESS; 106 } 107 108 cc = pldm_xlate_errno(rc); 109 assert(cc < UINT8_MAX); 110 if (cc > UINT8_MAX) { 111 static_assert(PLDM_ERROR < UINT8_MAX, "Unable to report error"); 112 return PLDM_ERROR; 113 } 114 115 return cc; 116 } 117 118 LIBPLDM_ABI_STABLE 119 bool pldm_msg_hdr_correlate_response(const struct pldm_msg_hdr *req, 120 const struct pldm_msg_hdr *resp) 121 { 122 return req->instance_id == resp->instance_id && req->request && 123 !resp->request && req->type == resp->type && 124 req->command == resp->command; 125 } 126 127 LIBPLDM_ABI_STABLE 128 int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg) 129 { 130 if (msg == NULL) { 131 return PLDM_ERROR_INVALID_DATA; 132 } 133 134 struct pldm_header_info header = { 0 }; 135 header.instance = instance_id; 136 header.msg_type = PLDM_REQUEST; 137 header.command = PLDM_GET_PLDM_TYPES; 138 139 return pack_pldm_header(&header, &(msg->hdr)); 140 } 141 142 LIBPLDM_ABI_STABLE 143 int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version, 144 struct pldm_msg *msg) 145 { 146 if (msg == NULL) { 147 return PLDM_ERROR_INVALID_DATA; 148 } 149 150 struct pldm_header_info header = { 0 }; 151 header.instance = instance_id; 152 header.msg_type = PLDM_REQUEST; 153 header.command = PLDM_GET_PLDM_COMMANDS; 154 155 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 156 if (rc != PLDM_SUCCESS) { 157 return rc; 158 } 159 160 struct pldm_get_commands_req *request = 161 (struct pldm_get_commands_req *)msg->payload; 162 163 request->type = type; 164 request->version = version; 165 166 return PLDM_SUCCESS; 167 } 168 169 LIBPLDM_ABI_STABLE 170 int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code, 171 const bitfield8_t *types, struct pldm_msg *msg) 172 { 173 if (msg == NULL) { 174 return PLDM_ERROR_INVALID_DATA; 175 } 176 177 struct pldm_header_info header = { 0 }; 178 header.instance = instance_id; 179 header.msg_type = PLDM_RESPONSE; 180 header.command = PLDM_GET_PLDM_TYPES; 181 182 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 183 if (rc != PLDM_SUCCESS) { 184 return rc; 185 } 186 187 struct pldm_get_types_resp *response = 188 (struct pldm_get_types_resp *)msg->payload; 189 response->completion_code = completion_code; 190 if (response->completion_code == PLDM_SUCCESS) { 191 if (types == NULL) { 192 return PLDM_ERROR_INVALID_DATA; 193 } 194 memcpy(response->types, &(types->byte), PLDM_MAX_TYPES / 8); 195 } 196 197 return PLDM_SUCCESS; 198 } 199 200 LIBPLDM_ABI_STABLE 201 int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length, 202 uint8_t *type, ver32_t *version) 203 { 204 if (msg == NULL || type == NULL || version == NULL) { 205 return PLDM_ERROR_INVALID_DATA; 206 } 207 208 if (payload_length != PLDM_GET_COMMANDS_REQ_BYTES) { 209 return PLDM_ERROR_INVALID_LENGTH; 210 } 211 212 struct pldm_get_commands_req *request = 213 (struct pldm_get_commands_req *)msg->payload; 214 *type = request->type; 215 *version = request->version; 216 return PLDM_SUCCESS; 217 } 218 219 LIBPLDM_ABI_STABLE 220 int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code, 221 const bitfield8_t *commands, struct pldm_msg *msg) 222 { 223 if (msg == NULL) { 224 return PLDM_ERROR_INVALID_DATA; 225 } 226 227 struct pldm_header_info header = { 0 }; 228 header.instance = instance_id; 229 header.msg_type = PLDM_RESPONSE; 230 header.command = PLDM_GET_PLDM_COMMANDS; 231 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 232 if (rc != PLDM_SUCCESS) { 233 return rc; 234 } 235 236 struct pldm_get_commands_resp *response = 237 (struct pldm_get_commands_resp *)msg->payload; 238 response->completion_code = completion_code; 239 if (response->completion_code == PLDM_SUCCESS) { 240 if (commands == NULL) { 241 return PLDM_ERROR_INVALID_DATA; 242 } 243 memcpy(response->commands, &(commands->byte), 244 PLDM_MAX_CMDS_PER_TYPE / 8); 245 } 246 247 return PLDM_SUCCESS; 248 } 249 250 LIBPLDM_ABI_STABLE 251 int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length, 252 uint8_t *completion_code, bitfield8_t *types) 253 { 254 if (msg == NULL || types == NULL || completion_code == NULL) { 255 return PLDM_ERROR_INVALID_DATA; 256 } 257 258 *completion_code = msg->payload[0]; 259 if (PLDM_SUCCESS != *completion_code) { 260 return PLDM_SUCCESS; 261 } 262 263 if (payload_length != PLDM_GET_TYPES_RESP_BYTES) { 264 return PLDM_ERROR_INVALID_LENGTH; 265 } 266 267 struct pldm_get_types_resp *response = 268 (struct pldm_get_types_resp *)msg->payload; 269 270 memcpy(&(types->byte), response->types, PLDM_MAX_TYPES / 8); 271 272 return PLDM_SUCCESS; 273 } 274 275 LIBPLDM_ABI_STABLE 276 int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length, 277 uint8_t *completion_code, bitfield8_t *commands) 278 { 279 if (msg == NULL || commands == NULL || completion_code == NULL) { 280 return PLDM_ERROR_INVALID_DATA; 281 } 282 283 *completion_code = msg->payload[0]; 284 if (PLDM_SUCCESS != *completion_code) { 285 return PLDM_SUCCESS; 286 } 287 288 if (payload_length != PLDM_GET_COMMANDS_RESP_BYTES) { 289 return PLDM_ERROR_INVALID_LENGTH; 290 } 291 292 struct pldm_get_commands_resp *response = 293 (struct pldm_get_commands_resp *)msg->payload; 294 295 memcpy(&(commands->byte), response->commands, 296 PLDM_MAX_CMDS_PER_TYPE / 8); 297 298 return PLDM_SUCCESS; 299 } 300 301 LIBPLDM_ABI_STABLE 302 int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle, 303 uint8_t transfer_opflag, uint8_t type, 304 struct pldm_msg *msg) 305 { 306 if (NULL == msg) { 307 return PLDM_ERROR_INVALID_DATA; 308 } 309 310 struct pldm_header_info header = { 0 }; 311 header.msg_type = PLDM_REQUEST; 312 header.instance = instance_id; 313 header.pldm_type = PLDM_BASE; 314 header.command = PLDM_GET_PLDM_VERSION; 315 316 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 317 if (rc != PLDM_SUCCESS) { 318 return rc; 319 } 320 321 struct pldm_get_version_req *request = 322 (struct pldm_get_version_req *)msg->payload; 323 transfer_handle = htole32(transfer_handle); 324 request->transfer_handle = transfer_handle; 325 request->transfer_opflag = transfer_opflag; 326 request->type = type; 327 328 return PLDM_SUCCESS; 329 } 330 331 LIBPLDM_ABI_DEPRECATED_UNSAFE 332 int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code, 333 uint32_t next_transfer_handle, 334 uint8_t transfer_flag, const ver32_t *version_data, 335 size_t version_size, struct pldm_msg *msg) 336 { 337 if (NULL == msg || NULL == version_data) { 338 return PLDM_ERROR_INVALID_DATA; 339 } 340 341 struct pldm_header_info header = { 0 }; 342 header.msg_type = PLDM_RESPONSE; 343 header.instance = instance_id; 344 header.pldm_type = PLDM_BASE; 345 header.command = PLDM_GET_PLDM_VERSION; 346 347 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 348 if (rc != PLDM_SUCCESS) { 349 return rc; 350 } 351 352 struct pldm_get_version_resp *response = 353 (struct pldm_get_version_resp *)msg->payload; 354 response->completion_code = completion_code; 355 if (response->completion_code == PLDM_SUCCESS) { 356 response->next_transfer_handle = htole32(next_transfer_handle); 357 response->transfer_flag = transfer_flag; 358 memcpy(response->version_data, (uint8_t *)version_data, 359 version_size); 360 } 361 return PLDM_SUCCESS; 362 } 363 364 LIBPLDM_ABI_STABLE 365 int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length, 366 uint32_t *transfer_handle, uint8_t *transfer_opflag, 367 uint8_t *type) 368 { 369 if (payload_length != PLDM_GET_VERSION_REQ_BYTES) { 370 return PLDM_ERROR_INVALID_LENGTH; 371 } 372 373 struct pldm_get_version_req *request = 374 (struct pldm_get_version_req *)msg->payload; 375 *transfer_handle = le32toh(request->transfer_handle); 376 *transfer_opflag = request->transfer_opflag; 377 *type = request->type; 378 return PLDM_SUCCESS; 379 } 380 381 LIBPLDM_ABI_STABLE 382 int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length, 383 uint8_t *completion_code, 384 uint32_t *next_transfer_handle, 385 uint8_t *transfer_flag, ver32_t *version) 386 { 387 if (msg == NULL || next_transfer_handle == NULL || 388 transfer_flag == NULL || completion_code == NULL) { 389 return PLDM_ERROR_INVALID_DATA; 390 } 391 392 *completion_code = msg->payload[0]; 393 if (PLDM_SUCCESS != *completion_code) { 394 return PLDM_SUCCESS; 395 } 396 397 if (payload_length < PLDM_GET_VERSION_RESP_BYTES) { 398 return PLDM_ERROR_INVALID_LENGTH; 399 } 400 401 struct pldm_get_version_resp *response = 402 (struct pldm_get_version_resp *)msg->payload; 403 404 *next_transfer_handle = le32toh(response->next_transfer_handle); 405 *transfer_flag = response->transfer_flag; 406 memcpy(version, (uint8_t *)response->version_data, sizeof(ver32_t)); 407 408 return PLDM_SUCCESS; 409 } 410 411 LIBPLDM_ABI_STABLE 412 int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg) 413 { 414 if (msg == NULL) { 415 return PLDM_ERROR_INVALID_DATA; 416 } 417 418 struct pldm_header_info header = { 0 }; 419 header.instance = instance_id; 420 header.msg_type = PLDM_REQUEST; 421 header.command = PLDM_GET_TID; 422 423 return pack_pldm_header(&header, &(msg->hdr)); 424 } 425 426 LIBPLDM_ABI_STABLE 427 int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code, 428 uint8_t tid, struct pldm_msg *msg) 429 { 430 if (msg == NULL) { 431 return PLDM_ERROR_INVALID_DATA; 432 } 433 434 struct pldm_header_info header = { 0 }; 435 header.instance = instance_id; 436 header.msg_type = PLDM_RESPONSE; 437 header.command = PLDM_GET_TID; 438 439 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 440 if (rc != PLDM_SUCCESS) { 441 return rc; 442 } 443 444 struct pldm_get_tid_resp *response = 445 (struct pldm_get_tid_resp *)msg->payload; 446 response->completion_code = completion_code; 447 response->tid = tid; 448 449 return PLDM_SUCCESS; 450 } 451 452 LIBPLDM_ABI_STABLE 453 int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length, 454 uint8_t *completion_code, uint8_t *tid) 455 { 456 if (msg == NULL || tid == NULL || completion_code == NULL) { 457 return PLDM_ERROR_INVALID_DATA; 458 } 459 460 *completion_code = msg->payload[0]; 461 if (PLDM_SUCCESS != *completion_code) { 462 return PLDM_SUCCESS; 463 } 464 465 if (payload_length != PLDM_GET_TID_RESP_BYTES) { 466 return PLDM_ERROR_INVALID_LENGTH; 467 } 468 469 struct pldm_get_tid_resp *response = 470 (struct pldm_get_tid_resp *)msg->payload; 471 472 *tid = response->tid; 473 474 return PLDM_SUCCESS; 475 } 476 477 LIBPLDM_ABI_STABLE 478 int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg) 479 { 480 if (msg == NULL) { 481 return PLDM_ERROR_INVALID_DATA; 482 } 483 484 if (tid == 0x0 || tid == 0xff) { 485 return PLDM_ERROR_INVALID_DATA; 486 } 487 488 struct pldm_header_info header = { 0 }; 489 header.instance = instance_id; 490 header.msg_type = PLDM_REQUEST; 491 header.command = PLDM_SET_TID; 492 493 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 494 if (rc != PLDM_SUCCESS) { 495 return rc; 496 } 497 498 struct pldm_set_tid_req *request = 499 (struct pldm_set_tid_req *)msg->payload; 500 request->tid = tid; 501 502 return PLDM_SUCCESS; 503 } 504 505 LIBPLDM_ABI_STABLE 506 int decode_multipart_receive_req(const struct pldm_msg *msg, 507 size_t payload_length, uint8_t *pldm_type, 508 uint8_t *transfer_opflag, 509 uint32_t *transfer_ctx, 510 uint32_t *transfer_handle, 511 uint32_t *section_offset, 512 uint32_t *section_length) 513 { 514 if (msg == NULL || pldm_type == NULL || transfer_opflag == NULL || 515 transfer_ctx == NULL || transfer_handle == NULL || 516 section_offset == NULL || section_length == NULL) { 517 return PLDM_ERROR_INVALID_DATA; 518 } 519 520 if (payload_length != PLDM_MULTIPART_RECEIVE_REQ_BYTES) { 521 return PLDM_ERROR_INVALID_LENGTH; 522 } 523 524 struct pldm_multipart_receive_req *request = 525 (struct pldm_multipart_receive_req *)msg->payload; 526 527 if (request->pldm_type != PLDM_BASE) { 528 return PLDM_ERROR_INVALID_PLDM_TYPE; 529 } 530 531 // Any enum value above PLDM_XFER_CURRENT_PART is invalid. 532 if (request->transfer_opflag > PLDM_XFER_CURRENT_PART) { 533 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 534 } 535 536 // A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers. 537 uint32_t sec_offset = le32toh(request->section_offset); 538 if (sec_offset == 0 && 539 (request->transfer_opflag != PLDM_XFER_FIRST_PART && 540 request->transfer_opflag != PLDM_XFER_COMPLETE)) { 541 return PLDM_ERROR_INVALID_DATA; 542 } 543 544 uint32_t handle = le32toh(request->transfer_handle); 545 if (handle == 0 && request->transfer_opflag != PLDM_XFER_COMPLETE) { 546 return PLDM_ERROR_INVALID_DATA; 547 } 548 549 *pldm_type = request->pldm_type; 550 *transfer_opflag = request->transfer_opflag; 551 *transfer_ctx = request->transfer_ctx; 552 *transfer_handle = handle; 553 *section_offset = sec_offset; 554 *section_length = le32toh(request->section_length); 555 556 return PLDM_SUCCESS; 557 } 558 559 LIBPLDM_ABI_TESTING 560 int encode_base_multipart_receive_req( 561 uint8_t instance_id, const struct pldm_multipart_receive_req *req, 562 struct pldm_msg *msg, size_t payload_length) 563 { 564 PLDM_MSGBUF_DEFINE_P(buf); 565 int rc; 566 567 if (req == NULL || msg == NULL) { 568 return -EINVAL; 569 } 570 571 struct pldm_header_info header = { 0 }; 572 header.instance = instance_id; 573 header.msg_type = PLDM_REQUEST; 574 header.pldm_type = PLDM_BASE; 575 header.command = PLDM_MULTIPART_RECEIVE; 576 577 rc = pack_pldm_header_errno(&header, &msg->hdr); 578 if (rc) { 579 return rc; 580 } 581 582 rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES, 583 msg->payload, payload_length); 584 if (rc) { 585 return rc; 586 } 587 588 pldm_msgbuf_insert(buf, req->pldm_type); 589 pldm_msgbuf_insert(buf, req->transfer_opflag); 590 pldm_msgbuf_insert(buf, req->transfer_ctx); 591 pldm_msgbuf_insert(buf, req->transfer_handle); 592 pldm_msgbuf_insert(buf, req->section_offset); 593 pldm_msgbuf_insert(buf, req->section_length); 594 595 return pldm_msgbuf_complete(buf); 596 } 597 598 LIBPLDM_ABI_TESTING 599 int decode_base_multipart_receive_resp(const struct pldm_msg *msg, 600 size_t payload_length, 601 struct pldm_multipart_receive_resp *resp, 602 uint32_t *data_integrity_checksum) 603 { 604 PLDM_MSGBUF_DEFINE_P(buf); 605 int rc; 606 607 if (msg == NULL || resp == NULL || data_integrity_checksum == NULL) { 608 return -EINVAL; 609 } 610 611 rc = pldm_msg_has_error(msg, payload_length); 612 613 if (rc) { 614 resp->completion_code = rc; 615 return 0; 616 } 617 618 rc = pldm_msgbuf_init_errno(buf, 619 PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES, 620 msg->payload, payload_length); 621 if (rc) { 622 return rc; 623 } 624 625 pldm_msgbuf_extract(buf, resp->completion_code); 626 rc = pldm_msgbuf_extract(buf, resp->transfer_flag); 627 if (rc) { 628 return pldm_msgbuf_discard(buf, rc); 629 } 630 pldm_msgbuf_extract(buf, resp->next_transfer_handle); 631 632 rc = pldm_msgbuf_extract_uint32_to_size(buf, resp->data.length); 633 if (rc) { 634 return pldm_msgbuf_discard(buf, rc); 635 } 636 637 if (resp->data.length > 0) { 638 resp->data.ptr = NULL; 639 pldm_msgbuf_span_required(buf, resp->data.length, 640 (void **)&resp->data.ptr); 641 } 642 643 if (resp->transfer_flag == 644 PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_END || 645 resp->transfer_flag == 646 PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_START_AND_END) { 647 pldm_msgbuf_extract_p(buf, data_integrity_checksum); 648 } 649 650 return pldm_msgbuf_complete_consumed(buf); 651 } 652 653 LIBPLDM_ABI_STABLE 654 int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command, 655 uint8_t cc, struct pldm_msg *msg) 656 { 657 if (msg == NULL) { 658 return PLDM_ERROR_INVALID_DATA; 659 } 660 661 struct pldm_header_info header = { 0 }; 662 header.instance = instance_id; 663 header.msg_type = PLDM_RESPONSE; 664 header.pldm_type = type; 665 header.command = command; 666 667 uint8_t rc = pack_pldm_header(&header, &msg->hdr); 668 if (rc != PLDM_SUCCESS) { 669 return rc; 670 } 671 672 msg->payload[0] = cc; 673 674 return PLDM_SUCCESS; 675 } 676 677 int encode_pldm_header_only_errno(uint8_t msg_type, uint8_t instance_id, 678 uint8_t pldm_type, uint8_t command, 679 struct pldm_msg *msg) 680 { 681 if (msg == NULL) { 682 return -EINVAL; 683 } 684 685 struct pldm_header_info header = { 0 }; 686 header.msg_type = msg_type; 687 header.instance = instance_id; 688 header.pldm_type = pldm_type; 689 header.command = command; 690 return pack_pldm_header_errno(&header, &(msg->hdr)); 691 } 692 693 LIBPLDM_ABI_STABLE 694 int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id, 695 uint8_t pldm_type, uint8_t command, 696 struct pldm_msg *msg) 697 { 698 int rc = encode_pldm_header_only_errno(msg_type, instance_id, pldm_type, 699 command, msg); 700 if (rc) { 701 return pldm_xlate_errno(rc); 702 } 703 return PLDM_SUCCESS; 704 } 705 706 LIBPLDM_ABI_TESTING 707 int encode_pldm_base_negotiate_transfer_params_req( 708 uint8_t instance_id, 709 const struct pldm_base_negotiate_transfer_params_req *req, 710 struct pldm_msg *msg, size_t payload_length) 711 { 712 PLDM_MSGBUF_DEFINE_P(buf); 713 int rc; 714 715 if (req == NULL || msg == NULL) { 716 return -EINVAL; 717 } 718 719 struct pldm_header_info header = { 0 }; 720 header.instance = instance_id; 721 header.msg_type = PLDM_REQUEST; 722 header.pldm_type = PLDM_BASE; 723 header.command = PLDM_NEGOTIATE_TRANSFER_PARAMETERS; 724 725 rc = pack_pldm_header_errno(&header, &msg->hdr); 726 if (rc) { 727 return rc; 728 } 729 730 rc = pldm_msgbuf_init_errno( 731 buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES, 732 msg->payload, payload_length); 733 if (rc) { 734 return rc; 735 } 736 737 pldm_msgbuf_insert(buf, req->requester_part_size); 738 rc = pldm_msgbuf_insert_array( 739 buf, sizeof(req->requester_protocol_support), 740 (uint8_t *)req->requester_protocol_support, 741 sizeof(req->requester_protocol_support)); 742 if (rc) { 743 return pldm_msgbuf_discard(buf, rc); 744 } 745 746 return pldm_msgbuf_complete(buf); 747 } 748 749 LIBPLDM_ABI_TESTING 750 int decode_pldm_base_negotiate_transfer_params_resp( 751 const struct pldm_msg *msg, size_t payload_length, 752 struct pldm_base_negotiate_transfer_params_resp *resp) 753 { 754 PLDM_MSGBUF_DEFINE_P(buf); 755 int rc; 756 757 if (msg == NULL || resp == NULL) { 758 return -EINVAL; 759 } 760 761 rc = pldm_msg_has_error(msg, payload_length); 762 763 if (rc) { 764 resp->completion_code = rc; 765 return 0; 766 } 767 768 rc = pldm_msgbuf_init_errno( 769 buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES, 770 msg->payload, payload_length); 771 if (rc) { 772 return rc; 773 } 774 775 pldm_msgbuf_extract(buf, resp->completion_code); 776 pldm_msgbuf_extract(buf, resp->responder_part_size); 777 rc = pldm_msgbuf_extract_array( 778 buf, sizeof(resp->responder_protocol_support), 779 (uint8_t *)resp->responder_protocol_support, 780 sizeof(resp->responder_protocol_support)); 781 if (rc) { 782 return pldm_msgbuf_discard(buf, rc); 783 } 784 785 return pldm_msgbuf_complete_consumed(buf); 786 } 787