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