blob: 8226554d92eb9bbb6ab6d870228bc1fae1399a2d [file] [log] [blame]
Haojian Zhuang12ade162016-03-18 15:14:19 +08001/*
Douglas Raillarda8954fc2017-01-26 15:54:44 +00002 * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
Haojian Zhuang12ade162016-03-18 15:14:19 +08003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Haojian Zhuang12ade162016-03-18 15:14:19 +08005 */
6
7#include <assert.h>
8#include <debug.h>
9#include <errno.h>
10#include <io_block.h>
11#include <io_driver.h>
12#include <io_storage.h>
13#include <platform_def.h>
14#include <string.h>
Douglas Raillarda8954fc2017-01-26 15:54:44 +000015#include <utils.h>
Haojian Zhuang12ade162016-03-18 15:14:19 +080016
17typedef struct {
18 io_block_dev_spec_t *dev_spec;
19 uintptr_t base;
20 size_t file_pos;
21 size_t size;
22} block_dev_state_t;
23
24#define is_power_of_2(x) ((x != 0) && ((x & (x - 1)) == 0))
25
26io_type_t device_type_block(void);
27
28static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
29 io_entity_t *entity);
30static int block_seek(io_entity_t *entity, int mode, ssize_t offset);
31static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
32 size_t *length_read);
33static int block_write(io_entity_t *entity, const uintptr_t buffer,
34 size_t length, size_t *length_written);
35static int block_close(io_entity_t *entity);
36static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
37static int block_dev_close(io_dev_info_t *dev_info);
38
39static const io_dev_connector_t block_dev_connector = {
40 .dev_open = block_dev_open
41};
42
43static const io_dev_funcs_t block_dev_funcs = {
44 .type = device_type_block,
45 .open = block_open,
46 .seek = block_seek,
47 .size = NULL,
48 .read = block_read,
49 .write = block_write,
50 .close = block_close,
51 .dev_init = NULL,
52 .dev_close = block_dev_close,
53};
54
55static block_dev_state_t state_pool[MAX_IO_BLOCK_DEVICES];
56static io_dev_info_t dev_info_pool[MAX_IO_BLOCK_DEVICES];
57
58/* Track number of allocated block state */
59static unsigned int block_dev_count;
60
61io_type_t device_type_block(void)
62{
63 return IO_TYPE_BLOCK;
64}
65
66/* Locate a block state in the pool, specified by address */
67static int find_first_block_state(const io_block_dev_spec_t *dev_spec,
68 unsigned int *index_out)
69{
70 int result = -ENOENT;
71 for (int index = 0; index < MAX_IO_BLOCK_DEVICES; ++index) {
72 /* dev_spec is used as identifier since it's unique */
73 if (state_pool[index].dev_spec == dev_spec) {
74 result = 0;
75 *index_out = index;
76 break;
77 }
78 }
79 return result;
80}
81
82/* Allocate a device info from the pool and return a pointer to it */
83static int allocate_dev_info(io_dev_info_t **dev_info)
84{
85 int result = -ENOMEM;
86 assert(dev_info != NULL);
87
88 if (block_dev_count < MAX_IO_BLOCK_DEVICES) {
89 unsigned int index = 0;
90 result = find_first_block_state(NULL, &index);
91 assert(result == 0);
92 /* initialize dev_info */
93 dev_info_pool[index].funcs = &block_dev_funcs;
94 dev_info_pool[index].info = (uintptr_t)&state_pool[index];
95 *dev_info = &dev_info_pool[index];
96 ++block_dev_count;
97 }
98
99 return result;
100}
101
102
103/* Release a device info to the pool */
104static int free_dev_info(io_dev_info_t *dev_info)
105{
106 int result;
107 unsigned int index = 0;
108 block_dev_state_t *state;
109 assert(dev_info != NULL);
110
111 state = (block_dev_state_t *)dev_info->info;
112 result = find_first_block_state(state->dev_spec, &index);
113 if (result == 0) {
114 /* free if device info is valid */
Douglas Raillarda8954fc2017-01-26 15:54:44 +0000115 zeromem(state, sizeof(block_dev_state_t));
116 zeromem(dev_info, sizeof(io_dev_info_t));
Haojian Zhuang12ade162016-03-18 15:14:19 +0800117 --block_dev_count;
118 }
119
120 return result;
121}
122
123static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
124 io_entity_t *entity)
125{
126 block_dev_state_t *cur;
127 io_block_spec_t *region;
128
129 assert((dev_info->info != (uintptr_t)NULL) &&
130 (spec != (uintptr_t)NULL) &&
131 (entity->info == (uintptr_t)NULL));
132
133 region = (io_block_spec_t *)spec;
134 cur = (block_dev_state_t *)dev_info->info;
135 assert(((region->offset % cur->dev_spec->block_size) == 0) &&
136 ((region->length % cur->dev_spec->block_size) == 0));
137
138 cur->base = region->offset;
139 cur->size = region->length;
140 cur->file_pos = 0;
141
142 entity->info = (uintptr_t)cur;
143 return 0;
144}
145
146/* parameter offset is relative address at here */
147static int block_seek(io_entity_t *entity, int mode, ssize_t offset)
148{
149 block_dev_state_t *cur;
150
151 assert(entity->info != (uintptr_t)NULL);
152
153 cur = (block_dev_state_t *)entity->info;
154 assert((offset >= 0) && (offset < cur->size));
155
156 switch (mode) {
157 case IO_SEEK_SET:
158 cur->file_pos = offset;
159 break;
160 case IO_SEEK_CUR:
161 cur->file_pos += offset;
162 break;
163 default:
164 return -EINVAL;
165 }
166 assert(cur->file_pos < cur->size);
167 return 0;
168}
169
Roberto Vargas034c9f82017-11-23 12:03:46 +0000170/*
171 * This function allows the caller to read any number of bytes
172 * from any position. It hides from the caller that the low level
173 * driver only can read aligned blocks of data. For this reason
174 * we need to handle the use case where the first byte to be read is not
175 * aligned to start of the block, the last byte to be read is also not
176 * aligned to the end of a block, and there are zero or more blocks-worth
177 * of data in between.
178 *
179 * In such a case we need to read more bytes than requested (i.e. full
180 * blocks) and strip-out the leading bytes (aka skip) and the trailing
181 * bytes (aka padding). See diagram below
182 *
183 * cur->file_pos ------------
184 * |
185 * cur->base |
186 * | |
187 * v v<---- length ---->
188 * --------------------------------------------------------------
189 * | | block#1 | | block#n |
190 * | block#0 | + | ... | + |
191 * | | <- skip -> + | | + <- padding ->|
192 * ------------------------+----------------------+--------------
193 * ^ ^
194 * | |
195 * v iteration#1 iteration#n v
196 * --------------------------------------------------
197 * | | | |
198 * |<---- request ---->| ... |<----- request ---->|
199 * | | | |
200 * --------------------------------------------------
201 * / / | |
202 * / / | |
203 * / / | |
204 * / / | |
205 * / / | |
206 * / / | |
207 * / / | |
208 * / / | |
209 * / / | |
210 * / / | |
211 * <---- request ------> <------ request ----->
212 * --------------------- -----------------------
213 * | | | | | |
214 * |<-skip->|<-nbytes->| -------->|<-nbytes->|<-padding->|
215 * | | | | | | |
216 * --------------------- | -----------------------
217 * ^ \ \ | | |
218 * | \ \ | | |
219 * | \ \ | | |
220 * buf->offset \ \ buf->offset | |
221 * \ \ | |
222 * \ \ | |
223 * \ \ | |
224 * \ \ | |
225 * \ \ | |
226 * \ \ | |
227 * \ \ | |
228 * --------------------------------
229 * | | | |
230 * buffer-------------->| | ... | |
231 * | | | |
232 * --------------------------------
233 * <-count#1->| |
234 * <---------- count#n -------->
235 * <---------- length ---------->
236 *
237 * Additionally, the IO driver has an underlying buffer that is at least
238 * one block-size and may be big enough to allow.
239 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800240static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
241 size_t *length_read)
242{
243 block_dev_state_t *cur;
244 io_block_spec_t *buf;
245 io_block_ops_t *ops;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800246 int lba;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000247 size_t block_size, left;
248 size_t nbytes; /* number of bytes read in one iteration */
249 size_t request; /* number of requested bytes in one iteration */
250 size_t count; /* number of bytes already read */
251 /*
252 * number of leading bytes from start of the block
253 * to the first byte to be read
254 */
255 size_t skip;
256
257 /*
258 * number of trailing bytes between the last byte
259 * to be read and the end of the block
260 */
261 size_t padding;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800262
263 assert(entity->info != (uintptr_t)NULL);
264 cur = (block_dev_state_t *)entity->info;
265 ops = &(cur->dev_spec->ops);
266 buf = &(cur->dev_spec->buffer);
267 block_size = cur->dev_spec->block_size;
268 assert((length <= cur->size) &&
269 (length > 0) &&
270 (ops->read != 0));
271
Roberto Vargas034c9f82017-11-23 12:03:46 +0000272 /*
273 * We don't know the number of bytes that we are going
274 * to read in every iteration, because it will depend
275 * on the low level driver.
276 */
277 count = 0;
278 for (left = length; left > 0; left -= nbytes) {
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800279 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000280 * We must only request operations aligned to the block
281 * size. Therefore if file_pos is not block-aligned,
282 * we have to request the operation to start at the
283 * previous block boundary and skip the leading bytes. And
284 * similarly, the number of bytes requested must be a
285 * block size multiple
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800286 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000287 skip = cur->file_pos & (block_size - 1);
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800288
Roberto Vargas034c9f82017-11-23 12:03:46 +0000289 /*
290 * Calculate the block number containing file_pos
291 * - e.g. block 3.
292 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800293 lba = (cur->file_pos + cur->base) / block_size;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000294
295 if (skip + left > buf->length) {
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800296 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000297 * The underlying read buffer is too small to
298 * read all the required data - limit to just
299 * fill the buffer, and then read again.
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800300 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000301 request = buf->length;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800302 } else {
Roberto Vargas034c9f82017-11-23 12:03:46 +0000303 /*
304 * The underlying read buffer is big enough to
305 * read all the required data. Calculate the
306 * number of bytes to read to align with the
307 * block size.
308 */
309 request = skip + left;
310 request = (request + (block_size - 1)) & ~(block_size - 1);
311 }
312 request = ops->read(lba, buf->offset, request);
313
314 if (request <= skip) {
315 /*
316 * We couldn't read enough bytes to jump over
317 * the skip bytes, so we should have to read
318 * again the same block, thus generating
319 * the same error.
320 */
321 return -EIO;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800322 }
Roberto Vargas034c9f82017-11-23 12:03:46 +0000323
324 /*
325 * Need to remove skip and padding bytes,if any, from
326 * the read data when copying to the user buffer.
327 */
328 nbytes = request - skip;
329 padding = (nbytes > left) ? nbytes - left : 0;
330 nbytes -= padding;
331
332 memcpy((void *)(buffer + count),
333 (void *)(buf->offset + skip),
334 nbytes);
335
336 cur->file_pos += nbytes;
337 count += nbytes;
338 }
339 assert(count == length);
340 *length_read = count;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800341
342 return 0;
343}
344
Roberto Vargas034c9f82017-11-23 12:03:46 +0000345/*
346 * This function allows the caller to write any number of bytes
347 * from any position. It hides from the caller that the low level
348 * driver only can write aligned blocks of data.
349 * See comments for block_read for more details.
350 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800351static int block_write(io_entity_t *entity, const uintptr_t buffer,
352 size_t length, size_t *length_written)
353{
354 block_dev_state_t *cur;
355 io_block_spec_t *buf;
356 io_block_ops_t *ops;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800357 int lba;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000358 size_t block_size, left;
359 size_t nbytes; /* number of bytes read in one iteration */
360 size_t request; /* number of requested bytes in one iteration */
361 size_t count; /* number of bytes already read */
362 /*
363 * number of leading bytes from start of the block
364 * to the first byte to be read
365 */
366 size_t skip;
367
368 /*
369 * number of trailing bytes between the last byte
370 * to be read and the end of the block
371 */
372 size_t padding;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800373
374 assert(entity->info != (uintptr_t)NULL);
375 cur = (block_dev_state_t *)entity->info;
376 ops = &(cur->dev_spec->ops);
377 buf = &(cur->dev_spec->buffer);
378 block_size = cur->dev_spec->block_size;
379 assert((length <= cur->size) &&
380 (length > 0) &&
381 (ops->read != 0) &&
382 (ops->write != 0));
383
Roberto Vargas034c9f82017-11-23 12:03:46 +0000384 /*
385 * We don't know the number of bytes that we are going
386 * to write in every iteration, because it will depend
387 * on the low level driver.
388 */
389 count = 0;
390 for (left = length; left > 0; left -= nbytes) {
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800391 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000392 * We must only request operations aligned to the block
393 * size. Therefore if file_pos is not block-aligned,
394 * we have to request the operation to start at the
395 * previous block boundary and skip the leading bytes. And
396 * similarly, the number of bytes requested must be a
397 * block size multiple
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800398 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000399 skip = cur->file_pos & (block_size - 1);
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800400
Roberto Vargas034c9f82017-11-23 12:03:46 +0000401 /*
402 * Calculate the block number containing file_pos
403 * - e.g. block 3.
404 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800405 lba = (cur->file_pos + cur->base) / block_size;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000406
407 if (skip + left > buf->length) {
408 /*
409 * The underlying read buffer is too small to
410 * read all the required data - limit to just
411 * fill the buffer, and then read again.
412 */
413 request = buf->length;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800414 } else {
Roberto Vargas034c9f82017-11-23 12:03:46 +0000415 /*
416 * The underlying read buffer is big enough to
417 * read all the required data. Calculate the
418 * number of bytes to read to align with the
419 * block size.
420 */
421 request = skip + left;
422 request = (request + (block_size - 1)) & ~(block_size - 1);
423 }
424
425 /*
426 * The number of bytes that we are going to write
427 * from the user buffer will depend of the size
428 * of the current request.
429 */
430 nbytes = request - skip;
431 padding = (nbytes > left) ? nbytes - left : 0;
432 nbytes -= padding;
433
434 /*
435 * If we have skip or padding bytes then we have to preserve
436 * some content and it means that we have to read before
437 * writing
438 */
439 if (skip > 0 || padding > 0) {
440 request = ops->read(lba, buf->offset, request);
441 /*
442 * The read may return size less than
443 * requested. Round down to the nearest block
444 * boundary
445 */
446 request &= ~(block_size-1);
447 if (request <= skip) {
Haojian Zhuang12ade162016-03-18 15:14:19 +0800448 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000449 * We couldn't read enough bytes to jump over
450 * the skip bytes, so we should have to read
451 * again the same block, thus generating
452 * the same error.
Haojian Zhuang12ade162016-03-18 15:14:19 +0800453 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000454 return -EIO;
455 }
456 nbytes = request - skip;
457 padding = (nbytes > left) ? nbytes - left : 0;
458 nbytes -= padding;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800459 }
Roberto Vargas034c9f82017-11-23 12:03:46 +0000460
461 memcpy((void *)(buf->offset + skip),
462 (void *)(buffer + count),
463 nbytes);
464
465 request = ops->write(lba, buf->offset, request);
466 if (request <= skip)
467 return -EIO;
468
469 /*
470 * And the previous write operation may modify the size
471 * of the request, so again, we have to calculate the
472 * number of bytes that we consumed from the user
473 * buffer
474 */
475 nbytes = request - skip;
476 padding = (nbytes > left) ? nbytes - left : 0;
477 nbytes -= padding;
478
479 cur->file_pos += nbytes;
480 count += nbytes;
481 }
482 assert(count == length);
483 *length_written = count;
484
Haojian Zhuang12ade162016-03-18 15:14:19 +0800485 return 0;
486}
487
488static int block_close(io_entity_t *entity)
489{
490 entity->info = (uintptr_t)NULL;
491 return 0;
492}
493
494static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info)
495{
496 block_dev_state_t *cur;
497 io_block_spec_t *buffer;
498 io_dev_info_t *info;
499 size_t block_size;
500 int result;
501
502 assert(dev_info != NULL);
503 result = allocate_dev_info(&info);
504 if (result)
505 return -ENOENT;
506
507 cur = (block_dev_state_t *)info->info;
508 /* dev_spec is type of io_block_dev_spec_t. */
509 cur->dev_spec = (io_block_dev_spec_t *)dev_spec;
510 buffer = &(cur->dev_spec->buffer);
511 block_size = cur->dev_spec->block_size;
512 assert((block_size > 0) &&
513 (is_power_of_2(block_size) != 0) &&
514 ((buffer->offset % block_size) == 0) &&
515 ((buffer->length % block_size) == 0));
516
517 *dev_info = info; /* cast away const */
518 (void)block_size;
519 (void)buffer;
520 return 0;
521}
522
523static int block_dev_close(io_dev_info_t *dev_info)
524{
525 return free_dev_info(dev_info);
526}
527
528/* Exported functions */
529
530/* Register the Block driver with the IO abstraction */
531int register_io_dev_block(const io_dev_connector_t **dev_con)
532{
533 int result;
534
535 assert(dev_con != NULL);
536
537 /*
538 * Since dev_info isn't really used in io_register_device, always
539 * use the same device info at here instead.
540 */
541 result = io_register_device(&dev_info_pool[0]);
542 if (result == 0)
543 *dev_con = &block_dev_connector;
544 return result;
545}