qemu/backends/tpm.c
<<
>>
Prefs
   1/*
   2 * QEMU TPM Backend
   3 *
   4 * Copyright IBM, Corp. 2013
   5 *
   6 * Authors:
   7 *  Stefan Berger   <stefanb@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 * Based on backends/rng.c by Anthony Liguori
  13 */
  14
  15#include "sysemu/tpm_backend.h"
  16#include "qapi/qmp/qerror.h"
  17#include "sysemu/tpm.h"
  18#include "qemu/thread.h"
  19#include "sysemu/tpm_backend_int.h"
  20
  21enum TpmType tpm_backend_get_type(TPMBackend *s)
  22{
  23    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  24
  25    return k->ops->type;
  26}
  27
  28const char *tpm_backend_get_desc(TPMBackend *s)
  29{
  30    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  31
  32    return k->ops->desc();
  33}
  34
  35void tpm_backend_destroy(TPMBackend *s)
  36{
  37    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  38
  39    return k->ops->destroy(s);
  40}
  41
  42int tpm_backend_init(TPMBackend *s, TPMState *state,
  43                     TPMRecvDataCB *datacb)
  44{
  45    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  46
  47    return k->ops->init(s, state, datacb);
  48}
  49
  50int tpm_backend_startup_tpm(TPMBackend *s)
  51{
  52    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  53
  54    return k->ops->startup_tpm(s);
  55}
  56
  57bool tpm_backend_had_startup_error(TPMBackend *s)
  58{
  59    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  60
  61    return k->ops->had_startup_error(s);
  62}
  63
  64size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
  65{
  66    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  67
  68    return k->ops->realloc_buffer(sb);
  69}
  70
  71void tpm_backend_deliver_request(TPMBackend *s)
  72{
  73    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  74
  75    k->ops->deliver_request(s);
  76}
  77
  78void tpm_backend_reset(TPMBackend *s)
  79{
  80    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  81
  82    k->ops->reset(s);
  83}
  84
  85void tpm_backend_cancel_cmd(TPMBackend *s)
  86{
  87    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  88
  89    k->ops->cancel_cmd(s);
  90}
  91
  92bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
  93{
  94    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
  95
  96    return k->ops->get_tpm_established_flag(s);
  97}
  98
  99static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
 100{
 101    TPMBackend *s = TPM_BACKEND(obj);
 102
 103    return s->opened;
 104}
 105
 106void tpm_backend_open(TPMBackend *s, Error **errp)
 107{
 108    object_property_set_bool(OBJECT(s), true, "opened", errp);
 109}
 110
 111static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp)
 112{
 113    TPMBackend *s = TPM_BACKEND(obj);
 114    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
 115
 116    if (value == s->opened) {
 117        return;
 118    }
 119
 120    if (!value && s->opened) {
 121        error_set(errp, QERR_PERMISSION_DENIED);
 122        return;
 123    }
 124
 125    if (k->opened) {
 126        k->opened(s, errp);
 127    }
 128
 129    if (!error_is_set(errp)) {
 130        s->opened = value;
 131    }
 132}
 133
 134static void tpm_backend_instance_init(Object *obj)
 135{
 136    object_property_add_bool(obj, "opened",
 137                             tpm_backend_prop_get_opened,
 138                             tpm_backend_prop_set_opened,
 139                             NULL);
 140}
 141
 142void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
 143{
 144   g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL);
 145}
 146
 147void tpm_backend_thread_create(TPMBackendThread *tbt,
 148                               GFunc func, gpointer user_data)
 149{
 150    if (!tbt->pool) {
 151        tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
 152        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
 153    }
 154}
 155
 156void tpm_backend_thread_end(TPMBackendThread *tbt)
 157{
 158    if (tbt->pool) {
 159        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
 160        g_thread_pool_free(tbt->pool, FALSE, TRUE);
 161        tbt->pool = NULL;
 162    }
 163}
 164
 165void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt,
 166                                  GFunc func, gpointer user_data)
 167{
 168    if (!tbt->pool) {
 169        tpm_backend_thread_create(tbt, func, user_data);
 170    } else {
 171        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_TPM_RESET,
 172                           NULL);
 173    }
 174}
 175
 176static const TypeInfo tpm_backend_info = {
 177    .name = TYPE_TPM_BACKEND,
 178    .parent = TYPE_OBJECT,
 179    .instance_size = sizeof(TPMBackend),
 180    .instance_init = tpm_backend_instance_init,
 181    .class_size = sizeof(TPMBackendClass),
 182    .abstract = true,
 183};
 184
 185static void register_types(void)
 186{
 187    type_register_static(&tpm_backend_info);
 188}
 189
 190type_init(register_types);
 191