| /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ |
| #include <libpldm/oem/meta/file_io.h> |
| #include <endian.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| #include "api.h" |
| #include "msgbuf.h" |
| #include "dsp/base.h" |
| |
| LIBPLDM_ABI_TESTING |
| void *pldm_oem_meta_file_io_write_req_data( |
| struct pldm_oem_meta_file_io_write_req *req) |
| { |
| return req->data; |
| } |
| |
| LIBPLDM_ABI_TESTING |
| int decode_oem_meta_file_io_write_req( |
| const struct pldm_msg *msg, size_t payload_length, |
| struct pldm_oem_meta_file_io_write_req *req, size_t req_length) |
| { |
| struct pldm_msgbuf _buf; |
| struct pldm_msgbuf *buf = &_buf; |
| int rc; |
| |
| if (msg == NULL || req == NULL) { |
| return -EINVAL; |
| } |
| |
| if (req_length < sizeof(*req)) { |
| return -EINVAL; |
| } |
| |
| rc = pldm_msgbuf_init_errno(buf, |
| PLDM_OEM_META_FILE_IO_WRITE_REQ_MIN_LENGTH, |
| msg->payload, payload_length); |
| if (rc) { |
| return rc; |
| } |
| |
| pldm_msgbuf_extract(buf, req->handle); |
| rc = pldm_msgbuf_extract(buf, req->length); |
| if (rc) { |
| return rc; |
| } |
| |
| rc = pldm_msgbuf_extract_array(buf, req->length, req->data, |
| req_length - sizeof(*req)); |
| if (rc) { |
| return rc; |
| } |
| |
| return pldm_msgbuf_destroy_consumed(buf); |
| } |
| |
| LIBPLDM_ABI_DEPRECATED |
| int decode_oem_meta_file_io_req(const struct pldm_msg *msg, |
| size_t payload_length, uint8_t *file_handle, |
| uint32_t *length, uint8_t *data) |
| { |
| struct pldm_oem_meta_file_io_write_req *request_msg; |
| size_t request_msg_len; |
| int rc; |
| |
| if (msg == NULL || file_handle == NULL || length == NULL || |
| data == NULL) { |
| return pldm_xlate_errno(-EINVAL); |
| } |
| |
| request_msg_len = sizeof(*request_msg) + payload_length; |
| request_msg = malloc(request_msg_len); |
| |
| rc = decode_oem_meta_file_io_write_req(msg, payload_length, request_msg, |
| request_msg_len); |
| if (rc < 0) { |
| free(request_msg); |
| return pldm_xlate_errno(rc); |
| } |
| |
| *file_handle = request_msg->handle; |
| *length = request_msg->length; |
| |
| /* NOTE: Unsafe, memory safety is not possible due to API constraints. */ |
| memcpy(data, request_msg->data, request_msg->length); |
| |
| free(request_msg); |
| |
| return 0; |
| } |
| |
| LIBPLDM_ABI_TESTING |
| int decode_oem_meta_file_io_read_req(const struct pldm_msg *msg, |
| size_t payload_length, |
| struct pldm_oem_meta_file_io_read_req *req) |
| { |
| struct pldm_msgbuf _buf; |
| struct pldm_msgbuf *buf = &_buf; |
| |
| if (msg == NULL || req == NULL) { |
| return -EINVAL; |
| } |
| |
| if (req->version > sizeof(struct pldm_oem_meta_file_io_read_req)) { |
| return -E2BIG; |
| } |
| |
| int rc = pldm_msgbuf_init_errno( |
| buf, PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH, msg->payload, |
| payload_length); |
| if (rc) { |
| return rc; |
| } |
| |
| pldm_msgbuf_extract(buf, req->handle); |
| rc = pldm_msgbuf_extract(buf, req->option); |
| if (rc) { |
| return rc; |
| } |
| |
| rc = pldm_msgbuf_extract(buf, req->length); |
| if (rc) { |
| return rc; |
| } |
| |
| switch (req->option) { |
| case PLDM_OEM_META_FILE_IO_READ_ATTR: |
| if (req->length != 0) { |
| return -EPROTO; |
| } |
| break; |
| case PLDM_OEM_META_FILE_IO_READ_DATA: |
| pldm_msgbuf_extract(buf, req->info.data.transferFlag); |
| pldm_msgbuf_extract(buf, req->info.data.offset); |
| break; |
| default: |
| return -EPROTO; |
| } |
| |
| return pldm_msgbuf_destroy_consumed(buf); |
| } |
| |
| LIBPLDM_ABI_TESTING |
| void *pldm_oem_meta_file_io_read_resp_data( |
| struct pldm_oem_meta_file_io_read_resp *resp) |
| { |
| return resp->data; |
| } |
| |
| LIBPLDM_ABI_TESTING |
| int encode_oem_meta_file_io_read_resp( |
| uint8_t instance_id, struct pldm_oem_meta_file_io_read_resp *resp, |
| size_t resp_len, struct pldm_msg *responseMsg, size_t payload_length) |
| { |
| int rc; |
| struct pldm_msgbuf _buf; |
| struct pldm_msgbuf *buf = &_buf; |
| struct pldm_header_info header = { 0 }; |
| |
| if (resp == NULL || responseMsg == NULL) { |
| return -EINVAL; |
| } |
| |
| if (resp_len < sizeof(*resp)) { |
| return -EINVAL; |
| } |
| |
| if (resp->version > sizeof(*resp)) { |
| return -E2BIG; |
| } |
| |
| header.instance = instance_id; |
| header.msg_type = PLDM_RESPONSE; |
| header.pldm_type = PLDM_OEM; |
| header.command = PLDM_OEM_META_FILE_IO_CMD_READ_FILE; |
| rc = pack_pldm_header_errno(&header, &(responseMsg->hdr)); |
| if (rc) { |
| return rc; |
| } |
| |
| rc = pldm_msgbuf_init_errno(buf, |
| PLDM_OEM_META_FILE_IO_READ_RESP_MIN_SIZE, |
| responseMsg->payload, payload_length); |
| if (rc) { |
| return rc; |
| } |
| |
| pldm_msgbuf_insert(buf, resp->completion_code); |
| pldm_msgbuf_insert(buf, resp->handle); |
| pldm_msgbuf_insert(buf, resp->option); |
| pldm_msgbuf_insert(buf, resp->length); |
| |
| switch (resp->option) { |
| case PLDM_OEM_META_FILE_IO_READ_ATTR: |
| pldm_msgbuf_insert(buf, resp->info.attr.size); |
| pldm_msgbuf_insert(buf, resp->info.attr.crc32); |
| break; |
| case PLDM_OEM_META_FILE_IO_READ_DATA: |
| pldm_msgbuf_insert(buf, resp->info.data.transferFlag); |
| pldm_msgbuf_insert(buf, resp->info.data.offset); |
| rc = pldm_msgbuf_insert_array_uint8(buf, resp->length, |
| resp->data, |
| resp_len - sizeof(*resp)); |
| if (rc) { |
| return rc; |
| } |
| break; |
| default: |
| return -EPROTO; |
| } |
| |
| return pldm_msgbuf_destroy(buf); |
| } |