1256381Smarkm/*-
2256381Smarkm * Copyright (c) 2013 Arthur Mesh <arthurmesh@gmail.com>
3256381Smarkm * All rights reserved.
4256381Smarkm *
5256381Smarkm * Redistribution and use in source and binary forms, with or without
6256381Smarkm * modification, are permitted provided that the following conditions
7256381Smarkm * are met:
8256381Smarkm * 1. Redistributions of source code must retain the above copyright
9256381Smarkm *    notice, this list of conditions and the following disclaimer
10256381Smarkm *    in this position and unchanged.
11256381Smarkm * 2. Redistributions in binary form must reproduce the above copyright
12256381Smarkm *    notice, this list of conditions and the following disclaimer in the
13256381Smarkm *    documentation and/or other materials provided with the distribution.
14256381Smarkm *
15256381Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16256381Smarkm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17256381Smarkm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18256381Smarkm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19256381Smarkm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20256381Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21256381Smarkm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22256381Smarkm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23256381Smarkm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24256381Smarkm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25256381Smarkm *
26256381Smarkm */
27256381Smarkm#include <sys/cdefs.h>
28256381Smarkm__FBSDID("$FreeBSD$");
29256381Smarkm
30256381Smarkm#include <sys/param.h>
31256381Smarkm#include <sys/fcntl.h>
32256381Smarkm#include <sys/kernel.h>
33256381Smarkm#include <sys/malloc.h>
34256381Smarkm#include <sys/module.h>
35256381Smarkm#include <sys/random.h>
36256381Smarkm#include <sys/selinfo.h>
37256381Smarkm#include <sys/systm.h>
38256381Smarkm#include <sys/time.h>
39256381Smarkm
40256381Smarkm#include <dev/random/random_adaptors.h>
41256381Smarkm#include <dev/random/randomdev.h>
42256381Smarkm
43256381Smarkmstatic struct mtx	dummy_random_mtx;
44256381Smarkm
45256381Smarkm/* Used to fake out unused random calls in random_adaptor */
46256381Smarkmstatic void
47256381Smarkmrandom_null_func(void)
48256381Smarkm{
49256381Smarkm}
50256381Smarkm
51256381Smarkmstatic int
52256381Smarkmdummy_random_poll(int events __unused, struct thread *td __unused)
53256381Smarkm{
54256381Smarkm
55256381Smarkm	return (0);
56256381Smarkm}
57256381Smarkm
58256381Smarkmstatic int
59256381Smarkmdummy_random_block(int flag)
60256381Smarkm{
61256381Smarkm	int error = 0;
62256381Smarkm
63256381Smarkm	mtx_lock(&dummy_random_mtx);
64256381Smarkm
65256381Smarkm	/* Blocking logic */
66256381Smarkm	while (!error) {
67256381Smarkm		if (flag & O_NONBLOCK)
68256381Smarkm			error = EWOULDBLOCK;
69256381Smarkm		else {
70256381Smarkm			printf("random: dummy device blocking on read.\n");
71256381Smarkm			error = msleep(&dummy_random_block,
72256381Smarkm			    &dummy_random_mtx,
73256381Smarkm			    PUSER | PCATCH, "block", 0);
74256381Smarkm		}
75256381Smarkm	}
76256381Smarkm	mtx_unlock(&dummy_random_mtx);
77256381Smarkm
78256381Smarkm	return (error);
79256381Smarkm}
80256381Smarkm
81256381Smarkmstatic void
82256381Smarkmdummy_random_init(void)
83256381Smarkm{
84256381Smarkm
85256381Smarkm	mtx_init(&dummy_random_mtx, "sleep mtx for dummy_random",
86256381Smarkm	    NULL, MTX_DEF);
87256381Smarkm}
88256381Smarkm
89256381Smarkmstatic void
90256381Smarkmdummy_random_deinit(void)
91256381Smarkm{
92256381Smarkm
93256381Smarkm	mtx_destroy(&dummy_random_mtx);
94256381Smarkm}
95256381Smarkm
96256381Smarkmstruct random_adaptor dummy_random = {
97256381Smarkm	.ident = "Dummy entropy device that always blocks",
98256381Smarkm	.init = dummy_random_init,
99256381Smarkm	.deinit = dummy_random_deinit,
100256381Smarkm	.block = dummy_random_block,
101256381Smarkm	.poll = dummy_random_poll,
102256381Smarkm	.read = (random_read_func_t *)random_null_func,
103256381Smarkm	.reseed = (random_reseed_func_t *)random_null_func,
104256381Smarkm	.seeded = 0, /* This device can never be seeded */
105256414Smarkm	.priority = 1, /* Bottom priority, so goes to last position */
106256381Smarkm};
107256381Smarkm
108256381Smarkmstatic int
109256381Smarkmdummy_random_modevent(module_t mod __unused, int type, void *unused __unused)
110256381Smarkm{
111256381Smarkm
112256381Smarkm	switch (type) {
113256381Smarkm	case MOD_LOAD:
114256381Smarkm		random_adaptor_register("dummy", &dummy_random);
115256381Smarkm		EVENTHANDLER_INVOKE(random_adaptor_attach,
116256381Smarkm		    &dummy_random);
117256381Smarkm
118256381Smarkm		return (0);
119256381Smarkm	}
120256381Smarkm
121256381Smarkm	return (EINVAL);
122256381Smarkm}
123256381Smarkm
124256381SmarkmRANDOM_ADAPTOR_MODULE(dummy, dummy_random_modevent, 1);
125