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