16c4e9d48SLaurent Vivier /* 26c4e9d48SLaurent Vivier * QEMU Builtin Random Number Generator Backend 36c4e9d48SLaurent Vivier * 46c4e9d48SLaurent Vivier * This work is licensed under the terms of the GNU GPL, version 2 or later. 56c4e9d48SLaurent Vivier * See the COPYING file in the top-level directory. 66c4e9d48SLaurent Vivier */ 76c4e9d48SLaurent Vivier 86c4e9d48SLaurent Vivier #include "qemu/osdep.h" 96c4e9d48SLaurent Vivier #include "sysemu/rng.h" 106c4e9d48SLaurent Vivier #include "qemu/main-loop.h" 116c4e9d48SLaurent Vivier #include "qemu/guest-random.h" 12db1015e9SEduardo Habkost #include "qom/object.h" 136c4e9d48SLaurent Vivier 14*8063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(RngBuiltin, RNG_BUILTIN) 156c4e9d48SLaurent Vivier 16db1015e9SEduardo Habkost struct RngBuiltin { 176c4e9d48SLaurent Vivier RngBackend parent; 186c4e9d48SLaurent Vivier QEMUBH *bh; 19db1015e9SEduardo Habkost }; 206c4e9d48SLaurent Vivier 216c4e9d48SLaurent Vivier static void rng_builtin_receive_entropy_bh(void *opaque) 226c4e9d48SLaurent Vivier { 236c4e9d48SLaurent Vivier RngBuiltin *s = opaque; 246c4e9d48SLaurent Vivier 256c4e9d48SLaurent Vivier while (!QSIMPLEQ_EMPTY(&s->parent.requests)) { 266c4e9d48SLaurent Vivier RngRequest *req = QSIMPLEQ_FIRST(&s->parent.requests); 276c4e9d48SLaurent Vivier 286c4e9d48SLaurent Vivier qemu_guest_getrandom_nofail(req->data, req->size); 296c4e9d48SLaurent Vivier 306c4e9d48SLaurent Vivier req->receive_entropy(req->opaque, req->data, req->size); 316c4e9d48SLaurent Vivier 326c4e9d48SLaurent Vivier rng_backend_finalize_request(&s->parent, req); 336c4e9d48SLaurent Vivier } 346c4e9d48SLaurent Vivier } 356c4e9d48SLaurent Vivier 366c4e9d48SLaurent Vivier static void rng_builtin_request_entropy(RngBackend *b, RngRequest *req) 376c4e9d48SLaurent Vivier { 386c4e9d48SLaurent Vivier RngBuiltin *s = RNG_BUILTIN(b); 396c4e9d48SLaurent Vivier 406c4e9d48SLaurent Vivier qemu_bh_schedule(s->bh); 416c4e9d48SLaurent Vivier } 426c4e9d48SLaurent Vivier 436c4e9d48SLaurent Vivier static void rng_builtin_init(Object *obj) 446c4e9d48SLaurent Vivier { 456c4e9d48SLaurent Vivier RngBuiltin *s = RNG_BUILTIN(obj); 466c4e9d48SLaurent Vivier 476c4e9d48SLaurent Vivier s->bh = qemu_bh_new(rng_builtin_receive_entropy_bh, s); 486c4e9d48SLaurent Vivier } 496c4e9d48SLaurent Vivier 506c4e9d48SLaurent Vivier static void rng_builtin_finalize(Object *obj) 516c4e9d48SLaurent Vivier { 526c4e9d48SLaurent Vivier RngBuiltin *s = RNG_BUILTIN(obj); 536c4e9d48SLaurent Vivier 546c4e9d48SLaurent Vivier qemu_bh_delete(s->bh); 556c4e9d48SLaurent Vivier } 566c4e9d48SLaurent Vivier 576c4e9d48SLaurent Vivier static void rng_builtin_class_init(ObjectClass *klass, void *data) 586c4e9d48SLaurent Vivier { 596c4e9d48SLaurent Vivier RngBackendClass *rbc = RNG_BACKEND_CLASS(klass); 606c4e9d48SLaurent Vivier 616c4e9d48SLaurent Vivier rbc->request_entropy = rng_builtin_request_entropy; 626c4e9d48SLaurent Vivier } 636c4e9d48SLaurent Vivier 646c4e9d48SLaurent Vivier static const TypeInfo rng_builtin_info = { 656c4e9d48SLaurent Vivier .name = TYPE_RNG_BUILTIN, 666c4e9d48SLaurent Vivier .parent = TYPE_RNG_BACKEND, 676c4e9d48SLaurent Vivier .instance_size = sizeof(RngBuiltin), 686c4e9d48SLaurent Vivier .instance_init = rng_builtin_init, 696c4e9d48SLaurent Vivier .instance_finalize = rng_builtin_finalize, 706c4e9d48SLaurent Vivier .class_init = rng_builtin_class_init, 716c4e9d48SLaurent Vivier }; 726c4e9d48SLaurent Vivier 736c4e9d48SLaurent Vivier static void register_types(void) 746c4e9d48SLaurent Vivier { 756c4e9d48SLaurent Vivier type_register_static(&rng_builtin_info); 766c4e9d48SLaurent Vivier } 776c4e9d48SLaurent Vivier 786c4e9d48SLaurent Vivier type_init(register_types); 79