random.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* Copyright (C) 2005 - 2008 Jeff Dike <jdike@{linux.intel,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/signal.h>
  9. #include <linux/module.h>
  10. #include <linux/fs.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/miscdevice.h>
  13. #include <linux/hw_random.h>
  14. #include <linux/delay.h>
  15. #include <linux/uaccess.h>
  16. #include <init.h>
  17. #include <irq_kern.h>
  18. #include <os.h>
  19. /*
  20. * core module information
  21. */
  22. #define RNG_MODULE_NAME "hw_random"
  23. /* Changed at init time, in the non-modular case, and at module load
  24. * time, in the module case. Presumably, the module subsystem
  25. * protects against a module being loaded twice at the same time.
  26. */
  27. static int random_fd = -1;
  28. static struct hwrng hwrng;
  29. static DECLARE_COMPLETION(have_data);
  30. static int rng_dev_read(struct hwrng *rng, void *buf, size_t max, bool block)
  31. {
  32. int ret;
  33. for (;;) {
  34. ret = os_read_file(random_fd, buf, max);
  35. if (block && ret == -EAGAIN) {
  36. add_sigio_fd(random_fd);
  37. ret = wait_for_completion_killable(&have_data);
  38. ignore_sigio_fd(random_fd);
  39. deactivate_fd(random_fd, RANDOM_IRQ);
  40. if (ret < 0)
  41. break;
  42. } else {
  43. break;
  44. }
  45. }
  46. return ret != -EAGAIN ? ret : 0;
  47. }
  48. static irqreturn_t random_interrupt(int irq, void *data)
  49. {
  50. complete(&have_data);
  51. return IRQ_HANDLED;
  52. }
  53. /*
  54. * rng_init - initialize RNG module
  55. */
  56. static int __init rng_init (void)
  57. {
  58. int err;
  59. err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
  60. if (err < 0)
  61. goto out;
  62. random_fd = err;
  63. err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
  64. 0, "random", NULL);
  65. if (err < 0)
  66. goto err_out_cleanup_hw;
  67. sigio_broken(random_fd);
  68. hwrng.name = RNG_MODULE_NAME;
  69. hwrng.read = rng_dev_read;
  70. hwrng.quality = 1024;
  71. err = hwrng_register(&hwrng);
  72. if (err) {
  73. pr_err(RNG_MODULE_NAME " registering failed (%d)\n", err);
  74. goto err_out_cleanup_hw;
  75. }
  76. out:
  77. return err;
  78. err_out_cleanup_hw:
  79. os_close_file(random_fd);
  80. random_fd = -1;
  81. goto out;
  82. }
  83. /*
  84. * rng_cleanup - shutdown RNG module
  85. */
  86. static void cleanup(void)
  87. {
  88. free_irq_by_fd(random_fd);
  89. os_close_file(random_fd);
  90. }
  91. static void __exit rng_cleanup(void)
  92. {
  93. hwrng_unregister(&hwrng);
  94. os_close_file(random_fd);
  95. }
  96. module_init (rng_init);
  97. module_exit (rng_cleanup);
  98. __uml_exitcall(cleanup);
  99. MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
  100. MODULE_LICENSE("GPL");