1 /*
2  * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "rpc_caller_session.h"
12 #include "block_storage_client.h"
13 #include "protocols/rpc/common/packed-c/status.h"
14 #include "protocols/service/block_storage/packed-c/messages.h"
15 #include "protocols/service/block_storage/packed-c/opcodes.h"
16 
block_storage_client_get_partition_info(void * context,const struct uuid_octets * partition_guid,struct storage_partition_info * info)17 static psa_status_t block_storage_client_get_partition_info(void *context,
18 	const struct uuid_octets *partition_guid,
19 	struct storage_partition_info *info)
20 {
21 	struct block_storage_client *this_context = (struct block_storage_client *)context;
22 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
23 	struct ts_block_storage_get_partition_info_in req_msg = {0};
24 	size_t req_len = sizeof(req_msg);
25 	uint8_t *req_buf = NULL;
26 
27 	memcpy(req_msg.partition_guid, partition_guid->octets, sizeof(req_msg.partition_guid));
28 
29 	rpc_call_handle call_handle =
30 		rpc_caller_session_begin(this_context->client.session, &req_buf, req_len,
31 					 sizeof(struct ts_block_storage_get_partition_info_out));
32 
33 	if (call_handle) {
34 		uint8_t *resp_buf = NULL;
35 		size_t resp_len = 0;
36 		service_status_t service_status = 0;
37 
38 		memcpy(req_buf, &req_msg, req_len);
39 
40 		this_context->client.rpc_status = rpc_caller_session_invoke(
41 			call_handle, TS_BLOCK_STORAGE_OPCODE_GET_PARTITION_INFO, &resp_buf,
42 			&resp_len, &service_status);
43 
44 		if (this_context->client.rpc_status == RPC_SUCCESS) {
45 
46 			psa_status = service_status;
47 
48 			if (psa_status == PSA_SUCCESS) {
49 
50 				if (resp_len >=
51 				    sizeof(struct ts_block_storage_get_partition_info_out)) {
52 
53 					struct ts_block_storage_get_partition_info_out resp_msg;
54 
55 					memcpy(&resp_msg, resp_buf, sizeof(resp_msg));
56 
57 					info->block_size = resp_msg.block_size;
58 					info->num_blocks = resp_msg.num_blocks;
59 
60 					memcpy(info->partition_guid.octets,
61 						resp_msg.partition_guid,
62 						TS_BLOCK_STORAGE_GUID_OCTET_LEN);
63 
64 					memcpy(info->parent_guid.octets,
65 						resp_msg.parent_guid,
66 						TS_BLOCK_STORAGE_GUID_OCTET_LEN);
67 				}
68 				else {
69 					/* Failed to decode response message */
70 					psa_status = PSA_ERROR_GENERIC_ERROR;
71 				}
72 			}
73 		}
74 
75 		rpc_caller_session_end(call_handle);
76 	} else {
77 
78 		this_context->client.rpc_status = RPC_ERROR_INTERNAL;
79 	}
80 
81 	return psa_status;
82 }
83 
block_storage_client_open(void * context,uint32_t client_id,const struct uuid_octets * partition_guid,storage_partition_handle_t * handle)84 static psa_status_t block_storage_client_open(void *context,
85 	uint32_t client_id,
86 	const struct uuid_octets *partition_guid,
87 	storage_partition_handle_t *handle)
88 {
89 	struct block_storage_client *this_context = (struct block_storage_client *)context;
90 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
91 	struct ts_block_storage_open_in req_msg = {0};
92 	size_t req_len = sizeof(req_msg);
93 	uint8_t *req_buf = NULL;
94 
95 	(void)client_id;
96 
97 	memcpy(req_msg.partition_guid, partition_guid->octets, sizeof(req_msg.partition_guid));
98 
99 	rpc_call_handle call_handle =
100 		rpc_caller_session_begin(this_context->client.session, &req_buf, req_len,
101 					 sizeof(struct ts_block_storage_open_out));
102 
103 	if (call_handle) {
104 
105 		uint8_t *resp_buf = NULL;
106 		size_t resp_len = 0;
107 		service_status_t service_status = 0;
108 
109 		memcpy(req_buf, &req_msg, req_len);
110 
111 		this_context->client.rpc_status = rpc_caller_session_invoke(
112 			call_handle, TS_BLOCK_STORAGE_OPCODE_OPEN, &resp_buf, &resp_len,
113 			&service_status);
114 
115 		if (this_context->client.rpc_status == RPC_SUCCESS) {
116 
117 			psa_status = service_status;
118 
119 			if (psa_status == PSA_SUCCESS) {
120 
121 				if (resp_len >= sizeof(struct ts_block_storage_open_out)) {
122 
123 					struct ts_block_storage_open_out resp_msg;
124 
125 					memcpy(&resp_msg, resp_buf, sizeof(resp_msg));
126 					*handle = resp_msg.handle;
127 				} else {
128 					/* Failed to decode response message */
129 					psa_status = PSA_ERROR_GENERIC_ERROR;
130 				}
131 			}
132 		}
133 
134 		rpc_caller_session_end(call_handle);
135 	} else {
136 
137 		this_context->client.rpc_status = RPC_ERROR_INTERNAL;
138 	}
139 
140 	return psa_status;
141 }
142 
block_storage_client_close(void * context,uint32_t client_id,storage_partition_handle_t handle)143 static psa_status_t block_storage_client_close(void *context,
144 	uint32_t client_id,
145 	storage_partition_handle_t handle)
146 {
147 	struct block_storage_client *this_context = (struct block_storage_client *)context;
148 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
149 	struct ts_block_storage_close_in req_msg = {0};
150 	size_t req_len = sizeof(req_msg);
151 	uint8_t *req_buf = NULL;
152 
153 	(void)client_id;
154 
155 	req_msg.handle = handle;
156 
157 	rpc_call_handle call_handle =
158 		rpc_caller_session_begin(this_context->client.session, &req_buf, req_len, 0);
159 
160 	if (call_handle) {
161 
162 		uint8_t *resp_buf = NULL;
163 		size_t resp_len = 0;
164 		service_status_t service_status = 0;
165 
166 		memcpy(req_buf, &req_msg, req_len);
167 
168 		this_context->client.rpc_status = rpc_caller_session_invoke(
169 			call_handle, TS_BLOCK_STORAGE_OPCODE_CLOSE,
170 			&resp_buf, &resp_len, &service_status);
171 
172 		if (this_context->client.rpc_status == RPC_SUCCESS)
173 			psa_status = service_status;
174 
175 		rpc_caller_session_end(call_handle);
176 	} else {
177 
178 		this_context->client.rpc_status = RPC_ERROR_INTERNAL;
179 	}
180 
181 	return psa_status;
182 }
183 
block_storage_client_read(void * context,uint32_t client_id,storage_partition_handle_t handle,uint64_t lba,size_t offset,size_t buffer_size,uint8_t * buffer,size_t * data_len)184 static psa_status_t block_storage_client_read(void *context,
185 	uint32_t client_id,
186 	storage_partition_handle_t handle,
187 	uint64_t lba,
188 	size_t offset,
189 	size_t buffer_size,
190 	uint8_t *buffer,
191 	size_t *data_len)
192 {
193 	struct block_storage_client *this_context = (struct block_storage_client *)context;
194 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
195 	struct ts_block_storage_read_in req_msg = {0};
196 	size_t req_len = sizeof(req_msg);
197 	uint8_t *req_buf = NULL;
198 
199 	(void)client_id;
200 
201 	*data_len = 0;
202 
203 	req_msg.handle = handle;
204 	req_msg.lba = lba;
205 	req_msg.offset = offset;
206 	req_msg.len = buffer_size;
207 
208 	rpc_call_handle call_handle =
209 		rpc_caller_session_begin(this_context->client.session, &req_buf, req_len,
210 					 buffer_size);
211 
212 	if (call_handle) {
213 
214 		uint8_t *resp_buf = NULL;
215 		size_t resp_len = 0;
216 		service_status_t service_status = 0;
217 
218 		memcpy(req_buf, &req_msg, req_len);
219 
220 		this_context->client.rpc_status = rpc_caller_session_invoke(
221 			call_handle, TS_BLOCK_STORAGE_OPCODE_READ, &resp_buf, &resp_len,
222 			&service_status);
223 
224 		if (this_context->client.rpc_status == RPC_SUCCESS) {
225 
226 			psa_status = service_status;
227 
228 			if (psa_status == PSA_SUCCESS) {
229 
230 				if (resp_len <= buffer_size) {
231 
232 					memcpy(buffer, resp_buf, resp_len);
233 					*data_len = resp_len;
234 				} else {
235 
236 					psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
237 				}
238 			}
239 		}
240 
241 		rpc_caller_session_end(call_handle);
242 	} else {
243 
244 		this_context->client.rpc_status = RPC_ERROR_INTERNAL;
245 	}
246 
247 	return psa_status;
248 }
249 
block_storage_client_write(void * context,uint32_t client_id,storage_partition_handle_t handle,uint64_t lba,size_t offset,const uint8_t * data,size_t data_len,size_t * num_written)250 static psa_status_t block_storage_client_write(void *context,
251 	uint32_t client_id,
252 	storage_partition_handle_t handle,
253 	uint64_t lba,
254 	size_t offset,
255 	const uint8_t *data,
256 	size_t data_len,
257 	size_t *num_written)
258 {
259 	struct block_storage_client *this_context = (struct block_storage_client *)context;
260 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
261 	struct ts_block_storage_write_in req_msg = {0};
262 	size_t req_len = sizeof(req_msg) + data_len;
263 	uint8_t *req_buf = NULL;
264 
265 	(void)client_id;
266 
267 	req_msg.handle = handle;
268 	req_msg.lba = lba;
269 	req_msg.offset = offset;
270 
271 	rpc_call_handle call_handle =
272 		rpc_caller_session_begin(this_context->client.session, &req_buf, req_len,
273 					 sizeof(struct ts_block_storage_write_out));
274 
275 	if (call_handle) {
276 		uint8_t *resp_buf = NULL;
277 		size_t resp_len = 0;
278 		service_status_t service_status = 0;
279 
280 		/* Copy fixed size message */
281 		memcpy(req_buf, &req_msg, sizeof(req_msg));
282 
283 		/* Copy variable length data */
284 		memcpy(&req_buf[sizeof(req_msg)], data, data_len);
285 
286 		this_context->client.rpc_status = rpc_caller_session_invoke(
287 			call_handle, TS_BLOCK_STORAGE_OPCODE_WRITE,
288 			&resp_buf, &resp_len, &service_status);
289 
290 		if (this_context->client.rpc_status == RPC_SUCCESS) {
291 
292 			psa_status = service_status;
293 
294 			if (psa_status == PSA_SUCCESS) {
295 
296 				if (resp_len >= sizeof(struct ts_block_storage_write_out)) {
297 
298 					struct ts_block_storage_write_out resp_msg;
299 
300 					memcpy(&resp_msg, resp_buf, sizeof(resp_msg));
301 					*num_written = resp_msg.num_written;
302 				} else {
303 					/* Failed to decode response message */
304 					psa_status = PSA_ERROR_GENERIC_ERROR;
305 				}
306 			}
307 		}
308 
309 		rpc_caller_session_end(call_handle);
310 	} else {
311 
312 		this_context->client.rpc_status = RPC_ERROR_INTERNAL;
313 	}
314 
315 	return psa_status;
316 }
317 
block_storage_client_erase(void * context,uint32_t client_id,storage_partition_handle_t handle,uint64_t begin_lba,size_t num_blocks)318 static psa_status_t block_storage_client_erase(void *context,
319 	uint32_t client_id,
320 	storage_partition_handle_t handle,
321 	uint64_t begin_lba,
322 	size_t num_blocks)
323 {
324 	struct block_storage_client *this_context = (struct block_storage_client *)context;
325 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
326 	struct ts_block_storage_erase_in req_msg = {0};
327 	size_t req_len = sizeof(req_msg);
328 	uint8_t *req_buf = NULL;
329 
330 	(void)client_id;
331 
332 	req_msg.handle = handle;
333 	req_msg.begin_lba = begin_lba;
334 	req_msg.num_blocks = num_blocks;
335 
336 	rpc_call_handle call_handle =
337 		rpc_caller_session_begin(this_context->client.session, &req_buf, req_len, 0);
338 
339 	if (call_handle) {
340 
341 		uint8_t *resp_buf = NULL;
342 		size_t resp_len = 0;
343 		service_status_t service_status = 0;
344 
345 		/* Copy fixed size message */
346 		memcpy(req_buf, &req_msg, sizeof(req_msg));
347 
348 		this_context->client.rpc_status = rpc_caller_session_invoke(
349 			call_handle, TS_BLOCK_STORAGE_OPCODE_ERASE,
350 			&resp_buf, &resp_len, &service_status);
351 
352 		if (this_context->client.rpc_status == RPC_SUCCESS)
353 			psa_status = service_status;
354 
355 		rpc_caller_session_end(call_handle);
356 	} else {
357 
358 		this_context->client.rpc_status = RPC_ERROR_INTERNAL;
359 	}
360 
361 	return psa_status;
362 }
363 
block_storage_client_init(struct block_storage_client * block_storage_client,struct rpc_caller_session * session)364 struct block_store *block_storage_client_init(
365 	struct block_storage_client *block_storage_client,
366 	struct rpc_caller_session *session)
367 {
368 	service_client_init(&block_storage_client->client, session);
369 
370 	/* Define concrete block store interface */
371 	static const struct block_store_interface interface = {
372 		block_storage_client_get_partition_info,
373 		block_storage_client_open,
374 		block_storage_client_close,
375 		block_storage_client_read,
376 		block_storage_client_write,
377 		block_storage_client_erase
378 	};
379 
380 	/* Initialize base block_store */
381 	block_storage_client->base_block_store.context = block_storage_client;
382 	block_storage_client->base_block_store.interface = &interface;
383 
384 	return &block_storage_client->base_block_store;
385 }
386 
block_storage_client_deinit(struct block_storage_client * block_storage_client)387 void block_storage_client_deinit(
388 	struct block_storage_client *block_storage_client)
389 {
390 	service_client_deinit(&block_storage_client->client);
391 }
392