at v2.6.25 132 lines 3.4 kB view raw
1/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */ 2/* Much of this ripped from drivers/char/hw_random.c, see there for other 3 * copyright. 4 * 5 * This software may be used and distributed according to the terms 6 * of the GNU General Public License, incorporated herein by reference. 7 */ 8#include <linux/sched.h> 9#include <linux/module.h> 10#include <linux/fs.h> 11#include <linux/miscdevice.h> 12#include <linux/delay.h> 13#include <asm/uaccess.h> 14#include "os.h" 15 16/* 17 * core module and version information 18 */ 19#define RNG_VERSION "1.0.0" 20#define RNG_MODULE_NAME "random" 21 22#define RNG_MISCDEV_MINOR 183 /* official */ 23 24/* Changed at init time, in the non-modular case, and at module load 25 * time, in the module case. Presumably, the module subsystem 26 * protects against a module being loaded twice at the same time. 27 */ 28static int random_fd = -1; 29 30static int rng_dev_open (struct inode *inode, struct file *filp) 31{ 32 /* enforce read-only access to this chrdev */ 33 if ((filp->f_mode & FMODE_READ) == 0) 34 return -EINVAL; 35 if (filp->f_mode & FMODE_WRITE) 36 return -EINVAL; 37 38 return 0; 39} 40 41static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, 42 loff_t * offp) 43{ 44 u32 data; 45 int n, ret = 0, have_data; 46 47 while(size){ 48 n = os_read_file(random_fd, &data, sizeof(data)); 49 if(n > 0){ 50 have_data = n; 51 while (have_data && size) { 52 if (put_user((u8)data, buf++)) { 53 ret = ret ? : -EFAULT; 54 break; 55 } 56 size--; 57 ret++; 58 have_data--; 59 data>>=8; 60 } 61 } 62 else if(n == -EAGAIN){ 63 if (filp->f_flags & O_NONBLOCK) 64 return ret ? : -EAGAIN; 65 66 if(need_resched()) 67 schedule_timeout_interruptible(1); 68 } 69 else return n; 70 if (signal_pending (current)) 71 return ret ? : -ERESTARTSYS; 72 } 73 return ret; 74} 75 76static const struct file_operations rng_chrdev_ops = { 77 .owner = THIS_MODULE, 78 .open = rng_dev_open, 79 .read = rng_dev_read, 80}; 81 82/* rng_init shouldn't be called more than once at boot time */ 83static struct miscdevice rng_miscdev = { 84 RNG_MISCDEV_MINOR, 85 RNG_MODULE_NAME, 86 &rng_chrdev_ops, 87}; 88 89/* 90 * rng_init - initialize RNG module 91 */ 92static int __init rng_init (void) 93{ 94 int err; 95 96 err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0); 97 if(err < 0) 98 goto out; 99 100 random_fd = err; 101 102 err = os_set_fd_block(random_fd, 0); 103 if(err) 104 goto err_out_cleanup_hw; 105 106 err = misc_register (&rng_miscdev); 107 if (err) { 108 printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); 109 goto err_out_cleanup_hw; 110 } 111 112 out: 113 return err; 114 115 err_out_cleanup_hw: 116 random_fd = -1; 117 goto out; 118} 119 120/* 121 * rng_cleanup - shutdown RNG module 122 */ 123static void __exit rng_cleanup (void) 124{ 125 misc_deregister (&rng_miscdev); 126} 127 128module_init (rng_init); 129module_exit (rng_cleanup); 130 131MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver"); 132MODULE_LICENSE("GPL");