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