1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <debug.h> 9 #include <io_driver.h> 10 #include <io_dummy.h> 11 #include <io_storage.h> 12 #include <string.h> 13 14 struct file_state { 15 int in_use; 16 size_t size; 17 }; 18 19 static struct file_state current_file = {0}; 20 21 /* Identify the device type as dummy */ 22 static io_type_t device_type_dummy(void) 23 { 24 return IO_TYPE_DUMMY; 25 } 26 27 /* Dummy device functions */ 28 static int dummy_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); 29 static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, 30 io_entity_t *entity); 31 static int dummy_block_len(io_entity_t *entity, size_t *length); 32 static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, 33 size_t length, size_t *length_read); 34 static int dummy_block_close(io_entity_t *entity); 35 static int dummy_dev_close(io_dev_info_t *dev_info); 36 37 38 static const io_dev_connector_t dummy_dev_connector = { 39 .dev_open = dummy_dev_open 40 }; 41 42 43 static const io_dev_funcs_t dummy_dev_funcs = { 44 .type = device_type_dummy, 45 .open = dummy_block_open, 46 .seek = NULL, 47 .size = dummy_block_len, 48 .read = dummy_block_read, 49 .write = NULL, 50 .close = dummy_block_close, 51 .dev_init = NULL, 52 .dev_close = dummy_dev_close, 53 }; 54 55 56 static const io_dev_info_t dummy_dev_info = { 57 .funcs = &dummy_dev_funcs, 58 .info = (uintptr_t)NULL 59 }; 60 61 62 /* Open a connection to the dummy device */ 63 static int dummy_dev_open(const uintptr_t dev_spec __attribute__((unused)), 64 io_dev_info_t **dev_info) 65 { 66 assert(dev_info != NULL); 67 *dev_info = (io_dev_info_t *)&dummy_dev_info; 68 69 return 0; 70 } 71 72 73 /* Close a connection to the dummy device */ 74 static int dummy_dev_close(io_dev_info_t *dev_info) 75 { 76 return 0; 77 } 78 79 80 /* Open a file on the dummy device */ 81 static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, 82 io_entity_t *entity) 83 { 84 int result; 85 const io_block_spec_t *block_spec = (io_block_spec_t *)spec; 86 87 if (current_file.in_use == 0) { 88 assert(block_spec != NULL); 89 assert(entity != NULL); 90 91 current_file.in_use = 1; 92 current_file.size = block_spec->length; 93 entity->info = (uintptr_t)¤t_file; 94 result = 0; 95 } else { 96 WARN("A Dummy device is already active. Close first.\n"); 97 result = -ENOMEM; 98 } 99 100 return result; 101 } 102 103 104 /* Return the size of a file on the dummy device */ 105 static int dummy_block_len(io_entity_t *entity, size_t *length) 106 { 107 assert(entity != NULL); 108 assert(length != NULL); 109 110 *length = ((struct file_state *)entity->info)->size; 111 112 return 0; 113 } 114 115 116 /* Read data from a file on the dummy device */ 117 static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, 118 size_t length, size_t *length_read) 119 { 120 assert(length_read != NULL); 121 122 *length_read = length; 123 124 return 0; 125 } 126 127 128 /* Close a file on the dummy device */ 129 static int dummy_block_close(io_entity_t *entity) 130 { 131 assert(entity != NULL); 132 133 entity->info = 0; 134 current_file.in_use = 0; 135 136 return 0; 137 } 138 139 140 /* Exported functions */ 141 142 /* Register the dummy driver with the IO abstraction */ 143 int register_io_dev_dummy(const io_dev_connector_t **dev_con) 144 { 145 int result; 146 147 assert(dev_con != NULL); 148 149 result = io_register_device(&dummy_dev_info); 150 if (result == 0) 151 *dev_con = &dummy_dev_connector; 152 153 return result; 154 } 155