1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 #include <libpldm/oem/meta/file_io.h> 3 #include <endian.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <stdio.h> 7 8 #include "api.h" 9 #include "msgbuf.h" 10 #include "dsp/base.h" 11 12 LIBPLDM_ABI_STABLE 13 void *pldm_oem_meta_file_io_write_req_data( 14 struct pldm_oem_meta_file_io_write_req *req) 15 { 16 return req->data; 17 } 18 19 LIBPLDM_ABI_STABLE 20 int decode_oem_meta_file_io_write_req( 21 const struct pldm_msg *msg, size_t payload_length, 22 struct pldm_oem_meta_file_io_write_req *req, size_t req_length) 23 { 24 struct pldm_msgbuf _buf; 25 struct pldm_msgbuf *buf = &_buf; 26 int rc; 27 28 if (msg == NULL || req == NULL) { 29 return -EINVAL; 30 } 31 32 if (req_length < sizeof(*req)) { 33 return -EINVAL; 34 } 35 36 rc = pldm_msgbuf_init_errno(buf, 37 PLDM_OEM_META_FILE_IO_WRITE_REQ_MIN_LENGTH, 38 msg->payload, payload_length); 39 if (rc) { 40 return rc; 41 } 42 43 pldm_msgbuf_extract(buf, req->handle); 44 rc = pldm_msgbuf_extract(buf, req->length); 45 if (rc) { 46 return rc; 47 } 48 49 rc = pldm_msgbuf_extract_array(buf, req->length, req->data, 50 req_length - sizeof(*req)); 51 if (rc) { 52 return rc; 53 } 54 55 return pldm_msgbuf_destroy_consumed(buf); 56 } 57 58 LIBPLDM_ABI_DEPRECATED_UNSAFE 59 int decode_oem_meta_file_io_req(const struct pldm_msg *msg, 60 size_t payload_length, uint8_t *file_handle, 61 uint32_t *length, uint8_t *data) 62 { 63 struct pldm_oem_meta_file_io_write_req *request_msg; 64 size_t request_msg_len; 65 int rc; 66 67 if (msg == NULL || file_handle == NULL || length == NULL || 68 data == NULL) { 69 return pldm_xlate_errno(-EINVAL); 70 } 71 72 if (SIZE_MAX - sizeof(*request_msg) < payload_length) { 73 return pldm_xlate_errno(-EOVERFLOW); 74 } 75 76 request_msg_len = sizeof(*request_msg) + payload_length; 77 request_msg = malloc(request_msg_len); 78 79 rc = decode_oem_meta_file_io_write_req(msg, payload_length, request_msg, 80 request_msg_len); 81 if (rc < 0) { 82 free(request_msg); 83 return pldm_xlate_errno(rc); 84 } 85 86 *file_handle = request_msg->handle; 87 *length = request_msg->length; 88 89 /* NOTE: Unsafe, memory safety is not possible due to API constraints. */ 90 memcpy(data, request_msg->data, request_msg->length); 91 92 free(request_msg); 93 94 return 0; 95 } 96 97 LIBPLDM_ABI_STABLE 98 int decode_oem_meta_file_io_read_req(const struct pldm_msg *msg, 99 size_t payload_length, 100 struct pldm_oem_meta_file_io_read_req *req) 101 { 102 struct pldm_msgbuf _buf; 103 struct pldm_msgbuf *buf = &_buf; 104 105 if (msg == NULL || req == NULL) { 106 return -EINVAL; 107 } 108 109 if (req->version > sizeof(struct pldm_oem_meta_file_io_read_req)) { 110 return -E2BIG; 111 } 112 113 int rc = pldm_msgbuf_init_errno( 114 buf, PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH, msg->payload, 115 payload_length); 116 if (rc) { 117 return rc; 118 } 119 120 pldm_msgbuf_extract(buf, req->handle); 121 rc = pldm_msgbuf_extract(buf, req->option); 122 if (rc) { 123 return rc; 124 } 125 126 rc = pldm_msgbuf_extract(buf, req->length); 127 if (rc) { 128 return rc; 129 } 130 131 switch (req->option) { 132 case PLDM_OEM_META_FILE_IO_READ_ATTR: 133 if (req->length != 0) { 134 return -EPROTO; 135 } 136 break; 137 case PLDM_OEM_META_FILE_IO_READ_DATA: 138 pldm_msgbuf_extract(buf, req->info.data.transferFlag); 139 pldm_msgbuf_extract(buf, req->info.data.offset); 140 break; 141 default: 142 return -EPROTO; 143 } 144 145 return pldm_msgbuf_destroy_consumed(buf); 146 } 147 148 LIBPLDM_ABI_STABLE 149 void *pldm_oem_meta_file_io_read_resp_data( 150 struct pldm_oem_meta_file_io_read_resp *resp) 151 { 152 return resp->data; 153 } 154 155 LIBPLDM_ABI_STABLE 156 int encode_oem_meta_file_io_read_resp( 157 uint8_t instance_id, struct pldm_oem_meta_file_io_read_resp *resp, 158 size_t resp_len, struct pldm_msg *responseMsg, size_t payload_length) 159 { 160 int rc; 161 struct pldm_msgbuf _buf; 162 struct pldm_msgbuf *buf = &_buf; 163 struct pldm_header_info header = { 0 }; 164 165 if (resp == NULL || responseMsg == NULL) { 166 return -EINVAL; 167 } 168 169 if (resp_len < sizeof(*resp)) { 170 return -EINVAL; 171 } 172 173 if (resp->version > sizeof(*resp)) { 174 return -E2BIG; 175 } 176 177 header.instance = instance_id; 178 header.msg_type = PLDM_RESPONSE; 179 header.pldm_type = PLDM_OEM; 180 header.command = PLDM_OEM_META_FILE_IO_CMD_READ_FILE; 181 rc = pack_pldm_header_errno(&header, &(responseMsg->hdr)); 182 if (rc) { 183 return rc; 184 } 185 186 rc = pldm_msgbuf_init_errno(buf, 187 PLDM_OEM_META_FILE_IO_READ_RESP_MIN_SIZE, 188 responseMsg->payload, payload_length); 189 if (rc) { 190 return rc; 191 } 192 193 pldm_msgbuf_insert(buf, resp->completion_code); 194 pldm_msgbuf_insert(buf, resp->handle); 195 pldm_msgbuf_insert(buf, resp->option); 196 pldm_msgbuf_insert(buf, resp->length); 197 198 switch (resp->option) { 199 case PLDM_OEM_META_FILE_IO_READ_ATTR: 200 pldm_msgbuf_insert(buf, resp->info.attr.size); 201 pldm_msgbuf_insert(buf, resp->info.attr.crc32); 202 break; 203 case PLDM_OEM_META_FILE_IO_READ_DATA: 204 pldm_msgbuf_insert(buf, resp->info.data.transferFlag); 205 pldm_msgbuf_insert(buf, resp->info.data.offset); 206 rc = pldm_msgbuf_insert_array_uint8(buf, resp->length, 207 resp->data, 208 resp_len - sizeof(*resp)); 209 if (rc) { 210 return rc; 211 } 212 break; 213 default: 214 return -EPROTO; 215 } 216 217 return pldm_msgbuf_destroy(buf); 218 } 219