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_TESTING 506 int decode_set_tid_req(const struct pldm_msg *msg, size_t payload_length, 507 uint8_t *tid) 508 { 509 PLDM_MSGBUF_DEFINE_P(buf); 510 int rc; 511 512 if (!msg || !tid) { 513 return -EINVAL; 514 } 515 516 rc = pldm_msgbuf_init_errno(buf, PLDM_SET_TID_REQ_BYTES, msg->payload, 517 payload_length); 518 if (rc) { 519 return rc; 520 } 521 522 pldm_msgbuf_extract_p(buf, tid); 523 524 return pldm_msgbuf_complete_consumed(buf); 525 } 526 527 LIBPLDM_ABI_STABLE 528 int decode_multipart_receive_req(const struct pldm_msg *msg, 529 size_t payload_length, uint8_t *pldm_type, 530 uint8_t *transfer_opflag, 531 uint32_t *transfer_ctx, 532 uint32_t *transfer_handle, 533 uint32_t *section_offset, 534 uint32_t *section_length) 535 { 536 if (msg == NULL || pldm_type == NULL || transfer_opflag == NULL || 537 transfer_ctx == NULL || transfer_handle == NULL || 538 section_offset == NULL || section_length == NULL) { 539 return PLDM_ERROR_INVALID_DATA; 540 } 541 542 if (payload_length != PLDM_MULTIPART_RECEIVE_REQ_BYTES) { 543 return PLDM_ERROR_INVALID_LENGTH; 544 } 545 546 struct pldm_multipart_receive_req *request = 547 (struct pldm_multipart_receive_req *)msg->payload; 548 549 if (request->pldm_type != PLDM_BASE) { 550 return PLDM_ERROR_INVALID_PLDM_TYPE; 551 } 552 553 // Any enum value above PLDM_XFER_CURRENT_PART is invalid. 554 if (request->transfer_opflag > PLDM_XFER_CURRENT_PART) { 555 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 556 } 557 558 // A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers. 559 uint32_t sec_offset = le32toh(request->section_offset); 560 if (sec_offset == 0 && 561 (request->transfer_opflag != PLDM_XFER_FIRST_PART && 562 request->transfer_opflag != PLDM_XFER_COMPLETE)) { 563 return PLDM_ERROR_INVALID_DATA; 564 } 565 566 uint32_t handle = le32toh(request->transfer_handle); 567 if (handle == 0 && request->transfer_opflag != PLDM_XFER_COMPLETE) { 568 return PLDM_ERROR_INVALID_DATA; 569 } 570 571 *pldm_type = request->pldm_type; 572 *transfer_opflag = request->transfer_opflag; 573 *transfer_ctx = request->transfer_ctx; 574 *transfer_handle = handle; 575 *section_offset = sec_offset; 576 *section_length = le32toh(request->section_length); 577 578 return PLDM_SUCCESS; 579 } 580 581 LIBPLDM_ABI_TESTING 582 int encode_base_multipart_receive_req( 583 uint8_t instance_id, const struct pldm_multipart_receive_req *req, 584 struct pldm_msg *msg, size_t payload_length) 585 { 586 PLDM_MSGBUF_DEFINE_P(buf); 587 int rc; 588 589 if (req == NULL || msg == NULL) { 590 return -EINVAL; 591 } 592 593 struct pldm_header_info header = { 0 }; 594 header.instance = instance_id; 595 header.msg_type = PLDM_REQUEST; 596 header.pldm_type = PLDM_BASE; 597 header.command = PLDM_MULTIPART_RECEIVE; 598 599 rc = pack_pldm_header_errno(&header, &msg->hdr); 600 if (rc) { 601 return rc; 602 } 603 604 rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES, 605 msg->payload, payload_length); 606 if (rc) { 607 return rc; 608 } 609 610 pldm_msgbuf_insert(buf, req->pldm_type); 611 pldm_msgbuf_insert(buf, req->transfer_opflag); 612 pldm_msgbuf_insert(buf, req->transfer_ctx); 613 pldm_msgbuf_insert(buf, req->transfer_handle); 614 pldm_msgbuf_insert(buf, req->section_offset); 615 pldm_msgbuf_insert(buf, req->section_length); 616 617 return pldm_msgbuf_complete(buf); 618 } 619 620 LIBPLDM_ABI_TESTING 621 int decode_base_multipart_receive_resp(const struct pldm_msg *msg, 622 size_t payload_length, 623 struct pldm_multipart_receive_resp *resp, 624 uint32_t *data_integrity_checksum) 625 { 626 PLDM_MSGBUF_DEFINE_P(buf); 627 int rc; 628 629 if (msg == NULL || resp == NULL || data_integrity_checksum == NULL) { 630 return -EINVAL; 631 } 632 633 rc = pldm_msg_has_error(msg, payload_length); 634 635 if (rc) { 636 resp->completion_code = rc; 637 return 0; 638 } 639 640 rc = pldm_msgbuf_init_errno(buf, 641 PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES, 642 msg->payload, payload_length); 643 if (rc) { 644 return rc; 645 } 646 647 pldm_msgbuf_extract(buf, resp->completion_code); 648 rc = pldm_msgbuf_extract(buf, resp->transfer_flag); 649 if (rc) { 650 return pldm_msgbuf_discard(buf, rc); 651 } 652 pldm_msgbuf_extract(buf, resp->next_transfer_handle); 653 654 rc = pldm_msgbuf_extract_uint32_to_size(buf, resp->data.length); 655 if (rc) { 656 return pldm_msgbuf_discard(buf, rc); 657 } 658 659 if (resp->data.length > 0) { 660 resp->data.ptr = NULL; 661 pldm_msgbuf_span_required(buf, resp->data.length, 662 (void **)&resp->data.ptr); 663 } 664 665 if (resp->transfer_flag == 666 PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_END || 667 resp->transfer_flag == 668 PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_START_AND_END) { 669 pldm_msgbuf_extract_p(buf, data_integrity_checksum); 670 } 671 672 return pldm_msgbuf_complete_consumed(buf); 673 } 674 675 LIBPLDM_ABI_STABLE 676 int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command, 677 uint8_t cc, struct pldm_msg *msg) 678 { 679 if (msg == NULL) { 680 return PLDM_ERROR_INVALID_DATA; 681 } 682 683 struct pldm_header_info header = { 0 }; 684 header.instance = instance_id; 685 header.msg_type = PLDM_RESPONSE; 686 header.pldm_type = type; 687 header.command = command; 688 689 uint8_t rc = pack_pldm_header(&header, &msg->hdr); 690 if (rc != PLDM_SUCCESS) { 691 return rc; 692 } 693 694 msg->payload[0] = cc; 695 696 return PLDM_SUCCESS; 697 } 698 699 int encode_pldm_header_only_errno(uint8_t msg_type, uint8_t instance_id, 700 uint8_t pldm_type, uint8_t command, 701 struct pldm_msg *msg) 702 { 703 if (msg == NULL) { 704 return -EINVAL; 705 } 706 707 struct pldm_header_info header = { 0 }; 708 header.msg_type = msg_type; 709 header.instance = instance_id; 710 header.pldm_type = pldm_type; 711 header.command = command; 712 return pack_pldm_header_errno(&header, &(msg->hdr)); 713 } 714 715 LIBPLDM_ABI_STABLE 716 int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id, 717 uint8_t pldm_type, uint8_t command, 718 struct pldm_msg *msg) 719 { 720 int rc = encode_pldm_header_only_errno(msg_type, instance_id, pldm_type, 721 command, msg); 722 if (rc) { 723 return pldm_xlate_errno(rc); 724 } 725 return PLDM_SUCCESS; 726 } 727 728 LIBPLDM_ABI_TESTING 729 int encode_pldm_base_negotiate_transfer_params_req( 730 uint8_t instance_id, 731 const struct pldm_base_negotiate_transfer_params_req *req, 732 struct pldm_msg *msg, size_t payload_length) 733 { 734 PLDM_MSGBUF_DEFINE_P(buf); 735 int rc; 736 737 if (req == NULL || msg == NULL) { 738 return -EINVAL; 739 } 740 741 struct pldm_header_info header = { 0 }; 742 header.instance = instance_id; 743 header.msg_type = PLDM_REQUEST; 744 header.pldm_type = PLDM_BASE; 745 header.command = PLDM_NEGOTIATE_TRANSFER_PARAMETERS; 746 747 rc = pack_pldm_header_errno(&header, &msg->hdr); 748 if (rc) { 749 return rc; 750 } 751 752 rc = pldm_msgbuf_init_errno( 753 buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES, 754 msg->payload, payload_length); 755 if (rc) { 756 return rc; 757 } 758 759 pldm_msgbuf_insert(buf, req->requester_part_size); 760 rc = pldm_msgbuf_insert_array( 761 buf, sizeof(req->requester_protocol_support), 762 (uint8_t *)req->requester_protocol_support, 763 sizeof(req->requester_protocol_support)); 764 if (rc) { 765 return pldm_msgbuf_discard(buf, rc); 766 } 767 768 return pldm_msgbuf_complete(buf); 769 } 770 771 LIBPLDM_ABI_TESTING 772 int decode_pldm_base_negotiate_transfer_params_resp( 773 const struct pldm_msg *msg, size_t payload_length, 774 struct pldm_base_negotiate_transfer_params_resp *resp) 775 { 776 PLDM_MSGBUF_DEFINE_P(buf); 777 int rc; 778 779 if (msg == NULL || resp == NULL) { 780 return -EINVAL; 781 } 782 783 rc = pldm_msg_has_error(msg, payload_length); 784 785 if (rc) { 786 resp->completion_code = rc; 787 return 0; 788 } 789 790 rc = pldm_msgbuf_init_errno( 791 buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES, 792 msg->payload, payload_length); 793 if (rc) { 794 return rc; 795 } 796 797 pldm_msgbuf_extract(buf, resp->completion_code); 798 pldm_msgbuf_extract(buf, resp->responder_part_size); 799 rc = pldm_msgbuf_extract_array( 800 buf, sizeof(resp->responder_protocol_support), 801 (uint8_t *)resp->responder_protocol_support, 802 sizeof(resp->responder_protocol_support)); 803 if (rc) { 804 return pldm_msgbuf_discard(buf, rc); 805 } 806 807 return pldm_msgbuf_complete_consumed(buf); 808 } 809