2005-05-28 15:51:58 -07:00
/* 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-04 22:30:53 -08:00
# include <linux/sched.h>
2005-04-16 15:20:36 -07:00
# 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 */
2006-09-29 01:58:50 -07:00
/* 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 .
*/
2005-04-16 15:20:36 -07:00
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 ) {
2007-05-06 14:51:43 -07:00
n = os_read_file ( random_fd , & data , sizeof ( data ) ) ;
2005-04-16 15:20:36 -07:00
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 ;
2005-11-07 01:01:14 -08:00
if ( need_resched ( ) )
schedule_timeout_interruptible ( 1 ) ;
2005-04-16 15:20:36 -07:00
}
else return n ;
if ( signal_pending ( current ) )
return ret ? : - ERESTARTSYS ;
}
return ret ;
}
2006-09-27 01:50:33 -07:00
static const struct file_operations rng_chrdev_ops = {
2005-04-16 15:20:36 -07:00
. owner = THIS_MODULE ,
. open = rng_dev_open ,
. read = rng_dev_read ,
} ;
2007-02-10 01:44:05 -08:00
/* rng_init shouldn't be called more than once at boot time */
2005-04-16 15:20:36 -07:00
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 ) {
2005-05-28 15:51:58 -07:00
printk ( KERN_ERR RNG_MODULE_NAME " : misc device register failed \n " ) ;
2005-04-16 15:20:36 -07:00
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 ) ;
2005-05-28 15:51:58 -07:00
MODULE_DESCRIPTION ( " UML Host Random Number Generator (RNG) driver " ) ;
MODULE_LICENSE ( " GPL " ) ;