xref: /openbmc/libpldm/src/oem/meta/file_io.c (revision 1c4c704d)
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
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 	request_msg_len = sizeof(*request_msg) + payload_length;
73 	request_msg = malloc(request_msg_len);
74 
75 	rc = decode_oem_meta_file_io_write_req(msg, payload_length, request_msg,
76 					       request_msg_len);
77 	if (rc < 0) {
78 		free(request_msg);
79 		return pldm_xlate_errno(rc);
80 	}
81 
82 	*file_handle = request_msg->handle;
83 	*length = request_msg->length;
84 
85 	/* NOTE: Unsafe, memory safety is not possible due to API constraints. */
86 	memcpy(data, request_msg->data, request_msg->length);
87 
88 	free(request_msg);
89 
90 	return 0;
91 }
92 
93 LIBPLDM_ABI_STABLE
94 int decode_oem_meta_file_io_read_req(const struct pldm_msg *msg,
95 				     size_t payload_length,
96 				     struct pldm_oem_meta_file_io_read_req *req)
97 {
98 	struct pldm_msgbuf _buf;
99 	struct pldm_msgbuf *buf = &_buf;
100 
101 	if (msg == NULL || req == NULL) {
102 		return -EINVAL;
103 	}
104 
105 	if (req->version > sizeof(struct pldm_oem_meta_file_io_read_req)) {
106 		return -E2BIG;
107 	}
108 
109 	int rc = pldm_msgbuf_init_errno(
110 		buf, PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH, msg->payload,
111 		payload_length);
112 	if (rc) {
113 		return rc;
114 	}
115 
116 	pldm_msgbuf_extract(buf, req->handle);
117 	rc = pldm_msgbuf_extract(buf, req->option);
118 	if (rc) {
119 		return rc;
120 	}
121 
122 	rc = pldm_msgbuf_extract(buf, req->length);
123 	if (rc) {
124 		return rc;
125 	}
126 
127 	switch (req->option) {
128 	case PLDM_OEM_META_FILE_IO_READ_ATTR:
129 		if (req->length != 0) {
130 			return -EPROTO;
131 		}
132 		break;
133 	case PLDM_OEM_META_FILE_IO_READ_DATA:
134 		pldm_msgbuf_extract(buf, req->info.data.transferFlag);
135 		pldm_msgbuf_extract(buf, req->info.data.offset);
136 		break;
137 	default:
138 		return -EPROTO;
139 	}
140 
141 	return pldm_msgbuf_destroy_consumed(buf);
142 }
143 
144 LIBPLDM_ABI_STABLE
145 void *pldm_oem_meta_file_io_read_resp_data(
146 	struct pldm_oem_meta_file_io_read_resp *resp)
147 {
148 	return resp->data;
149 }
150 
151 LIBPLDM_ABI_STABLE
152 int encode_oem_meta_file_io_read_resp(
153 	uint8_t instance_id, struct pldm_oem_meta_file_io_read_resp *resp,
154 	size_t resp_len, struct pldm_msg *responseMsg, size_t payload_length)
155 {
156 	int rc;
157 	struct pldm_msgbuf _buf;
158 	struct pldm_msgbuf *buf = &_buf;
159 	struct pldm_header_info header = { 0 };
160 
161 	if (resp == NULL || responseMsg == NULL) {
162 		return -EINVAL;
163 	}
164 
165 	if (resp_len < sizeof(*resp)) {
166 		return -EINVAL;
167 	}
168 
169 	if (resp->version > sizeof(*resp)) {
170 		return -E2BIG;
171 	}
172 
173 	header.instance = instance_id;
174 	header.msg_type = PLDM_RESPONSE;
175 	header.pldm_type = PLDM_OEM;
176 	header.command = PLDM_OEM_META_FILE_IO_CMD_READ_FILE;
177 	rc = pack_pldm_header_errno(&header, &(responseMsg->hdr));
178 	if (rc) {
179 		return rc;
180 	}
181 
182 	rc = pldm_msgbuf_init_errno(buf,
183 				    PLDM_OEM_META_FILE_IO_READ_RESP_MIN_SIZE,
184 				    responseMsg->payload, payload_length);
185 	if (rc) {
186 		return rc;
187 	}
188 
189 	pldm_msgbuf_insert(buf, resp->completion_code);
190 	pldm_msgbuf_insert(buf, resp->handle);
191 	pldm_msgbuf_insert(buf, resp->option);
192 	pldm_msgbuf_insert(buf, resp->length);
193 
194 	switch (resp->option) {
195 	case PLDM_OEM_META_FILE_IO_READ_ATTR:
196 		pldm_msgbuf_insert(buf, resp->info.attr.size);
197 		pldm_msgbuf_insert(buf, resp->info.attr.crc32);
198 		break;
199 	case PLDM_OEM_META_FILE_IO_READ_DATA:
200 		pldm_msgbuf_insert(buf, resp->info.data.transferFlag);
201 		pldm_msgbuf_insert(buf, resp->info.data.offset);
202 		rc = pldm_msgbuf_insert_array_uint8(buf, resp->length,
203 						    resp->data,
204 						    resp_len - sizeof(*resp));
205 		if (rc) {
206 			return rc;
207 		}
208 		break;
209 	default:
210 		return -EPROTO;
211 	}
212 
213 	return pldm_msgbuf_destroy(buf);
214 }
215