random.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* Much of this ripped from hw_random.c */
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/miscdevice.h>
  5. #include <linux/delay.h>
  6. #include <asm/uaccess.h>
  7. #include "os.h"
  8. /*
  9. * core module and version information
  10. */
  11. #define RNG_VERSION "1.0.0"
  12. #define RNG_MODULE_NAME "random"
  13. #define RNG_DRIVER_NAME RNG_MODULE_NAME " virtual driver " RNG_VERSION
  14. #define PFX RNG_MODULE_NAME ": "
  15. #define RNG_MISCDEV_MINOR 183 /* official */
  16. static int random_fd = -1;
  17. static int rng_dev_open (struct inode *inode, struct file *filp)
  18. {
  19. /* enforce read-only access to this chrdev */
  20. if ((filp->f_mode & FMODE_READ) == 0)
  21. return -EINVAL;
  22. if (filp->f_mode & FMODE_WRITE)
  23. return -EINVAL;
  24. return 0;
  25. }
  26. static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
  27. loff_t * offp)
  28. {
  29. u32 data;
  30. int n, ret = 0, have_data;
  31. while(size){
  32. n = os_read_file(random_fd, &data, sizeof(data));
  33. if(n > 0){
  34. have_data = n;
  35. while (have_data && size) {
  36. if (put_user((u8)data, buf++)) {
  37. ret = ret ? : -EFAULT;
  38. break;
  39. }
  40. size--;
  41. ret++;
  42. have_data--;
  43. data>>=8;
  44. }
  45. }
  46. else if(n == -EAGAIN){
  47. if (filp->f_flags & O_NONBLOCK)
  48. return ret ? : -EAGAIN;
  49. if(need_resched()){
  50. current->state = TASK_INTERRUPTIBLE;
  51. schedule_timeout(1);
  52. }
  53. }
  54. else return n;
  55. if (signal_pending (current))
  56. return ret ? : -ERESTARTSYS;
  57. }
  58. return ret;
  59. }
  60. static struct file_operations rng_chrdev_ops = {
  61. .owner = THIS_MODULE,
  62. .open = rng_dev_open,
  63. .read = rng_dev_read,
  64. };
  65. static struct miscdevice rng_miscdev = {
  66. RNG_MISCDEV_MINOR,
  67. RNG_MODULE_NAME,
  68. &rng_chrdev_ops,
  69. };
  70. /*
  71. * rng_init - initialize RNG module
  72. */
  73. static int __init rng_init (void)
  74. {
  75. int err;
  76. err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
  77. if(err < 0)
  78. goto out;
  79. random_fd = err;
  80. err = os_set_fd_block(random_fd, 0);
  81. if(err)
  82. goto err_out_cleanup_hw;
  83. err = misc_register (&rng_miscdev);
  84. if (err) {
  85. printk (KERN_ERR PFX "misc device register failed\n");
  86. goto err_out_cleanup_hw;
  87. }
  88. out:
  89. return err;
  90. err_out_cleanup_hw:
  91. random_fd = -1;
  92. goto out;
  93. }
  94. /*
  95. * rng_cleanup - shutdown RNG module
  96. */
  97. static void __exit rng_cleanup (void)
  98. {
  99. misc_deregister (&rng_miscdev);
  100. }
  101. module_init (rng_init);
  102. module_exit (rng_cleanup);