qemu/backends/rng.c
<<
>>
Prefs
   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 "sysemu/rng.h"
  15#include "qapi/error.h"
  16#include "qapi/qmp/qerror.h"
  17#include "qom/object_interfaces.h"
  18
  19void rng_backend_request_entropy(RngBackend *s, size_t size,
  20                                 EntropyReceiveFunc *receive_entropy,
  21                                 void *opaque)
  22{
  23    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
  24    RngRequest *req;
  25
  26    if (k->request_entropy) {
  27        req = g_malloc(sizeof(*req));
  28
  29        req->offset = 0;
  30        req->size = size;
  31        req->receive_entropy = receive_entropy;
  32        req->opaque = opaque;
  33        req->data = g_malloc(req->size);
  34
  35        k->request_entropy(s, req);
  36
  37        QSIMPLEQ_INSERT_TAIL(&s->requests, req, next);
  38    }
  39}
  40
  41static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
  42{
  43    RngBackend *s = RNG_BACKEND(obj);
  44
  45    return s->opened;
  46}
  47
  48static void rng_backend_complete(UserCreatable *uc, Error **errp)
  49{
  50    object_property_set_bool(OBJECT(uc), true, "opened", errp);
  51}
  52
  53static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
  54{
  55    RngBackend *s = RNG_BACKEND(obj);
  56    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
  57    Error *local_err = NULL;
  58
  59    if (value == s->opened) {
  60        return;
  61    }
  62
  63    if (!value && s->opened) {
  64        error_setg(errp, QERR_PERMISSION_DENIED);
  65        return;
  66    }
  67
  68    if (k->opened) {
  69        k->opened(s, &local_err);
  70        if (local_err) {
  71            error_propagate(errp, local_err);
  72            return;
  73        }
  74    }
  75
  76    s->opened = true;
  77}
  78
  79static void rng_backend_free_request(RngRequest *req)
  80{
  81    g_free(req->data);
  82    g_free(req);
  83}
  84
  85static void rng_backend_free_requests(RngBackend *s)
  86{
  87    RngRequest *req, *next;
  88
  89    QSIMPLEQ_FOREACH_SAFE(req, &s->requests, next, next) {
  90        rng_backend_free_request(req);
  91    }
  92
  93    QSIMPLEQ_INIT(&s->requests);
  94}
  95
  96void rng_backend_finalize_request(RngBackend *s, RngRequest *req)
  97{
  98    QSIMPLEQ_REMOVE(&s->requests, req, RngRequest, next);
  99    rng_backend_free_request(req);
 100}
 101
 102static void rng_backend_init(Object *obj)
 103{
 104    RngBackend *s = RNG_BACKEND(obj);
 105
 106    QSIMPLEQ_INIT(&s->requests);
 107
 108    object_property_add_bool(obj, "opened",
 109                             rng_backend_prop_get_opened,
 110                             rng_backend_prop_set_opened,
 111                             NULL);
 112}
 113
 114static void rng_backend_finalize(Object *obj)
 115{
 116    RngBackend *s = RNG_BACKEND(obj);
 117
 118    rng_backend_free_requests(s);
 119}
 120
 121static void rng_backend_class_init(ObjectClass *oc, void *data)
 122{
 123    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 124
 125    ucc->complete = rng_backend_complete;
 126}
 127
 128static const TypeInfo rng_backend_info = {
 129    .name = TYPE_RNG_BACKEND,
 130    .parent = TYPE_OBJECT,
 131    .instance_size = sizeof(RngBackend),
 132    .instance_init = rng_backend_init,
 133    .instance_finalize = rng_backend_finalize,
 134    .class_size = sizeof(RngBackendClass),
 135    .class_init = rng_backend_class_init,
 136    .abstract = true,
 137    .interfaces = (InterfaceInfo[]) {
 138        { TYPE_USER_CREATABLE },
 139        { }
 140    }
 141};
 142
 143static void register_types(void)
 144{
 145    type_register_static(&rng_backend_info);
 146}
 147
 148type_init(register_types);
 149