summaryrefslogtreecommitdiffstats
path: root/sys/dev/random/randomdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/random/randomdev.c')
-rw-r--r--sys/dev/random/randomdev.c78
1 files changed, 55 insertions, 23 deletions
diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c
index 18b17d8..eeef425 100644
--- a/sys/dev/random/randomdev.c
+++ b/sys/dev/random/randomdev.c
@@ -70,12 +70,15 @@ static struct cdevsw random_cdevsw = {
.d_name = "random",
};
-struct random_systat *random_systat;
+static struct random_adaptor *random_adaptor;
+static eventhandler_tag attach_tag;
+static int random_inited;
+
/* For use with make_dev(9)/destroy_dev(9). */
static struct cdev *random_dev;
-/* Used to fake out unused random calls in random_systat */
+/* Used to fake out unused random calls in random_adaptor */
void
random_null_func(void)
{
@@ -88,8 +91,8 @@ random_close(struct cdev *dev __unused, int flags, int fmt __unused,
{
if ((flags & FWRITE) && (priv_check(td, PRIV_RANDOM_RESEED) == 0)
&& (securelevel_gt(td->td_ucred, 0) == 0)) {
- (*random_systat->reseed)();
- random_systat->seeded = 1;
+ (*random_adaptor->reseed)();
+ random_adaptor->seeded = 1;
arc4rand(NULL, 0, 1); /* Reseed arc4random as well. */
}
@@ -104,8 +107,8 @@ random_read(struct cdev *dev __unused, struct uio *uio, int flag)
void *random_buf;
/* Blocking logic */
- if (!random_systat->seeded)
- error = (*random_systat->block)(flag);
+ if (!random_adaptor->seeded)
+ error = (*random_adaptor->block)(flag);
/* The actual read */
if (!error) {
@@ -114,7 +117,7 @@ random_read(struct cdev *dev __unused, struct uio *uio, int flag)
while (uio->uio_resid > 0 && !error) {
c = MIN(uio->uio_resid, PAGE_SIZE);
- c = (*random_systat->read)(random_buf, c);
+ c = (*random_adaptor->read)(random_buf, c);
error = uiomove(random_buf, c, uio);
}
@@ -139,7 +142,7 @@ random_write(struct cdev *dev __unused, struct uio *uio, int flag __unused)
error = uiomove(random_buf, c, uio);
if (error)
break;
- (*random_systat->write)(random_buf, c);
+ (*random_adaptor->write)(random_buf, c);
}
free(random_buf, M_TEMP);
@@ -172,14 +175,37 @@ random_poll(struct cdev *dev __unused, int events, struct thread *td)
int revents = 0;
if (events & (POLLIN | POLLRDNORM)) {
- if (random_systat->seeded)
+ if (random_adaptor->seeded)
revents = events & (POLLIN | POLLRDNORM);
else
- revents = (*random_systat->poll) (events,td);
+ revents = (*random_adaptor->poll) (events,td);
}
return (revents);
}
+static void
+random_initialize(void *p, struct random_adaptor *s)
+{
+ if (random_inited) {
+ printf("random: <%s> already initialized\n",
+ random_adaptor->ident);
+ return;
+ }
+
+ random_adaptor = s;
+
+ (s->init)();
+
+ printf("random: <%s> initialized\n", s->ident);
+
+ random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
+ RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0666, "random");
+ make_dev_alias(random_dev, "urandom"); /* XXX Deprecated */
+
+ /* mark random(4) as initialized, to avoid being called again */
+ random_inited = 1;
+}
+
/* ARGSUSED */
static int
random_modevent(module_t mod __unused, int type, void *data __unused)
@@ -188,23 +214,29 @@ random_modevent(module_t mod __unused, int type, void *data __unused)
switch (type) {
case MOD_LOAD:
- random_ident_hardware(&random_systat);
- (*random_systat->init)();
-
- if (bootverbose)
- printf("random: <entropy source, %s>\n",
- random_systat->ident);
-
- random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
- RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0666, "random");
- make_dev_alias(random_dev, "urandom"); /* XXX Deprecated */
+ random_ident_hardware(&random_adaptor);
+
+ if (random_adaptor == NULL) {
+ printf(
+ "random: No random adaptor attached, postponing initialization\n");
+ attach_tag = EVENTHANDLER_REGISTER(random_adaptor_attach,
+ random_initialize, NULL, EVENTHANDLER_PRI_ANY);
+ } else {
+ random_initialize(NULL, random_adaptor);
+ }
break;
case MOD_UNLOAD:
- (*random_systat->deinit)();
-
- destroy_dev(random_dev);
+ if (random_adaptor != NULL) {
+ (*random_adaptor->deinit)();
+ destroy_dev(random_dev);
+ }
+ /* Unregister the event handler */
+ if (attach_tag != NULL) {
+ EVENTHANDLER_DEREGISTER(random_adaptor_attach,
+ attach_tag);
+ }
break;
OpenPOWER on IntegriCloud