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 23 enum TpmType tpm_backend_get_type(TPMBackend *s) 24 { 25 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 26 27 return k->ops->type; 28 } 29 30 const char *tpm_backend_get_desc(TPMBackend *s) 31 { 32 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 33 34 return k->ops->desc(); 35 } 36 37 void tpm_backend_destroy(TPMBackend *s) 38 { 39 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 40 41 k->ops->destroy(s); 42 } 43 44 int 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 52 int 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 59 bool 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 66 size_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 73 void tpm_backend_deliver_request(TPMBackend *s) 74 { 75 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 76 77 k->ops->deliver_request(s); 78 } 79 80 void tpm_backend_reset(TPMBackend *s) 81 { 82 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 83 84 k->ops->reset(s); 85 } 86 87 void tpm_backend_cancel_cmd(TPMBackend *s) 88 { 89 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); 90 91 k->ops->cancel_cmd(s); 92 } 93 94 bool 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 101 int 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 108 TPMVersion 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 115 static bool tpm_backend_prop_get_opened(Object *obj, Error **errp) 116 { 117 TPMBackend *s = TPM_BACKEND(obj); 118 119 return s->opened; 120 } 121 122 void tpm_backend_open(TPMBackend *s, Error **errp) 123 { 124 object_property_set_bool(OBJECT(s), true, "opened", errp); 125 } 126 127 static 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 153 static 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 161 void tpm_backend_thread_deliver_request(TPMBackendThread *tbt) 162 { 163 g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL); 164 } 165 166 void 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 175 void 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 184 static 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 193 static void register_types(void) 194 { 195 type_register_static(&tpm_backend_info); 196 } 197 198 type_init(register_types); 199