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 21 enum TpmType tpm_backend_get_type(TPMBackend *s) 22 { 23 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 24 25 return k->ops->type; 26 } 27 28 const char *tpm_backend_get_desc(TPMBackend *s) 29 { 30 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 31 32 return k->ops->desc(); 33 } 34 35 void tpm_backend_destroy(TPMBackend *s) 36 { 37 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 38 39 return k->ops->destroy(s); 40 } 41 42 int 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 50 int 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 57 bool 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 64 size_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 71 void tpm_backend_deliver_request(TPMBackend *s) 72 { 73 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 74 75 k->ops->deliver_request(s); 76 } 77 78 void tpm_backend_reset(TPMBackend *s) 79 { 80 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 81 82 k->ops->reset(s); 83 } 84 85 void tpm_backend_cancel_cmd(TPMBackend *s) 86 { 87 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 88 89 k->ops->cancel_cmd(s); 90 } 91 92 bool 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 99 static bool tpm_backend_prop_get_opened(Object *obj, Error **errp) 100 { 101 TPMBackend *s = TPM_BACKEND(obj); 102 103 return s->opened; 104 } 105 106 void tpm_backend_open(TPMBackend *s, Error **errp) 107 { 108 object_property_set_bool(OBJECT(s), true, "opened", errp); 109 } 110 111 static 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 137 static 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 145 void tpm_backend_thread_deliver_request(TPMBackendThread *tbt) 146 { 147 g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL); 148 } 149 150 void 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 159 void 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 168 void 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 179 static 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 188 static void register_types(void) 189 { 190 type_register_static(&tpm_backend_info); 191 } 192 193 type_init(register_types); 194