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 39static mutex sRandomLock; 40static void *sRandomCookie; 41device_manager_info* gDeviceManager; 42 43 44typedef struct { 45 device_node* node; 46} random_driver_info; 47 48 49static status_t 50random_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 61static status_t 62random_init_device(void* _info, void** _cookie) 63{ 64 return B_OK; 65} 66 67 68static void 69random_uninit_device(void* _cookie) 70{ 71} 72 73 74static status_t 75random_open(void *deviceCookie, const char *name, int flags, void **cookie) 76{ 77 TRACE("open(\"%s\")\n", name); 78 return B_OK; 79} 80 81 82static status_t 83random_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 92static status_t 93random_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 101static status_t 102random_control(void *cookie, uint32 op, void *arg, size_t length) 103{ 104 TRACE("ioctl(%ld)\n", op); 105 return B_ERROR; 106} 107 108 109static status_t 110random_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 136static status_t 137random_close(void *cookie) 138{ 139 TRACE("close()\n"); 140 return B_OK; 141} 142 143 144static status_t 145random_free(void *cookie) 146{ 147 TRACE("free()\n"); 148 return B_OK; 149} 150 151 152static status_t 153random_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 168static status_t 169random_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 179static float 180random_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 196static status_t 197random_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 213static status_t 214random_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 237static void 238random_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 253static status_t 254random_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 271module_dependency module_dependencies[] = { 272 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, 273 {} 274}; 275 276 277struct 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 301struct 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 318random_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 337module_info* modules[] = { 338 (module_info*)&sRandomDriver, 339 (module_info*)&sRandomDevice, 340 (module_info*)&sRandomForControllerModule, 341 NULL 342}; 343