1 /*
2 * Copyright 2002-2013, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Jérôme Duval, korli@berlios.de
7 * Axel Dörfler, axeld@pinc-software.de
8 * David Reid
9 */
10
11
12 #include <stdio.h>
13
14 #include <device_manager.h>
15 #include <Drivers.h>
16 #include <generic_syscall.h>
17 #include <kernel.h>
18 #include <malloc.h>
19 #include <random_defs.h>
20 #include <string.h>
21 #include <util/AutoLock.h>
22
23 #include "yarrow_rng.h"
24
25
26 //#define TRACE_DRIVER
27 #ifdef TRACE_DRIVER
28 # define TRACE(x...) dprintf("random: " x)
29 #else
30 # define TRACE(x...) ;
31 #endif
32 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
33
34
35 #define RANDOM_DRIVER_MODULE_NAME "bus_managers/random/driver_v1"
36 #define RANDOM_DEVICE_MODULE_NAME "bus_managers/random/device_v1"
37
38
39 static mutex sRandomLock;
40 static void *sRandomCookie;
41 device_manager_info* gDeviceManager;
42
43
44 typedef struct {
45 device_node* node;
46 } random_driver_info;
47
48
49 static status_t
random_queue_randomness(uint64 value)50 random_queue_randomness(uint64 value)
51 {
52 MutexLocker locker(&sRandomLock);
53 RANDOM_ENQUEUE(value);
54 return B_OK;
55 }
56
57
58 // #pragma mark - device module API
59
60
61 static status_t
random_init_device(void * _info,void ** _cookie)62 random_init_device(void* _info, void** _cookie)
63 {
64 return B_OK;
65 }
66
67
68 static void
random_uninit_device(void * _cookie)69 random_uninit_device(void* _cookie)
70 {
71 }
72
73
74 static status_t
random_open(void * deviceCookie,const char * name,int flags,void ** cookie)75 random_open(void *deviceCookie, const char *name, int flags, void **cookie)
76 {
77 TRACE("open(\"%s\")\n", name);
78 return B_OK;
79 }
80
81
82 static status_t
random_read(void * cookie,off_t position,void * _buffer,size_t * _numBytes)83 random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes)
84 {
85 TRACE("read(%lld,, %ld)\n", position, *_numBytes);
86
87 MutexLocker locker(&sRandomLock);
88 return RANDOM_READ(sRandomCookie, _buffer, _numBytes);
89 }
90
91
92 static status_t
random_write(void * cookie,off_t position,const void * buffer,size_t * _numBytes)93 random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes)
94 {
95 TRACE("write(%lld,, %ld)\n", position, *_numBytes);
96 MutexLocker locker(&sRandomLock);
97 return RANDOM_WRITE(sRandomCookie, buffer, _numBytes);
98 }
99
100
101 static status_t
random_control(void * cookie,uint32 op,void * arg,size_t length)102 random_control(void *cookie, uint32 op, void *arg, size_t length)
103 {
104 TRACE("ioctl(%ld)\n", op);
105 return B_ERROR;
106 }
107
108
109 static status_t
random_generic_syscall(const char * subsystem,uint32 function,void * buffer,size_t bufferSize)110 random_generic_syscall(const char* subsystem, uint32 function, void* buffer,
111 size_t bufferSize)
112 {
113 switch (function) {
114 case RANDOM_GET_ENTROPY:
115 {
116 random_get_entropy_args args;
117 if (bufferSize != sizeof(args) || !IS_USER_ADDRESS(buffer))
118 return B_BAD_VALUE;
119
120 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
121 return B_BAD_ADDRESS;
122 if (!IS_USER_ADDRESS(args.buffer))
123 return B_BAD_ADDRESS;
124
125 status_t result = random_read(NULL, 0, args.buffer, &args.length);
126 if (result < 0)
127 return result;
128
129 return user_memcpy(buffer, &args, sizeof(args));
130 }
131 }
132 return B_BAD_HANDLER;
133 }
134
135
136 static status_t
random_close(void * cookie)137 random_close(void *cookie)
138 {
139 TRACE("close()\n");
140 return B_OK;
141 }
142
143
144 static status_t
random_free(void * cookie)145 random_free(void *cookie)
146 {
147 TRACE("free()\n");
148 return B_OK;
149 }
150
151
152 static status_t
random_select(void * cookie,uint8 event,selectsync * sync)153 random_select(void *cookie, uint8 event, selectsync *sync)
154 {
155 TRACE("select()\n");
156
157 if (event == B_SELECT_READ) {
158 /* tell there is already data to read */
159 notify_select_event(sync, event);
160 } else if (event == B_SELECT_WRITE) {
161 /* we're now writable */
162 notify_select_event(sync, event);
163 }
164 return B_OK;
165 }
166
167
168 static status_t
random_deselect(void * cookie,uint8 event,selectsync * sync)169 random_deselect(void *cookie, uint8 event, selectsync *sync)
170 {
171 TRACE("deselect()\n");
172 return B_OK;
173 }
174
175
176 // #pragma mark - driver module API
177
178
179 static float
random_supports_device(device_node * parent)180 random_supports_device(device_node *parent)
181 {
182 CALLED();
183 const char *bus;
184
185 // make sure parent is really device root
186 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
187 return -1;
188
189 if (strcmp(bus, "root"))
190 return 0.0;
191
192 return 1.0;
193 }
194
195
196 static status_t
random_register_device(device_node * node)197 random_register_device(device_node *node)
198 {
199 CALLED();
200
201 // ready to register
202 device_attr attrs[] = {
203 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "Random" }},
204 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_KEEP_DRIVER_LOADED }},
205 { NULL }
206 };
207
208 return gDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME,
209 attrs, NULL, NULL);
210 }
211
212
213 static status_t
random_init_driver(device_node * node,void ** cookie)214 random_init_driver(device_node *node, void **cookie)
215 {
216 CALLED();
217
218 random_driver_info* info = (random_driver_info*)malloc(
219 sizeof(random_driver_info));
220 if (info == NULL)
221 return B_NO_MEMORY;
222
223 mutex_init(&sRandomLock, "/dev/random lock");
224 RANDOM_INIT();
225
226 memset(info, 0, sizeof(*info));
227
228 info->node = node;
229
230 register_generic_syscall(RANDOM_SYSCALLS, random_generic_syscall, 1, 0);
231
232 *cookie = info;
233 return B_OK;
234 }
235
236
237 static void
random_uninit_driver(void * _cookie)238 random_uninit_driver(void *_cookie)
239 {
240 CALLED();
241
242 unregister_generic_syscall(RANDOM_SYSCALLS, 1);
243
244 RANDOM_UNINIT();
245
246 mutex_destroy(&sRandomLock);
247
248 random_driver_info* info = (random_driver_info*)_cookie;
249 free(info);
250 }
251
252
253 static status_t
random_register_child_devices(void * _cookie)254 random_register_child_devices(void* _cookie)
255 {
256 CALLED();
257 random_driver_info* info = (random_driver_info*)_cookie;
258 status_t status = gDeviceManager->publish_device(info->node, "random",
259 RANDOM_DEVICE_MODULE_NAME);
260 if (status == B_OK) {
261 gDeviceManager->publish_device(info->node, "urandom",
262 RANDOM_DEVICE_MODULE_NAME);
263 }
264 return status;
265 }
266
267
268 // #pragma mark -
269
270
271 module_dependency module_dependencies[] = {
272 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
273 {}
274 };
275
276
277 struct device_module_info sRandomDevice = {
278 {
279 RANDOM_DEVICE_MODULE_NAME,
280 0,
281 NULL
282 },
283
284 random_init_device,
285 random_uninit_device,
286 NULL, // remove,
287
288 random_open,
289 random_close,
290 random_free,
291 random_read,
292 random_write,
293 NULL,
294 random_control,
295
296 random_select,
297 random_deselect,
298 };
299
300
301 struct driver_module_info sRandomDriver = {
302 {
303 RANDOM_DRIVER_MODULE_NAME,
304 0,
305 NULL
306 },
307
308 random_supports_device,
309 random_register_device,
310 random_init_driver,
311 random_uninit_driver,
312 random_register_child_devices,
313 NULL, // rescan
314 NULL, // removed
315 };
316
317
318 random_for_controller_interface sRandomForControllerModule = {
319 {
320 {
321 RANDOM_FOR_CONTROLLER_MODULE_NAME,
322 0,
323 NULL
324 },
325
326 NULL, // supported devices
327 NULL,
328 NULL,
329 NULL,
330 NULL
331 },
332
333 random_queue_randomness,
334 };
335
336
337 module_info* modules[] = {
338 (module_info*)&sRandomDriver,
339 (module_info*)&sRandomDevice,
340 (module_info*)&sRandomForControllerModule,
341 NULL
342 };
343