1 /* 2 * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <string.h> 8 9 #include <common/debug.h> 10 #include <drivers/io/io_driver.h> 11 #include <drivers/io/io_storage.h> 12 13 #include "io_common.h" 14 #include "io_memdrv.h" 15 #include "io_private.h" 16 #include "rcar_def.h" 17 18 extern void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len); 19 20 static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), 21 io_dev_info_t **dev_info); 22 static int32_t memdrv_dev_close(io_dev_info_t *dev_info); 23 24 /* 25 * As we need to be able to keep state for seek, only one file can be open 26 * at a time. Make this a structure and point to the entity->info. When we 27 * can malloc memory we can change this to support more open files. 28 */ 29 typedef struct { 30 uint32_t in_use; 31 uintptr_t base; 32 signed long long file_pos; 33 } file_state_t; 34 35 static file_state_t current_file = { 0 }; 36 37 static io_type_t device_type_memdrv(void) 38 { 39 return IO_TYPE_MEMMAP; 40 } 41 42 static int32_t memdrv_block_open(io_dev_info_t *dev_info, const uintptr_t spec, 43 io_entity_t *entity) 44 { 45 const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; 46 47 /* 48 * Since we need to track open state for seek() we only allow one open 49 * spec at a time. When we have dynamic memory we can malloc and set 50 * entity->info. 51 */ 52 if (current_file.in_use != 0U) { 53 return IO_RESOURCES_EXHAUSTED; 54 } 55 56 /* File cursor offset for seek and incremental reads etc. */ 57 current_file.base = block_spec->offset; 58 current_file.file_pos = 0; 59 current_file.in_use = 1; 60 61 entity->info = (uintptr_t) ¤t_file; 62 63 return IO_SUCCESS; 64 } 65 66 static int32_t memdrv_block_seek(io_entity_t *entity, int32_t mode, 67 signed long long offset) 68 { 69 if (mode != IO_SEEK_SET) { 70 return IO_FAIL; 71 } 72 73 ((file_state_t *) entity->info)->file_pos = offset; 74 75 return IO_SUCCESS; 76 } 77 78 static int32_t memdrv_block_read(io_entity_t *entity, uintptr_t buffer, 79 size_t length, size_t *cnt) 80 { 81 file_state_t *fp; 82 83 fp = (file_state_t *) entity->info; 84 85 NOTICE("BL2: dst=0x%lx src=0x%llx len=%ld(0x%lx)\n", 86 buffer, (unsigned long long)fp->base + 87 (unsigned long long)fp->file_pos, length, length); 88 89 if (FLASH_MEMORY_SIZE < (fp->file_pos + (signed long long)length)) { 90 ERROR("BL2: check load image (source address)\n"); 91 return IO_FAIL; 92 } 93 94 rcar_dma_exec(buffer, fp->base + (uintptr_t)fp->file_pos, length); 95 fp->file_pos += (signed long long)length; 96 *cnt = length; 97 98 return IO_SUCCESS; 99 } 100 101 static int32_t memdrv_block_close(io_entity_t *entity) 102 { 103 entity->info = 0U; 104 105 memset((void *)¤t_file, 0, sizeof(current_file)); 106 107 return IO_SUCCESS; 108 } 109 110 static const io_dev_funcs_t memdrv_dev_funcs = { 111 .type = &device_type_memdrv, 112 .open = &memdrv_block_open, 113 .seek = &memdrv_block_seek, 114 .size = NULL, 115 .read = &memdrv_block_read, 116 .write = NULL, 117 .close = &memdrv_block_close, 118 .dev_init = NULL, 119 .dev_close = &memdrv_dev_close, 120 }; 121 122 static const io_dev_info_t memdrv_dev_info = { 123 .funcs = &memdrv_dev_funcs, 124 .info = 0, 125 }; 126 127 static const io_dev_connector_t memdrv_dev_connector = { 128 .dev_open = &memdrv_dev_open 129 }; 130 131 static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), 132 io_dev_info_t **dev_info) 133 { 134 *dev_info = (io_dev_info_t *) &memdrv_dev_info; 135 136 return IO_SUCCESS; 137 } 138 139 static int32_t memdrv_dev_close(io_dev_info_t *dev_info) 140 { 141 return IO_SUCCESS; 142 } 143 144 int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **dev_con) 145 { 146 int32_t result; 147 148 result = io_register_device(&memdrv_dev_info); 149 if (result == IO_SUCCESS) { 150 *dev_con = &memdrv_dev_connector; 151 } 152 153 return result; 154 } 155