blob: e2458de7fa1b2c818690213fe207a7cb7657c15c [file] [log] [blame]
Gerald Lejeune339f5592015-07-21 14:15:12 +02001/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <assert.h>
32#include <debug.h>
33#include <io_driver.h>
34#include <io_storage.h>
35#include <string.h>
36
37struct file_state {
38 int in_use;
39 size_t size;
40};
41
42static struct file_state current_file = {0};
43
44/* Identify the device type as dummy */
45io_type_t device_type_dummy(void)
46{
47 return IO_TYPE_DUMMY;
48}
49
50/* Dummy device functions */
51static int dummy_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
52static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
53 io_entity_t *entity);
54static int dummy_block_len(io_entity_t *entity, size_t *length);
55static int dummy_block_read(io_entity_t *entity, uintptr_t buffer,
56 size_t length, size_t *length_read);
57static int dummy_block_close(io_entity_t *entity);
58static int dummy_dev_close(io_dev_info_t *dev_info);
59
60
61static const io_dev_connector_t dummy_dev_connector = {
62 .dev_open = dummy_dev_open
63};
64
65
66static const io_dev_funcs_t dummy_dev_funcs = {
67 .type = device_type_dummy,
68 .open = dummy_block_open,
69 .seek = NULL,
70 .size = dummy_block_len,
71 .read = dummy_block_read,
72 .write = NULL,
73 .close = dummy_block_close,
74 .dev_init = NULL,
75 .dev_close = dummy_dev_close,
76};
77
78
79static const io_dev_info_t dummy_dev_info = {
80 .funcs = &dummy_dev_funcs,
81 .info = (uintptr_t)NULL
82};
83
84
85/* Open a connection to the dummy device */
86static int dummy_dev_open(const uintptr_t dev_spec __attribute__((unused)),
87 io_dev_info_t **dev_info)
88{
89 assert(dev_info != NULL);
90 *dev_info = (io_dev_info_t *)&dummy_dev_info;
91
92 return 0;
93}
94
95
96/* Close a connection to the dummy device */
97static int dummy_dev_close(io_dev_info_t *dev_info)
98{
99 return 0;
100}
101
102
103/* Open a file on the dummy device */
104static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
105 io_entity_t *entity)
106{
107 int result;
108 const io_block_spec_t *block_spec = (io_block_spec_t *)spec;
109
110 if (current_file.in_use == 0) {
111 assert(block_spec != NULL);
112 assert(entity != NULL);
113
114 current_file.in_use = 1;
115 current_file.size = block_spec->length;
116 entity->info = (uintptr_t)&current_file;
117 result = 0;
118 } else {
119 WARN("A Dummy device is already active. Close first.\n");
120 result = -ENOMEM;
121 }
122
123 return result;
124}
125
126
127/* Return the size of a file on the dummy device */
128static int dummy_block_len(io_entity_t *entity, size_t *length)
129{
130 assert(entity != NULL);
131 assert(length != NULL);
132
133 *length = ((struct file_state *)entity->info)->size;
134
135 return 0;
136}
137
138
139/* Read data from a file on the dummy device */
140static int dummy_block_read(io_entity_t *entity, uintptr_t buffer,
141 size_t length, size_t *length_read)
142{
143 assert(length_read != NULL);
144
145 *length_read = length;
146
147 return 0;
148}
149
150
151/* Close a file on the dummy device */
152static int dummy_block_close(io_entity_t *entity)
153{
154 assert(entity != NULL);
155
156 entity->info = 0;
157 current_file.in_use = 0;
158
159 return 0;
160}
161
162
163/* Exported functions */
164
165/* Register the dummy driver with the IO abstraction */
166int register_io_dev_dummy(const io_dev_connector_t **dev_con)
167{
168 int result;
169
170 assert(dev_con != NULL);
171
172 result = io_register_device(&dummy_dev_info);
173 if (result == 0)
174 *dev_con = &dummy_dev_connector;
175
176 return result;
177}