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    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
  99int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
 100{
 101    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
 102
 103    return k->ops->reset_tpm_established_flag(s, locty);
 104}
 105
 106TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
 107{
 108    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
 109
 110    return k->ops->get_tpm_version(s);
 111}
 112
 113static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
 114{
 115    TPMBackend *s = TPM_BACKEND(obj);
 116
 117    return s->opened;
 118}
 119
 120void tpm_backend_open(TPMBackend *s, Error **errp)
 121{
 122    object_property_set_bool(OBJECT(s), true, "opened", errp);
 123}
 124
 125static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp)
 126{
 127    TPMBackend *s = TPM_BACKEND(obj);
 128    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
 129    Error *local_err = NULL;
 130
 131    if (value == s->opened) {
 132        return;
 133    }
 134
 135    if (!value && s->opened) {
 136        error_setg(errp, QERR_PERMISSION_DENIED);
 137        return;
 138    }
 139
 140    if (k->opened) {
 141        k->opened(s, &local_err);
 142        if (local_err) {
 143            error_propagate(errp, local_err);
 144            return;
 145        }
 146    }
 147
 148    s->opened = true;
 149}
 150
 151static void tpm_backend_instance_init(Object *obj)
 152{
 153    object_property_add_bool(obj, "opened",
 154                             tpm_backend_prop_get_opened,
 155                             tpm_backend_prop_set_opened,
 156                             NULL);
 157}
 158
 159void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
 160{
 161   g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL);
 162}
 163
 164void tpm_backend_thread_create(TPMBackendThread *tbt,
 165                               GFunc func, gpointer user_data)
 166{
 167    if (!tbt->pool) {
 168        tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
 169        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
 170    }
 171}
 172
 173void tpm_backend_thread_end(TPMBackendThread *tbt)
 174{
 175    if (tbt->pool) {
 176        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
 177        g_thread_pool_free(tbt->pool, FALSE, TRUE);
 178        tbt->pool = NULL;
 179    }
 180}
 181
 182static const TypeInfo tpm_backend_info = {
 183    .name = TYPE_TPM_BACKEND,
 184    .parent = TYPE_OBJECT,
 185    .instance_size = sizeof(TPMBackend),
 186    .instance_init = tpm_backend_instance_init,
 187    .class_size = sizeof(TPMBackendClass),
 188    .abstract = true,
 189};
 190
 191static void register_types(void)
 192{
 193    type_register_static(&tpm_backend_info);
 194}
 195
 196type_init(register_types);
 197