linux/arch/um/drivers/random.c

133 lines
3.3 KiB
C
Raw Normal View History

/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */
/* Much of this ripped from drivers/char/hw_random.c, see there for other
* copyright.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*/
uml: header untangling Untangle UML headers somewhat and add some includes where they were needed explicitly, but gotten accidentally via some other header. arch/um/include/um_uaccess.h loses asm/fixmap.h because it uses no fixmap stuff and gains elf.h, because it needs FIXADDR_USER_*, and archsetjmp.h, because it needs jmp_buf. pmd_alloc_one is uninlined because it needs mm_struct, and that's inconvenient to provide in asm-um/pgtable-3level.h. elf_core_copy_fpregs is also uninlined from elf-i386.h and elf-x86_64.h, which duplicated the code anyway, to arch/um/kernel/process.c, so that the reference to current_thread doesn't pull sched.h or anything related into asm/elf.h. arch/um/sys-i386/ldt.c, arch/um/kernel/tlb.c and arch/um/kernel/skas/uaccess.c got sched.h because they dereference task_structs. Its includes of linux and asm headers got turned from "" to <>. arch/um/sys-i386/bug.c gets asm/errno.h because it needs errno constants. asm/elf-i386 gets asm/user.h because it needs user_regs_struct. asm/fixmap.h gets page.h because it needs PAGE_SIZE and PAGE_MASK and system.h for BUG_ON. asm/pgtable doesn't need sched.h. asm/processor-generic.h defined mm_segment_t, but didn't use it. So, that definition is moved to uaccess.h, which defines a bunch of mm_segment_t-related stuff. thread_info.h uses mm_segment_t, and includes uaccess.h, which causes a recursion. So, the definition is placed above the include of thread_info. in uaccess.h. thread_info.h also gets page.h because it needs PAGE_SIZE. ObCheckpatchViolationJustification - I'm not adding a typedef; I'm moving mm_segment_t from one place to another. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-05 14:30:53 +08:00
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include "os.h"
/*
* core module and version information
*/
#define RNG_VERSION "1.0.0"
#define RNG_MODULE_NAME "random"
#define RNG_MISCDEV_MINOR 183 /* official */
/* Changed at init time, in the non-modular case, and at module load
* time, in the module case. Presumably, the module subsystem
* protects against a module being loaded twice at the same time.
*/
static int random_fd = -1;
static int rng_dev_open (struct inode *inode, struct file *filp)
{
/* enforce read-only access to this chrdev */
if ((filp->f_mode & FMODE_READ) == 0)
return -EINVAL;
if (filp->f_mode & FMODE_WRITE)
return -EINVAL;
return 0;
}
static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
loff_t * offp)
{
u32 data;
int n, ret = 0, have_data;
while(size){
n = os_read_file(random_fd, &data, sizeof(data));
if(n > 0){
have_data = n;
while (have_data && size) {
if (put_user((u8)data, buf++)) {
ret = ret ? : -EFAULT;
break;
}
size--;
ret++;
have_data--;
data>>=8;
}
}
else if(n == -EAGAIN){
if (filp->f_flags & O_NONBLOCK)
return ret ? : -EAGAIN;
if(need_resched())
schedule_timeout_interruptible(1);
}
else return n;
if (signal_pending (current))
return ret ? : -ERESTARTSYS;
}
return ret;
}
static const struct file_operations rng_chrdev_ops = {
.owner = THIS_MODULE,
.open = rng_dev_open,
.read = rng_dev_read,
};
/* rng_init shouldn't be called more than once at boot time */
static struct miscdevice rng_miscdev = {
RNG_MISCDEV_MINOR,
RNG_MODULE_NAME,
&rng_chrdev_ops,
};
/*
* rng_init - initialize RNG module
*/
static int __init rng_init (void)
{
int err;
err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
if(err < 0)
goto out;
random_fd = err;
err = os_set_fd_block(random_fd, 0);
if(err)
goto err_out_cleanup_hw;
err = misc_register (&rng_miscdev);
if (err) {
printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
goto err_out_cleanup_hw;
}
out:
return err;
err_out_cleanup_hw:
random_fd = -1;
goto out;
}
/*
* rng_cleanup - shutdown RNG module
*/
static void __exit rng_cleanup (void)
{
misc_deregister (&rng_miscdev);
}
module_init (rng_init);
module_exit (rng_cleanup);
MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
MODULE_LICENSE("GPL");