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 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 int 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 106 TPMVersion 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 113 static bool tpm_backend_prop_get_opened(Object *obj, Error **errp) 114 { 115 TPMBackend *s = TPM_BACKEND(obj); 116 117 return s->opened; 118 } 119 120 void tpm_backend_open(TPMBackend *s, Error **errp) 121 { 122 object_property_set_bool(OBJECT(s), true, "opened", errp); 123 } 124 125 static 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 151 static 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 159 void tpm_backend_thread_deliver_request(TPMBackendThread *tbt) 160 { 161 g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL); 162 } 163 164 void 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 173 void 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 182 static 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 191 static void register_types(void) 192 { 193 type_register_static(&tpm_backend_info); 194 } 195 196 type_init(register_types); 197