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 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 62 random_init_device(void* _info, void** _cookie) 63 { 64 return B_OK; 65 } 66 67 68 static void 69 random_uninit_device(void* _cookie) 70 { 71 } 72 73 74 static status_t 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 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 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 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 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 137 random_close(void *cookie) 138 { 139 TRACE("close()\n"); 140 return B_OK; 141 } 142 143 144 static status_t 145 random_free(void *cookie) 146 { 147 TRACE("free()\n"); 148 return B_OK; 149 } 150 151 152 static status_t 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 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 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 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 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 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 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