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    Error *local_err = NULL;
 116
 117    if (value == s->opened) {
 118        return;
 119    }
 120
 121    if (!value && s->opened) {
 122        error_set(errp, QERR_PERMISSION_DENIED);
 123        return;
 124    }
 125
 126    if (k->opened) {
 127        k->opened(s, &local_err);
 128        if (local_err) {
 129            error_propagate(errp, local_err);
 130            return;
 131        }
 132    }
 133
 134    s->opened = true;
 135}
 136
 137static void tpm_backend_instance_init(Object *obj)
 138{
 139    object_property_add_bool(obj, "opened",
 140                             tpm_backend_prop_get_opened,
 141                             tpm_backend_prop_set_opened,
 142                             NULL);
 143}
 144
 145void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
 146{
 147   g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL);
 148}
 149
 150void tpm_backend_thread_create(TPMBackendThread *tbt,
 151                               GFunc func, gpointer user_data)
 152{
 153    if (!tbt->pool) {
 154        tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
 155        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
 156    }
 157}
 158
 159void tpm_backend_thread_end(TPMBackendThread *tbt)
 160{
 161    if (tbt->pool) {
 162        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
 163        g_thread_pool_free(tbt->pool, FALSE, TRUE);
 164        tbt->pool = NULL;
 165    }
 166}
 167
 168void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt,
 169                                  GFunc func, gpointer user_data)
 170{
 171    if (!tbt->pool) {
 172        tpm_backend_thread_create(tbt, func, user_data);
 173    } else {
 174        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_TPM_RESET,
 175                           NULL);
 176    }
 177}
 178
 179static const TypeInfo tpm_backend_info = {
 180    .name = TYPE_TPM_BACKEND,
 181    .parent = TYPE_OBJECT,
 182    .instance_size = sizeof(TPMBackend),
 183    .instance_init = tpm_backend_instance_init,
 184    .class_size = sizeof(TPMBackendClass),
 185    .abstract = true,
 186};
 187
 188static void register_types(void)
 189{
 190    type_register_static(&tpm_backend_info);
 191}
 192
 193type_init(register_types);
 194