Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/um/drivers/random.c
26424 views
1
/* Copyright (C) 2005 - 2008 Jeff Dike <jdike@{linux.intel,addtoit}.com> */
2
3
/* Much of this ripped from drivers/char/hw_random.c, see there for other
4
* copyright.
5
*
6
* This software may be used and distributed according to the terms
7
* of the GNU General Public License, incorporated herein by reference.
8
*/
9
#include <linux/sched/signal.h>
10
#include <linux/module.h>
11
#include <linux/fs.h>
12
#include <linux/interrupt.h>
13
#include <linux/miscdevice.h>
14
#include <linux/hw_random.h>
15
#include <linux/delay.h>
16
#include <linux/uaccess.h>
17
#include <init.h>
18
#include <irq_kern.h>
19
#include <os.h>
20
21
/*
22
* core module information
23
*/
24
#define RNG_MODULE_NAME "hw_random"
25
26
/* Changed at init time, in the non-modular case, and at module load
27
* time, in the module case. Presumably, the module subsystem
28
* protects against a module being loaded twice at the same time.
29
*/
30
static int random_fd = -1;
31
static struct hwrng hwrng;
32
static DECLARE_COMPLETION(have_data);
33
34
static int rng_dev_read(struct hwrng *rng, void *buf, size_t max, bool block)
35
{
36
int ret;
37
38
for (;;) {
39
ret = os_read_file(random_fd, buf, max);
40
if (block && ret == -EAGAIN) {
41
add_sigio_fd(random_fd);
42
43
ret = wait_for_completion_killable(&have_data);
44
45
ignore_sigio_fd(random_fd);
46
deactivate_fd(random_fd, RANDOM_IRQ);
47
48
if (ret < 0)
49
break;
50
} else {
51
break;
52
}
53
}
54
55
return ret != -EAGAIN ? ret : 0;
56
}
57
58
static irqreturn_t random_interrupt(int irq, void *data)
59
{
60
complete(&have_data);
61
62
return IRQ_HANDLED;
63
}
64
65
/*
66
* rng_init - initialize RNG module
67
*/
68
static int __init rng_init (void)
69
{
70
int err;
71
72
err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
73
if (err < 0)
74
goto out;
75
76
random_fd = err;
77
err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
78
0, "random", NULL);
79
if (err < 0)
80
goto err_out_cleanup_hw;
81
82
sigio_broken();
83
hwrng.name = RNG_MODULE_NAME;
84
hwrng.read = rng_dev_read;
85
86
err = hwrng_register(&hwrng);
87
if (err) {
88
pr_err(RNG_MODULE_NAME " registering failed (%d)\n", err);
89
goto err_out_cleanup_hw;
90
}
91
out:
92
return err;
93
94
err_out_cleanup_hw:
95
os_close_file(random_fd);
96
random_fd = -1;
97
goto out;
98
}
99
100
/*
101
* rng_cleanup - shutdown RNG module
102
*/
103
104
static void cleanup(void)
105
{
106
free_irq_by_fd(random_fd);
107
os_close_file(random_fd);
108
}
109
110
static void __exit rng_cleanup(void)
111
{
112
hwrng_unregister(&hwrng);
113
os_close_file(random_fd);
114
}
115
116
module_init (rng_init);
117
module_exit (rng_cleanup);
118
__uml_exitcall(cleanup);
119
120
MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
121
MODULE_LICENSE("GPL");
122
123