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