master
c 152 lines 3.61 KB
Raw
1 /*
2 * QEMU Random Number Generator Backend
3 *
4 * Copyright IBM, Corp. 2012
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
13 #include "qemu/osdep.h"
14 #include "qemu/units.h"
15 #include "system/rng.h"
16 #include "qapi/error.h"
17 #include "qemu/module.h"
18 #include "qom/object_interfaces.h"
19
20 #define RNG_MAX_REQUEST_SIZE (64 * KiB)
21
22 void rng_backend_request_entropy(RngBackend *s, size_t size,
23 EntropyReceiveFunc *receive_entropy,
24 void *opaque)
25 {
26 RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
27 RngRequest *req;
28
29 if (k->request_entropy) {
30 req = g_malloc(sizeof(*req));
31
32 req->offset = 0;
33 req->size = MIN(size, RNG_MAX_REQUEST_SIZE);
34 req->receive_entropy = receive_entropy;
35 req->opaque = opaque;
36 req->data = g_malloc(req->size);
37
38 k->request_entropy(s, req);
39
40 QSIMPLEQ_INSERT_TAIL(&s->requests, req, next);
41 }
42 }
43
44 static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
45 {
46 RngBackend *s = RNG_BACKEND(obj);
47
48 return s->opened;
49 }
50
51 static void rng_backend_complete(UserCreatable *uc, Error **errp)
52 {
53 RngBackend *s = RNG_BACKEND(uc);
54 RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
55 Error *local_err = NULL;
56
57 if (k->opened) {
58 k->opened(s, &local_err);
59 if (local_err) {
60 error_propagate(errp, local_err);
61 return;
62 }
63 }
64
65 s->opened = true;
66 }
67
68 static void rng_backend_free_request(RngRequest *req)
69 {
70 g_free(req->data);
71 g_free(req);
72 }
73
74 void rng_backend_cancel_requests(RngBackend *s,
75 EntropyReceiveFunc *receive_entropy,
76 const void *opaque)
77 {
78 RngRequest *req, *next;
79
80 QSIMPLEQ_FOREACH_SAFE(req, &s->requests, next, next) {
81 if (req->receive_entropy != receive_entropy ||
82 req->opaque != opaque) {
83 continue;
84 }
85 QSIMPLEQ_REMOVE(&s->requests, req, RngRequest, next);
86 rng_backend_free_request(req);
87 }
88 }
89
90 static void rng_backend_free_requests(RngBackend *s)
91 {
92 RngRequest *req, *next;
93
94 QSIMPLEQ_FOREACH_SAFE(req, &s->requests, next, next) {
95 rng_backend_free_request(req);
96 }
97
98 QSIMPLEQ_INIT(&s->requests);
99 }
100
101 void rng_backend_finalize_request(RngBackend *s, RngRequest *req)
102 {
103 QSIMPLEQ_REMOVE(&s->requests, req, RngRequest, next);
104 rng_backend_free_request(req);
105 }
106
107 static void rng_backend_init(Object *obj)
108 {
109 RngBackend *s = RNG_BACKEND(obj);
110
111 QSIMPLEQ_INIT(&s->requests);
112 }
113
114 static void rng_backend_finalize(Object *obj)
115 {
116 RngBackend *s = RNG_BACKEND(obj);
117
118 rng_backend_free_requests(s);
119 }
120
121 static void rng_backend_class_init(ObjectClass *oc, const void *data)
122 {
123 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
124
125 ucc->complete = rng_backend_complete;
126
127 object_class_property_add_bool(oc, "opened",
128 rng_backend_prop_get_opened,
129 NULL);
130 }
131
132 static const TypeInfo rng_backend_info = {
133 .name = TYPE_RNG_BACKEND,
134 .parent = TYPE_OBJECT,
135 .instance_size = sizeof(RngBackend),
136 .instance_init = rng_backend_init,
137 .instance_finalize = rng_backend_finalize,
138 .class_size = sizeof(RngBackendClass),
139 .class_init = rng_backend_class_init,
140 .abstract = true,
141 .interfaces = (const InterfaceInfo[]) {
142 { TYPE_USER_CREATABLE },
143 { }
144 }
145 };
146
147 static void register_types(void)
148 {
149 type_register_static(&rng_backend_info);
150 }
151
152 type_init(register_types);