blob: f190a4307bd10119afd619eb8b2d24ec71885286 [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>
Haojian Zhuang12ade162016-03-18 15:14:19 +08008#include <errno.h>
Haojian Zhuang12ade162016-03-18 15:14:19 +08009#include <string.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
11#include <platform_def.h>
12
13#include <common/debug.h>
14#include <drivers/io/io_block.h>
15#include <drivers/io/io_driver.h>
16#include <drivers/io/io_storage.h>
17#include <lib/utils.h>
Haojian Zhuang12ade162016-03-18 15:14:19 +080018
19typedef struct {
20 io_block_dev_spec_t *dev_spec;
21 uintptr_t base;
22 size_t file_pos;
23 size_t size;
24} block_dev_state_t;
25
26#define is_power_of_2(x) ((x != 0) && ((x & (x - 1)) == 0))
27
28io_type_t device_type_block(void);
29
30static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
31 io_entity_t *entity);
32static int block_seek(io_entity_t *entity, int mode, ssize_t offset);
33static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
34 size_t *length_read);
35static int block_write(io_entity_t *entity, const uintptr_t buffer,
36 size_t length, size_t *length_written);
37static int block_close(io_entity_t *entity);
38static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
39static int block_dev_close(io_dev_info_t *dev_info);
40
41static const io_dev_connector_t block_dev_connector = {
42 .dev_open = block_dev_open
43};
44
45static const io_dev_funcs_t block_dev_funcs = {
46 .type = device_type_block,
47 .open = block_open,
48 .seek = block_seek,
49 .size = NULL,
50 .read = block_read,
51 .write = block_write,
52 .close = block_close,
53 .dev_init = NULL,
54 .dev_close = block_dev_close,
55};
56
57static block_dev_state_t state_pool[MAX_IO_BLOCK_DEVICES];
58static io_dev_info_t dev_info_pool[MAX_IO_BLOCK_DEVICES];
59
60/* Track number of allocated block state */
61static unsigned int block_dev_count;
62
63io_type_t device_type_block(void)
64{
65 return IO_TYPE_BLOCK;
66}
67
68/* Locate a block state in the pool, specified by address */
69static int find_first_block_state(const io_block_dev_spec_t *dev_spec,
70 unsigned int *index_out)
71{
Yann Gautier37966212018-12-03 13:38:06 +010072 unsigned int index;
Haojian Zhuang12ade162016-03-18 15:14:19 +080073 int result = -ENOENT;
Yann Gautier37966212018-12-03 13:38:06 +010074
75 for (index = 0U; index < MAX_IO_BLOCK_DEVICES; ++index) {
Haojian Zhuang12ade162016-03-18 15:14:19 +080076 /* dev_spec is used as identifier since it's unique */
77 if (state_pool[index].dev_spec == dev_spec) {
78 result = 0;
79 *index_out = index;
80 break;
81 }
82 }
83 return result;
84}
85
86/* Allocate a device info from the pool and return a pointer to it */
87static int allocate_dev_info(io_dev_info_t **dev_info)
88{
89 int result = -ENOMEM;
90 assert(dev_info != NULL);
91
92 if (block_dev_count < MAX_IO_BLOCK_DEVICES) {
93 unsigned int index = 0;
94 result = find_first_block_state(NULL, &index);
95 assert(result == 0);
96 /* initialize dev_info */
97 dev_info_pool[index].funcs = &block_dev_funcs;
98 dev_info_pool[index].info = (uintptr_t)&state_pool[index];
99 *dev_info = &dev_info_pool[index];
100 ++block_dev_count;
101 }
102
103 return result;
104}
105
106
107/* Release a device info to the pool */
108static int free_dev_info(io_dev_info_t *dev_info)
109{
110 int result;
111 unsigned int index = 0;
112 block_dev_state_t *state;
113 assert(dev_info != NULL);
114
115 state = (block_dev_state_t *)dev_info->info;
116 result = find_first_block_state(state->dev_spec, &index);
117 if (result == 0) {
118 /* free if device info is valid */
Douglas Raillarda8954fc2017-01-26 15:54:44 +0000119 zeromem(state, sizeof(block_dev_state_t));
120 zeromem(dev_info, sizeof(io_dev_info_t));
Haojian Zhuang12ade162016-03-18 15:14:19 +0800121 --block_dev_count;
122 }
123
124 return result;
125}
126
127static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
128 io_entity_t *entity)
129{
130 block_dev_state_t *cur;
131 io_block_spec_t *region;
132
133 assert((dev_info->info != (uintptr_t)NULL) &&
134 (spec != (uintptr_t)NULL) &&
135 (entity->info == (uintptr_t)NULL));
136
137 region = (io_block_spec_t *)spec;
138 cur = (block_dev_state_t *)dev_info->info;
139 assert(((region->offset % cur->dev_spec->block_size) == 0) &&
140 ((region->length % cur->dev_spec->block_size) == 0));
141
142 cur->base = region->offset;
143 cur->size = region->length;
144 cur->file_pos = 0;
145
146 entity->info = (uintptr_t)cur;
147 return 0;
148}
149
150/* parameter offset is relative address at here */
151static int block_seek(io_entity_t *entity, int mode, ssize_t offset)
152{
153 block_dev_state_t *cur;
154
155 assert(entity->info != (uintptr_t)NULL);
156
157 cur = (block_dev_state_t *)entity->info;
158 assert((offset >= 0) && (offset < cur->size));
159
160 switch (mode) {
161 case IO_SEEK_SET:
162 cur->file_pos = offset;
163 break;
164 case IO_SEEK_CUR:
165 cur->file_pos += offset;
166 break;
167 default:
168 return -EINVAL;
169 }
170 assert(cur->file_pos < cur->size);
171 return 0;
172}
173
Roberto Vargas034c9f82017-11-23 12:03:46 +0000174/*
175 * This function allows the caller to read any number of bytes
176 * from any position. It hides from the caller that the low level
177 * driver only can read aligned blocks of data. For this reason
178 * we need to handle the use case where the first byte to be read is not
179 * aligned to start of the block, the last byte to be read is also not
180 * aligned to the end of a block, and there are zero or more blocks-worth
181 * of data in between.
182 *
183 * In such a case we need to read more bytes than requested (i.e. full
184 * blocks) and strip-out the leading bytes (aka skip) and the trailing
185 * bytes (aka padding). See diagram below
186 *
187 * cur->file_pos ------------
188 * |
189 * cur->base |
190 * | |
191 * v v<---- length ---->
192 * --------------------------------------------------------------
193 * | | block#1 | | block#n |
194 * | block#0 | + | ... | + |
195 * | | <- skip -> + | | + <- padding ->|
196 * ------------------------+----------------------+--------------
197 * ^ ^
198 * | |
199 * v iteration#1 iteration#n v
200 * --------------------------------------------------
201 * | | | |
202 * |<---- request ---->| ... |<----- request ---->|
203 * | | | |
204 * --------------------------------------------------
205 * / / | |
206 * / / | |
207 * / / | |
208 * / / | |
209 * / / | |
210 * / / | |
211 * / / | |
212 * / / | |
213 * / / | |
214 * / / | |
215 * <---- request ------> <------ request ----->
216 * --------------------- -----------------------
217 * | | | | | |
218 * |<-skip->|<-nbytes->| -------->|<-nbytes->|<-padding->|
219 * | | | | | | |
220 * --------------------- | -----------------------
221 * ^ \ \ | | |
222 * | \ \ | | |
223 * | \ \ | | |
224 * buf->offset \ \ buf->offset | |
225 * \ \ | |
226 * \ \ | |
227 * \ \ | |
228 * \ \ | |
229 * \ \ | |
230 * \ \ | |
231 * \ \ | |
232 * --------------------------------
233 * | | | |
234 * buffer-------------->| | ... | |
235 * | | | |
236 * --------------------------------
237 * <-count#1->| |
238 * <---------- count#n -------->
239 * <---------- length ---------->
240 *
241 * Additionally, the IO driver has an underlying buffer that is at least
242 * one block-size and may be big enough to allow.
243 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800244static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
245 size_t *length_read)
246{
247 block_dev_state_t *cur;
248 io_block_spec_t *buf;
249 io_block_ops_t *ops;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800250 int lba;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000251 size_t block_size, left;
252 size_t nbytes; /* number of bytes read in one iteration */
253 size_t request; /* number of requested bytes in one iteration */
254 size_t count; /* number of bytes already read */
255 /*
256 * number of leading bytes from start of the block
257 * to the first byte to be read
258 */
259 size_t skip;
260
261 /*
262 * number of trailing bytes between the last byte
263 * to be read and the end of the block
264 */
265 size_t padding;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800266
267 assert(entity->info != (uintptr_t)NULL);
268 cur = (block_dev_state_t *)entity->info;
269 ops = &(cur->dev_spec->ops);
270 buf = &(cur->dev_spec->buffer);
271 block_size = cur->dev_spec->block_size;
272 assert((length <= cur->size) &&
273 (length > 0) &&
274 (ops->read != 0));
275
Roberto Vargas034c9f82017-11-23 12:03:46 +0000276 /*
277 * We don't know the number of bytes that we are going
278 * to read in every iteration, because it will depend
279 * on the low level driver.
280 */
281 count = 0;
282 for (left = length; left > 0; left -= nbytes) {
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800283 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000284 * We must only request operations aligned to the block
285 * size. Therefore if file_pos is not block-aligned,
286 * we have to request the operation to start at the
287 * previous block boundary and skip the leading bytes. And
288 * similarly, the number of bytes requested must be a
289 * block size multiple
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800290 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000291 skip = cur->file_pos & (block_size - 1);
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800292
Roberto Vargas034c9f82017-11-23 12:03:46 +0000293 /*
294 * Calculate the block number containing file_pos
295 * - e.g. block 3.
296 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800297 lba = (cur->file_pos + cur->base) / block_size;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000298
299 if (skip + left > buf->length) {
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800300 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000301 * The underlying read buffer is too small to
302 * read all the required data - limit to just
303 * fill the buffer, and then read again.
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800304 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000305 request = buf->length;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800306 } else {
Roberto Vargas034c9f82017-11-23 12:03:46 +0000307 /*
308 * The underlying read buffer is big enough to
309 * read all the required data. Calculate the
310 * number of bytes to read to align with the
311 * block size.
312 */
313 request = skip + left;
314 request = (request + (block_size - 1)) & ~(block_size - 1);
315 }
316 request = ops->read(lba, buf->offset, request);
317
318 if (request <= skip) {
319 /*
320 * We couldn't read enough bytes to jump over
321 * the skip bytes, so we should have to read
322 * again the same block, thus generating
323 * the same error.
324 */
325 return -EIO;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800326 }
Roberto Vargas034c9f82017-11-23 12:03:46 +0000327
328 /*
329 * Need to remove skip and padding bytes,if any, from
330 * the read data when copying to the user buffer.
331 */
332 nbytes = request - skip;
333 padding = (nbytes > left) ? nbytes - left : 0;
334 nbytes -= padding;
335
336 memcpy((void *)(buffer + count),
337 (void *)(buf->offset + skip),
338 nbytes);
339
340 cur->file_pos += nbytes;
341 count += nbytes;
342 }
343 assert(count == length);
344 *length_read = count;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800345
346 return 0;
347}
348
Roberto Vargas034c9f82017-11-23 12:03:46 +0000349/*
350 * This function allows the caller to write any number of bytes
351 * from any position. It hides from the caller that the low level
352 * driver only can write aligned blocks of data.
353 * See comments for block_read for more details.
354 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800355static int block_write(io_entity_t *entity, const uintptr_t buffer,
356 size_t length, size_t *length_written)
357{
358 block_dev_state_t *cur;
359 io_block_spec_t *buf;
360 io_block_ops_t *ops;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800361 int lba;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000362 size_t block_size, left;
363 size_t nbytes; /* number of bytes read in one iteration */
364 size_t request; /* number of requested bytes in one iteration */
365 size_t count; /* number of bytes already read */
366 /*
367 * number of leading bytes from start of the block
368 * to the first byte to be read
369 */
370 size_t skip;
371
372 /*
373 * number of trailing bytes between the last byte
374 * to be read and the end of the block
375 */
376 size_t padding;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800377
378 assert(entity->info != (uintptr_t)NULL);
379 cur = (block_dev_state_t *)entity->info;
380 ops = &(cur->dev_spec->ops);
381 buf = &(cur->dev_spec->buffer);
382 block_size = cur->dev_spec->block_size;
383 assert((length <= cur->size) &&
384 (length > 0) &&
385 (ops->read != 0) &&
386 (ops->write != 0));
387
Roberto Vargas034c9f82017-11-23 12:03:46 +0000388 /*
389 * We don't know the number of bytes that we are going
390 * to write in every iteration, because it will depend
391 * on the low level driver.
392 */
393 count = 0;
394 for (left = length; left > 0; left -= nbytes) {
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800395 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000396 * We must only request operations aligned to the block
397 * size. Therefore if file_pos is not block-aligned,
398 * we have to request the operation to start at the
399 * previous block boundary and skip the leading bytes. And
400 * similarly, the number of bytes requested must be a
401 * block size multiple
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800402 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000403 skip = cur->file_pos & (block_size - 1);
Haojian Zhuangf800ccf2016-07-28 10:15:32 +0800404
Roberto Vargas034c9f82017-11-23 12:03:46 +0000405 /*
406 * Calculate the block number containing file_pos
407 * - e.g. block 3.
408 */
Haojian Zhuang12ade162016-03-18 15:14:19 +0800409 lba = (cur->file_pos + cur->base) / block_size;
Roberto Vargas034c9f82017-11-23 12:03:46 +0000410
411 if (skip + left > buf->length) {
412 /*
413 * The underlying read buffer is too small to
414 * read all the required data - limit to just
415 * fill the buffer, and then read again.
416 */
417 request = buf->length;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800418 } else {
Roberto Vargas034c9f82017-11-23 12:03:46 +0000419 /*
420 * The underlying read buffer is big enough to
421 * read all the required data. Calculate the
422 * number of bytes to read to align with the
423 * block size.
424 */
425 request = skip + left;
426 request = (request + (block_size - 1)) & ~(block_size - 1);
427 }
428
429 /*
430 * The number of bytes that we are going to write
431 * from the user buffer will depend of the size
432 * of the current request.
433 */
434 nbytes = request - skip;
435 padding = (nbytes > left) ? nbytes - left : 0;
436 nbytes -= padding;
437
438 /*
439 * If we have skip or padding bytes then we have to preserve
440 * some content and it means that we have to read before
441 * writing
442 */
443 if (skip > 0 || padding > 0) {
444 request = ops->read(lba, buf->offset, request);
445 /*
446 * The read may return size less than
447 * requested. Round down to the nearest block
448 * boundary
449 */
450 request &= ~(block_size-1);
451 if (request <= skip) {
Haojian Zhuang12ade162016-03-18 15:14:19 +0800452 /*
Roberto Vargas034c9f82017-11-23 12:03:46 +0000453 * We couldn't read enough bytes to jump over
454 * the skip bytes, so we should have to read
455 * again the same block, thus generating
456 * the same error.
Haojian Zhuang12ade162016-03-18 15:14:19 +0800457 */
Roberto Vargas034c9f82017-11-23 12:03:46 +0000458 return -EIO;
459 }
460 nbytes = request - skip;
461 padding = (nbytes > left) ? nbytes - left : 0;
462 nbytes -= padding;
Haojian Zhuang12ade162016-03-18 15:14:19 +0800463 }
Roberto Vargas034c9f82017-11-23 12:03:46 +0000464
465 memcpy((void *)(buf->offset + skip),
466 (void *)(buffer + count),
467 nbytes);
468
469 request = ops->write(lba, buf->offset, request);
470 if (request <= skip)
471 return -EIO;
472
473 /*
474 * And the previous write operation may modify the size
475 * of the request, so again, we have to calculate the
476 * number of bytes that we consumed from the user
477 * buffer
478 */
479 nbytes = request - skip;
480 padding = (nbytes > left) ? nbytes - left : 0;
481 nbytes -= padding;
482
483 cur->file_pos += nbytes;
484 count += nbytes;
485 }
486 assert(count == length);
487 *length_written = count;
488
Haojian Zhuang12ade162016-03-18 15:14:19 +0800489 return 0;
490}
491
492static int block_close(io_entity_t *entity)
493{
494 entity->info = (uintptr_t)NULL;
495 return 0;
496}
497
498static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info)
499{
500 block_dev_state_t *cur;
501 io_block_spec_t *buffer;
502 io_dev_info_t *info;
503 size_t block_size;
504 int result;
505
506 assert(dev_info != NULL);
507 result = allocate_dev_info(&info);
508 if (result)
509 return -ENOENT;
510
511 cur = (block_dev_state_t *)info->info;
512 /* dev_spec is type of io_block_dev_spec_t. */
513 cur->dev_spec = (io_block_dev_spec_t *)dev_spec;
514 buffer = &(cur->dev_spec->buffer);
515 block_size = cur->dev_spec->block_size;
516 assert((block_size > 0) &&
517 (is_power_of_2(block_size) != 0) &&
518 ((buffer->offset % block_size) == 0) &&
519 ((buffer->length % block_size) == 0));
520
521 *dev_info = info; /* cast away const */
522 (void)block_size;
523 (void)buffer;
524 return 0;
525}
526
527static int block_dev_close(io_dev_info_t *dev_info)
528{
529 return free_dev_info(dev_info);
530}
531
532/* Exported functions */
533
534/* Register the Block driver with the IO abstraction */
535int register_io_dev_block(const io_dev_connector_t **dev_con)
536{
537 int result;
538
539 assert(dev_con != NULL);
540
541 /*
542 * Since dev_info isn't really used in io_register_device, always
543 * use the same device info at here instead.
544 */
545 result = io_register_device(&dev_info_pool[0]);
546 if (result == 0)
547 *dev_con = &block_dev_connector;
548 return result;
549}