1 | /* This file contains the device dependent part of the drivers for the
|
---|
2 | * following special files:
|
---|
3 | * /dev/random - random number generator
|
---|
4 | */
|
---|
5 |
|
---|
6 | #include "../drivers.h"
|
---|
7 | #include "../libdriver/driver.h"
|
---|
8 | #include <sys/ioc_memory.h>
|
---|
9 | #include "../../kernel/const.h"
|
---|
10 | #include "../../kernel/config.h"
|
---|
11 | #include "../../kernel/type.h"
|
---|
12 |
|
---|
13 | #include "assert.h"
|
---|
14 | #include "random.h"
|
---|
15 |
|
---|
16 | #define NR_DEVS 1 /* number of minor devices */
|
---|
17 | # define RANDOM_DEV 0 /* minor device for /dev/random */
|
---|
18 |
|
---|
19 | #define KRANDOM_PERIOD 1 /* ticks between krandom calls */
|
---|
20 |
|
---|
21 | PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
|
---|
22 | PRIVATE int m_device; /* current device */
|
---|
23 |
|
---|
24 | extern int errno; /* error number for PM calls */
|
---|
25 |
|
---|
26 | FORWARD _PROTOTYPE( char *r_name, (void) );
|
---|
27 | FORWARD _PROTOTYPE( struct device *r_prepare, (int device) );
|
---|
28 | FORWARD _PROTOTYPE( int r_transfer, (int proc_nr, int opcode, off_t position,
|
---|
29 | iovec_t *iov, unsigned nr_req) );
|
---|
30 | FORWARD _PROTOTYPE( int r_do_open, (struct driver *dp, message *m_ptr) );
|
---|
31 | FORWARD _PROTOTYPE( void r_init, (void) );
|
---|
32 | FORWARD _PROTOTYPE( int r_ioctl, (struct driver *dp, message *m_ptr) );
|
---|
33 | FORWARD _PROTOTYPE( void r_geometry, (struct partition *entry) );
|
---|
34 | FORWARD _PROTOTYPE( void r_random, (struct driver *dp, message *m_ptr) );
|
---|
35 |
|
---|
36 | /* Entry points to this driver. */
|
---|
37 | PRIVATE struct driver r_dtab = {
|
---|
38 | r_name, /* current device's name */
|
---|
39 | r_do_open, /* open or mount */
|
---|
40 | do_nop, /* nothing on a close */
|
---|
41 | r_ioctl, /* specify ram disk geometry */
|
---|
42 | r_prepare, /* prepare for I/O on a given minor device */
|
---|
43 | r_transfer, /* do the I/O */
|
---|
44 | nop_cleanup, /* no need to clean up */
|
---|
45 | r_geometry, /* device "geometry" */
|
---|
46 | nop_signal, /* system signals */
|
---|
47 | r_random, /* get randomness from kernel (alarm) */
|
---|
48 | nop_cancel,
|
---|
49 | nop_select,
|
---|
50 | NULL,
|
---|
51 | NULL
|
---|
52 | };
|
---|
53 |
|
---|
54 | /* Buffer for the /dev/random number generator. */
|
---|
55 | #define RANDOM_BUF_SIZE 1024
|
---|
56 | PRIVATE char random_buf[RANDOM_BUF_SIZE];
|
---|
57 |
|
---|
58 | /*===========================================================================*
|
---|
59 | * main *
|
---|
60 | *===========================================================================*/
|
---|
61 | PUBLIC int main(void)
|
---|
62 | {
|
---|
63 | r_init(); /* initialize the memory driver */
|
---|
64 | driver_task(&r_dtab); /* start driver's main loop */
|
---|
65 | return(OK);
|
---|
66 | }
|
---|
67 |
|
---|
68 | /*===========================================================================*
|
---|
69 | * r_name *
|
---|
70 | *===========================================================================*/
|
---|
71 | PRIVATE char *r_name()
|
---|
72 | {
|
---|
73 | /* Return a name for the current device. */
|
---|
74 | static char name[] = "random";
|
---|
75 | return name;
|
---|
76 | }
|
---|
77 |
|
---|
78 | /*===========================================================================*
|
---|
79 | * r_prepare *
|
---|
80 | *===========================================================================*/
|
---|
81 | PRIVATE struct device *r_prepare(device)
|
---|
82 | int device;
|
---|
83 | {
|
---|
84 | /* Prepare for I/O on a device: check if the minor device number is ok. */
|
---|
85 |
|
---|
86 | if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
|
---|
87 | m_device = device;
|
---|
88 |
|
---|
89 | return(&m_geom[device]);
|
---|
90 | }
|
---|
91 |
|
---|
92 | /*===========================================================================*
|
---|
93 | * r_transfer *
|
---|
94 | *===========================================================================*/
|
---|
95 | PRIVATE int r_transfer(proc_nr, opcode, position, iov, nr_req)
|
---|
96 | int proc_nr; /* process doing the request */
|
---|
97 | int opcode; /* DEV_GATHER or DEV_SCATTER */
|
---|
98 | off_t position; /* offset on device to read or write */
|
---|
99 | iovec_t *iov; /* pointer to read or write request vector */
|
---|
100 | unsigned nr_req; /* length of request vector */
|
---|
101 | {
|
---|
102 | /* Read or write one the driver's minor devices. */
|
---|
103 | unsigned count, left, chunk;
|
---|
104 | vir_bytes user_vir;
|
---|
105 | struct device *dv;
|
---|
106 | unsigned long dv_size;
|
---|
107 |
|
---|
108 | /* Get minor device number and check for /dev/null. */
|
---|
109 | dv = &m_geom[m_device];
|
---|
110 | dv_size = cv64ul(dv->dv_size);
|
---|
111 |
|
---|
112 | while (nr_req > 0) {
|
---|
113 |
|
---|
114 | /* How much to transfer and where to / from. */
|
---|
115 | count = iov->iov_size;
|
---|
116 | user_vir = iov->iov_addr;
|
---|
117 |
|
---|
118 | switch (m_device) {
|
---|
119 |
|
---|
120 | /* Random number generator. Character instead of block device. */
|
---|
121 | case RANDOM_DEV:
|
---|
122 | if (opcode == DEV_GATHER && !random_isseeded())
|
---|
123 | return(EAGAIN);
|
---|
124 | left = count;
|
---|
125 | while (left > 0) {
|
---|
126 | chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
|
---|
127 | if (opcode == DEV_GATHER) {
|
---|
128 | random_getbytes(random_buf, chunk);
|
---|
129 | sys_vircopy(SELF, D, (vir_bytes) random_buf,
|
---|
130 | proc_nr, D, user_vir, chunk);
|
---|
131 | } else if (opcode == DEV_SCATTER) {
|
---|
132 | sys_vircopy(proc_nr, D, user_vir,
|
---|
133 | SELF, D, (vir_bytes) random_buf, chunk);
|
---|
134 | random_putbytes(random_buf, chunk);
|
---|
135 | }
|
---|
136 | user_vir += chunk;
|
---|
137 | left -= chunk;
|
---|
138 | }
|
---|
139 | break;
|
---|
140 |
|
---|
141 | /* Unknown (illegal) minor device. */
|
---|
142 | default:
|
---|
143 | return(EINVAL);
|
---|
144 | }
|
---|
145 |
|
---|
146 | /* Book the number of bytes transferred. */
|
---|
147 | position += count;
|
---|
148 | iov->iov_addr += count;
|
---|
149 | if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
|
---|
150 |
|
---|
151 | }
|
---|
152 | return(OK);
|
---|
153 | }
|
---|
154 |
|
---|
155 | /*============================================================================*
|
---|
156 | * r_do_open *
|
---|
157 | *============================================================================*/
|
---|
158 | PRIVATE int r_do_open(dp, m_ptr)
|
---|
159 | struct driver *dp;
|
---|
160 | message *m_ptr;
|
---|
161 | {
|
---|
162 | /* Check device number on open.
|
---|
163 | */
|
---|
164 | if (r_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
|
---|
165 |
|
---|
166 | return(OK);
|
---|
167 | }
|
---|
168 |
|
---|
169 | /*===========================================================================*
|
---|
170 | * r_init *
|
---|
171 | *===========================================================================*/
|
---|
172 | PRIVATE void r_init()
|
---|
173 | {
|
---|
174 | /* Initialize this task. All minor devices are initialized one by one. */
|
---|
175 | random_init();
|
---|
176 | r_random(NULL, NULL); /* also set periodic timer */
|
---|
177 | }
|
---|
178 |
|
---|
179 | /*===========================================================================*
|
---|
180 | * r_ioctl *
|
---|
181 | *===========================================================================*/
|
---|
182 | PRIVATE int r_ioctl(dp, m_ptr)
|
---|
183 | struct driver *dp; /* pointer to driver structure */
|
---|
184 | message *m_ptr; /* pointer to control message */
|
---|
185 | {
|
---|
186 | struct device *dv;
|
---|
187 | if ((dv = r_prepare(m_ptr->DEVICE)) == NIL_DEV) return(ENXIO);
|
---|
188 |
|
---|
189 | switch (m_ptr->REQUEST) {
|
---|
190 |
|
---|
191 | default:
|
---|
192 | return(do_diocntl(&r_dtab, m_ptr));
|
---|
193 | }
|
---|
194 | return(OK);
|
---|
195 | }
|
---|
196 |
|
---|
197 | /*============================================================================*
|
---|
198 | * r_random *
|
---|
199 | *============================================================================*/
|
---|
200 | PRIVATE void r_random(dp, m_ptr)
|
---|
201 | struct driver *dp; /* pointer to driver structure */
|
---|
202 | message *m_ptr; /* pointer to alarm message */
|
---|
203 | {
|
---|
204 | /* Fetch random information from the kernel to update /dev/random. */
|
---|
205 | int i, s, r_next, r_size, r_high;
|
---|
206 | struct randomness krandom;
|
---|
207 |
|
---|
208 | if (OK != (s=sys_getrandomness(&krandom)))
|
---|
209 | report("RANDOM", "sys_getrandomness failed", s);
|
---|
210 |
|
---|
211 | for (i= 0; i<RANDOM_SOURCES; i++)
|
---|
212 | {
|
---|
213 | r_next= krandom.bin[i].r_next;
|
---|
214 | r_size= krandom.bin[i].r_size;
|
---|
215 | r_high= r_next+r_size;
|
---|
216 | if (r_high <= RANDOM_ELEMENTS)
|
---|
217 | {
|
---|
218 | random_update(i, &krandom.bin[i].r_buf[r_next], r_size);
|
---|
219 | }
|
---|
220 | else
|
---|
221 | {
|
---|
222 | assert(r_next < RANDOM_ELEMENTS);
|
---|
223 | random_update(i, &krandom.bin[i].r_buf[r_next],
|
---|
224 | RANDOM_ELEMENTS-r_next);
|
---|
225 | random_update(i, &krandom.bin[i].r_buf[0],
|
---|
226 | r_high-RANDOM_ELEMENTS);
|
---|
227 | }
|
---|
228 | }
|
---|
229 |
|
---|
230 | /* Schedule new alarm for next m_random call. */
|
---|
231 | if (OK != (s=sys_setalarm(KRANDOM_PERIOD, 0)))
|
---|
232 | report("RANDOM", "sys_setalarm failed", s);
|
---|
233 | }
|
---|
234 |
|
---|
235 | /*============================================================================*
|
---|
236 | * r_geometry *
|
---|
237 | *============================================================================*/
|
---|
238 | PRIVATE void r_geometry(entry)
|
---|
239 | struct partition *entry;
|
---|
240 | {
|
---|
241 | /* Memory devices don't have a geometry, but the outside world insists. */
|
---|
242 | entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
|
---|
243 | entry->heads = 64;
|
---|
244 | entry->sectors = 32;
|
---|
245 | }
|
---|
246 |
|
---|