at v2.6.12 128 lines 3.2 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/module.h> 9#include <linux/fs.h> 10#include <linux/miscdevice.h> 11#include <linux/delay.h> 12#include <asm/uaccess.h> 13#include "os.h" 14 15/* 16 * core module and version information 17 */ 18#define RNG_VERSION "1.0.0" 19#define RNG_MODULE_NAME "random" 20 21#define RNG_MISCDEV_MINOR 183 /* official */ 22 23static int random_fd = -1; 24 25static int rng_dev_open (struct inode *inode, struct file *filp) 26{ 27 /* enforce read-only access to this chrdev */ 28 if ((filp->f_mode & FMODE_READ) == 0) 29 return -EINVAL; 30 if (filp->f_mode & FMODE_WRITE) 31 return -EINVAL; 32 33 return 0; 34} 35 36static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, 37 loff_t * offp) 38{ 39 u32 data; 40 int n, ret = 0, have_data; 41 42 while(size){ 43 n = os_read_file(random_fd, &data, sizeof(data)); 44 if(n > 0){ 45 have_data = n; 46 while (have_data && size) { 47 if (put_user((u8)data, buf++)) { 48 ret = ret ? : -EFAULT; 49 break; 50 } 51 size--; 52 ret++; 53 have_data--; 54 data>>=8; 55 } 56 } 57 else if(n == -EAGAIN){ 58 if (filp->f_flags & O_NONBLOCK) 59 return ret ? : -EAGAIN; 60 61 if(need_resched()){ 62 current->state = TASK_INTERRUPTIBLE; 63 schedule_timeout(1); 64 } 65 } 66 else return n; 67 if (signal_pending (current)) 68 return ret ? : -ERESTARTSYS; 69 } 70 return ret; 71} 72 73static struct file_operations rng_chrdev_ops = { 74 .owner = THIS_MODULE, 75 .open = rng_dev_open, 76 .read = rng_dev_read, 77}; 78 79static struct miscdevice rng_miscdev = { 80 RNG_MISCDEV_MINOR, 81 RNG_MODULE_NAME, 82 &rng_chrdev_ops, 83}; 84 85/* 86 * rng_init - initialize RNG module 87 */ 88static int __init rng_init (void) 89{ 90 int err; 91 92 err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0); 93 if(err < 0) 94 goto out; 95 96 random_fd = err; 97 98 err = os_set_fd_block(random_fd, 0); 99 if(err) 100 goto err_out_cleanup_hw; 101 102 err = misc_register (&rng_miscdev); 103 if (err) { 104 printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); 105 goto err_out_cleanup_hw; 106 } 107 108 out: 109 return err; 110 111 err_out_cleanup_hw: 112 random_fd = -1; 113 goto out; 114} 115 116/* 117 * rng_cleanup - shutdown RNG module 118 */ 119static void __exit rng_cleanup (void) 120{ 121 misc_deregister (&rng_miscdev); 122} 123 124module_init (rng_init); 125module_exit (rng_cleanup); 126 127MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver"); 128MODULE_LICENSE("GPL");