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