mirror of https://github.com/xemu-project/xemu.git
QOM-ify the TPM support
QOM-ified the TPM support with much code borrowed from the rng implementation. All other TPM related code moves will be provided in a subsequent patch. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Message-id: 1364469981.24703.1.camel@d941e-10 Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
684a096eaf
commit
8f0605cc9c
|
@ -4,3 +4,5 @@ common-obj-$(CONFIG_POSIX) += rng-random.o
|
||||||
common-obj-y += msmouse.o
|
common-obj-y += msmouse.o
|
||||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||||
$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
|
$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
|
||||||
|
|
||||||
|
common-obj-$(CONFIG_TPM) += tpm.o
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* QEMU TPM Backend
|
||||||
|
*
|
||||||
|
* Copyright IBM, Corp. 2013
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stefan Berger <stefanb@us.ibm.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*
|
||||||
|
* Based on backends/rng.c by Anthony Liguori
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "backends/tpm.h"
|
||||||
|
#include "tpm/tpm_int.h"
|
||||||
|
#include "qapi/qmp/qerror.h"
|
||||||
|
|
||||||
|
enum TpmType tpm_backend_get_type(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tpm_backend_get_desc(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->desc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tpm_backend_destroy(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->destroy(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tpm_backend_init(TPMBackend *s, TPMState *state,
|
||||||
|
TPMRecvDataCB *datacb)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->init(s, state, datacb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tpm_backend_startup_tpm(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->startup_tpm(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tpm_backend_had_startup_error(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->had_startup_error(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->realloc_buffer(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tpm_backend_deliver_request(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
k->ops->deliver_request(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tpm_backend_reset(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
k->ops->reset(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tpm_backend_cancel_cmd(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
k->ops->cancel_cmd(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->get_tpm_established_flag(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
TPMBackend *s = TPM_BACKEND(obj);
|
||||||
|
|
||||||
|
return s->opened;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tpm_backend_open(TPMBackend *s, Error **errp)
|
||||||
|
{
|
||||||
|
object_property_set_bool(OBJECT(s), true, "opened", errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp)
|
||||||
|
{
|
||||||
|
TPMBackend *s = TPM_BACKEND(obj);
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
if (value == s->opened) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value && s->opened) {
|
||||||
|
error_set(errp, QERR_PERMISSION_DENIED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k->opened) {
|
||||||
|
k->opened(s, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error_is_set(errp)) {
|
||||||
|
s->opened = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tpm_backend_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
object_property_add_bool(obj, "opened",
|
||||||
|
tpm_backend_prop_get_opened,
|
||||||
|
tpm_backend_prop_set_opened,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo tpm_backend_info = {
|
||||||
|
.name = TYPE_TPM_BACKEND,
|
||||||
|
.parent = TYPE_OBJECT,
|
||||||
|
.instance_size = sizeof(TPMBackend),
|
||||||
|
.instance_init = tpm_backend_instance_init,
|
||||||
|
.class_size = sizeof(TPMBackendClass),
|
||||||
|
.abstract = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&tpm_backend_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(register_types);
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* QEMU TPM Backend
|
||||||
|
*
|
||||||
|
* Copyright IBM, Corp. 2013
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stefan Berger <stefanb@us.ibm.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QEMU_TPM_H
|
||||||
|
#define _QEMU_TPM_H
|
||||||
|
|
||||||
|
#include "qom/object.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qapi-types.h"
|
||||||
|
#include "qemu/option.h"
|
||||||
|
#include "tpm/tpm.h"
|
||||||
|
|
||||||
|
#define TYPE_TPM_BACKEND "tpm-backend"
|
||||||
|
#define TPM_BACKEND(obj) \
|
||||||
|
OBJECT_CHECK(TPMBackend, (obj), TYPE_TPM_BACKEND)
|
||||||
|
#define TPM_BACKEND_GET_CLASS(obj) \
|
||||||
|
OBJECT_GET_CLASS(TPMBackendClass, (obj), TYPE_TPM_BACKEND)
|
||||||
|
#define TPM_BACKEND_CLASS(klass) \
|
||||||
|
OBJECT_CLASS_CHECK(TPMBackendClass, (klass), TYPE_TPM_BACKEND)
|
||||||
|
|
||||||
|
typedef struct TPMBackendClass TPMBackendClass;
|
||||||
|
typedef struct TPMBackend TPMBackend;
|
||||||
|
|
||||||
|
typedef struct TPMDriverOps TPMDriverOps;
|
||||||
|
|
||||||
|
struct TPMBackendClass {
|
||||||
|
ObjectClass parent_class;
|
||||||
|
|
||||||
|
const TPMDriverOps *ops;
|
||||||
|
|
||||||
|
void (*opened)(TPMBackend *s, Error **errp);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TPMBackend {
|
||||||
|
Object parent;
|
||||||
|
|
||||||
|
/*< protected >*/
|
||||||
|
bool opened;
|
||||||
|
|
||||||
|
char *id;
|
||||||
|
enum TpmModel fe_model;
|
||||||
|
char *path;
|
||||||
|
char *cancel_path;
|
||||||
|
const TPMDriverOps *ops;
|
||||||
|
|
||||||
|
QLIST_ENTRY(TPMBackend) list;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_get_type:
|
||||||
|
* @s: the backend
|
||||||
|
*
|
||||||
|
* Returns the TpmType of the backend.
|
||||||
|
*/
|
||||||
|
enum TpmType tpm_backend_get_type(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_get_desc:
|
||||||
|
* @s: the backend
|
||||||
|
*
|
||||||
|
* Returns a human readable description of the backend.
|
||||||
|
*/
|
||||||
|
const char *tpm_backend_get_desc(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_destroy:
|
||||||
|
* @s: the backend to destroy
|
||||||
|
*/
|
||||||
|
void tpm_backend_destroy(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_init:
|
||||||
|
* @s: the backend to initialized
|
||||||
|
* @state: TPMState
|
||||||
|
* @datacb: callback for sending data to frontend
|
||||||
|
*
|
||||||
|
* Initialize the backend with the given variables.
|
||||||
|
*
|
||||||
|
* Returns 0 on success.
|
||||||
|
*/
|
||||||
|
int tpm_backend_init(TPMBackend *s, TPMState *state,
|
||||||
|
TPMRecvDataCB *datacb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_startup_tpm:
|
||||||
|
* @s: the backend whose TPM support is to be started
|
||||||
|
*
|
||||||
|
* Returns 0 on success.
|
||||||
|
*/
|
||||||
|
int tpm_backend_startup_tpm(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_had_startup_error:
|
||||||
|
* @s: the backend to query for a statup error
|
||||||
|
*
|
||||||
|
* Check whether the backend had an error during startup. Returns
|
||||||
|
* false if no error occurred and the backend can be used, true
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
bool tpm_backend_had_startup_error(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_realloc_buffer:
|
||||||
|
* @s: the backend
|
||||||
|
* @sb: the TPMSizedBuffer to re-allocated to the size suitable for the
|
||||||
|
* backend.
|
||||||
|
*
|
||||||
|
* This function returns the size of the allocated buffer
|
||||||
|
*/
|
||||||
|
size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_deliver_request:
|
||||||
|
* @s: the backend to send the request to
|
||||||
|
*
|
||||||
|
* Send a request to the backend. The backend will then send the request
|
||||||
|
* to the TPM implementation.
|
||||||
|
*/
|
||||||
|
void tpm_backend_deliver_request(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_reset:
|
||||||
|
* @s: the backend to reset
|
||||||
|
*
|
||||||
|
* Reset the backend into a well defined state with all previous errors
|
||||||
|
* reset.
|
||||||
|
*/
|
||||||
|
void tpm_backend_reset(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_cancel_cmd:
|
||||||
|
* @s: the backend
|
||||||
|
*
|
||||||
|
* Cancel any ongoing command being processed by the TPM implementation
|
||||||
|
* on behalf of the QEMU guest.
|
||||||
|
*/
|
||||||
|
void tpm_backend_cancel_cmd(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_get_tpm_established_flag:
|
||||||
|
* @s: the backend
|
||||||
|
*
|
||||||
|
* Get the TPM establishment flag. This function may be called very
|
||||||
|
* frequently by the frontend since for example in the TIS implementation
|
||||||
|
* this flag is part of a register.
|
||||||
|
*/
|
||||||
|
bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_open:
|
||||||
|
* @s: the backend to open
|
||||||
|
* @errp: a pointer to return the #Error object if an error occurs.
|
||||||
|
*
|
||||||
|
* This function will open the backend if it is not already open. Calling this
|
||||||
|
* function on an already opened backend will not result in an error.
|
||||||
|
*/
|
||||||
|
void tpm_backend_open(TPMBackend *s, Error **errp);
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,6 +14,10 @@
|
||||||
|
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
|
|
||||||
|
typedef struct TPMState TPMState;
|
||||||
|
typedef struct TPMSizedBuffer TPMSizedBuffer;
|
||||||
|
typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty);
|
||||||
|
|
||||||
int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
|
int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
|
||||||
int tpm_init(void);
|
int tpm_init(void);
|
||||||
void tpm_cleanup(void);
|
void tpm_cleanup(void);
|
||||||
|
|
11
tpm/tpm.c
11
tpm/tpm.c
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
|
#include "backends/tpm.h"
|
||||||
#include "tpm_int.h"
|
#include "tpm_int.h"
|
||||||
#include "tpm/tpm.h"
|
#include "tpm/tpm.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
|
@ -145,6 +146,7 @@ static int configure_tpm(QemuOpts *opts)
|
||||||
const char *id;
|
const char *id;
|
||||||
const TPMDriverOps *be;
|
const TPMDriverOps *be;
|
||||||
TPMBackend *drv;
|
TPMBackend *drv;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (!QLIST_EMPTY(&tpm_backends)) {
|
if (!QLIST_EMPTY(&tpm_backends)) {
|
||||||
error_report("Only one TPM is allowed.\n");
|
error_report("Only one TPM is allowed.\n");
|
||||||
|
@ -177,6 +179,13 @@ static int configure_tpm(QemuOpts *opts)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tpm_backend_open(drv, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
qerror_report_err(local_err);
|
||||||
|
error_free(local_err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
QLIST_INSERT_HEAD(&tpm_backends, drv, list);
|
QLIST_INSERT_HEAD(&tpm_backends, drv, list);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -197,7 +206,7 @@ void tpm_cleanup(void)
|
||||||
|
|
||||||
QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
|
QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
|
||||||
QLIST_REMOVE(drv, list);
|
QLIST_REMOVE(drv, list);
|
||||||
drv->ops->destroy(drv);
|
tpm_backend_destroy(drv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,22 +18,6 @@
|
||||||
struct TPMDriverOps;
|
struct TPMDriverOps;
|
||||||
typedef struct TPMDriverOps TPMDriverOps;
|
typedef struct TPMDriverOps TPMDriverOps;
|
||||||
|
|
||||||
typedef struct TPMPassthruState TPMPassthruState;
|
|
||||||
|
|
||||||
typedef struct TPMBackend {
|
|
||||||
char *id;
|
|
||||||
enum TpmModel fe_model;
|
|
||||||
char *path;
|
|
||||||
char *cancel_path;
|
|
||||||
const TPMDriverOps *ops;
|
|
||||||
|
|
||||||
union {
|
|
||||||
TPMPassthruState *tpm_pt;
|
|
||||||
} s;
|
|
||||||
|
|
||||||
QLIST_ENTRY(TPMBackend) list;
|
|
||||||
} TPMBackend;
|
|
||||||
|
|
||||||
/* overall state of the TPM interface */
|
/* overall state of the TPM interface */
|
||||||
typedef struct TPMState {
|
typedef struct TPMState {
|
||||||
ISADevice busdev;
|
ISADevice busdev;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
|
#include "backends/tpm.h"
|
||||||
#include "tpm_int.h"
|
#include "tpm_int.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/pc.h"
|
#include "hw/pc.h"
|
||||||
|
@ -43,8 +44,11 @@
|
||||||
do { } while (0)
|
do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* data structures */
|
#define TYPE_TPM_PASSTHROUGH "tpm-passthrough"
|
||||||
|
#define TPM_PASSTHROUGH(obj) \
|
||||||
|
OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
|
||||||
|
|
||||||
|
/* data structures */
|
||||||
typedef struct TPMPassthruThreadParams {
|
typedef struct TPMPassthruThreadParams {
|
||||||
TPMState *tpm_state;
|
TPMState *tpm_state;
|
||||||
|
|
||||||
|
@ -53,6 +57,8 @@ typedef struct TPMPassthruThreadParams {
|
||||||
} TPMPassthruThreadParams;
|
} TPMPassthruThreadParams;
|
||||||
|
|
||||||
struct TPMPassthruState {
|
struct TPMPassthruState {
|
||||||
|
TPMBackend parent;
|
||||||
|
|
||||||
TPMBackendThread tbt;
|
TPMBackendThread tbt;
|
||||||
|
|
||||||
TPMPassthruThreadParams tpm_thread_params;
|
TPMPassthruThreadParams tpm_thread_params;
|
||||||
|
@ -65,6 +71,8 @@ struct TPMPassthruState {
|
||||||
bool had_startup_error;
|
bool had_startup_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct TPMPassthruState TPMPassthruState;
|
||||||
|
|
||||||
#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
|
#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
|
@ -149,7 +157,7 @@ static void tpm_passthrough_worker_thread(gpointer data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
TPMPassthruThreadParams *thr_parms = user_data;
|
TPMPassthruThreadParams *thr_parms = user_data;
|
||||||
TPMPassthruState *tpm_pt = thr_parms->tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
|
||||||
TPMBackendCmd cmd = (TPMBackendCmd)data;
|
TPMBackendCmd cmd = (TPMBackendCmd)data;
|
||||||
|
|
||||||
DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
|
DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
|
||||||
|
@ -176,21 +184,21 @@ static void tpm_passthrough_worker_thread(gpointer data,
|
||||||
*/
|
*/
|
||||||
static int tpm_passthrough_startup_tpm(TPMBackend *tb)
|
static int tpm_passthrough_startup_tpm(TPMBackend *tb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
|
||||||
/* terminate a running TPM */
|
/* terminate a running TPM */
|
||||||
tpm_backend_thread_end(&tpm_pt->tbt);
|
tpm_backend_thread_end(&tpm_pt->tbt);
|
||||||
|
|
||||||
tpm_backend_thread_create(&tpm_pt->tbt,
|
tpm_backend_thread_create(&tpm_pt->tbt,
|
||||||
tpm_passthrough_worker_thread,
|
tpm_passthrough_worker_thread,
|
||||||
&tb->s.tpm_pt->tpm_thread_params);
|
&tpm_pt->tpm_thread_params);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tpm_passthrough_reset(TPMBackend *tb)
|
static void tpm_passthrough_reset(TPMBackend *tb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
|
||||||
DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n");
|
DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n");
|
||||||
|
|
||||||
|
@ -204,7 +212,7 @@ static void tpm_passthrough_reset(TPMBackend *tb)
|
||||||
static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
|
static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
|
||||||
TPMRecvDataCB *recv_data_cb)
|
TPMRecvDataCB *recv_data_cb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
|
||||||
tpm_pt->tpm_thread_params.tpm_state = s;
|
tpm_pt->tpm_thread_params.tpm_state = s;
|
||||||
tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
|
tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
|
||||||
|
@ -220,7 +228,7 @@ static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
|
||||||
|
|
||||||
static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
|
static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
|
||||||
return tpm_pt->had_startup_error;
|
return tpm_pt->had_startup_error;
|
||||||
}
|
}
|
||||||
|
@ -238,14 +246,14 @@ static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
|
||||||
|
|
||||||
static void tpm_passthrough_deliver_request(TPMBackend *tb)
|
static void tpm_passthrough_deliver_request(TPMBackend *tb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
|
||||||
tpm_backend_thread_deliver_request(&tpm_pt->tbt);
|
tpm_backend_thread_deliver_request(&tpm_pt->tbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
|
static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -412,6 +420,7 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
|
||||||
|
|
||||||
static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
|
static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
|
||||||
{
|
{
|
||||||
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
value = qemu_opt_get(opts, "cancel-path");
|
value = qemu_opt_get(opts, "cancel-path");
|
||||||
|
@ -424,45 +433,45 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
|
||||||
value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
|
value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tb->s.tpm_pt->tpm_dev = g_strdup(value);
|
tpm_pt->tpm_dev = g_strdup(value);
|
||||||
|
|
||||||
tb->path = g_strdup(tb->s.tpm_pt->tpm_dev);
|
tb->path = g_strdup(tpm_pt->tpm_dev);
|
||||||
|
|
||||||
tb->s.tpm_pt->tpm_fd = qemu_open(tb->s.tpm_pt->tpm_dev, O_RDWR);
|
tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
|
||||||
if (tb->s.tpm_pt->tpm_fd < 0) {
|
if (tpm_pt->tpm_fd < 0) {
|
||||||
error_report("Cannot access TPM device using '%s': %s\n",
|
error_report("Cannot access TPM device using '%s': %s\n",
|
||||||
tb->s.tpm_pt->tpm_dev, strerror(errno));
|
tpm_pt->tpm_dev, strerror(errno));
|
||||||
goto err_free_parameters;
|
goto err_free_parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) {
|
if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) {
|
||||||
error_report("'%s' is not a TPM device.\n",
|
error_report("'%s' is not a TPM device.\n",
|
||||||
tb->s.tpm_pt->tpm_dev);
|
tpm_pt->tpm_dev);
|
||||||
goto err_close_tpmdev;
|
goto err_close_tpmdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_close_tpmdev:
|
err_close_tpmdev:
|
||||||
qemu_close(tb->s.tpm_pt->tpm_fd);
|
qemu_close(tpm_pt->tpm_fd);
|
||||||
tb->s.tpm_pt->tpm_fd = -1;
|
tpm_pt->tpm_fd = -1;
|
||||||
|
|
||||||
err_free_parameters:
|
err_free_parameters:
|
||||||
g_free(tb->path);
|
g_free(tb->path);
|
||||||
tb->path = NULL;
|
tb->path = NULL;
|
||||||
|
|
||||||
g_free(tb->s.tpm_pt->tpm_dev);
|
g_free(tpm_pt->tpm_dev);
|
||||||
tb->s.tpm_pt->tpm_dev = NULL;
|
tpm_pt->tpm_dev = NULL;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
|
static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
|
||||||
{
|
{
|
||||||
TPMBackend *tb;
|
Object *obj = object_new(TYPE_TPM_PASSTHROUGH);
|
||||||
|
TPMBackend *tb = TPM_BACKEND(obj);
|
||||||
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
|
||||||
tb = g_new0(TPMBackend, 1);
|
|
||||||
tb->s.tpm_pt = g_new0(TPMPassthruState, 1);
|
|
||||||
tb->id = g_strdup(id);
|
tb->id = g_strdup(id);
|
||||||
/* let frontend set the fe_model to proper value */
|
/* let frontend set the fe_model to proper value */
|
||||||
tb->fe_model = -1;
|
tb->fe_model = -1;
|
||||||
|
@ -473,8 +482,8 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
tb->s.tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
|
tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
|
||||||
if (tb->s.tpm_pt->cancel_fd < 0) {
|
if (tpm_pt->cancel_fd < 0) {
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,29 +491,25 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
|
||||||
|
|
||||||
err_exit:
|
err_exit:
|
||||||
g_free(tb->id);
|
g_free(tb->id);
|
||||||
g_free(tb->s.tpm_pt);
|
|
||||||
g_free(tb);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tpm_passthrough_destroy(TPMBackend *tb)
|
static void tpm_passthrough_destroy(TPMBackend *tb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
|
||||||
tpm_passthrough_cancel_cmd(tb);
|
tpm_passthrough_cancel_cmd(tb);
|
||||||
|
|
||||||
tpm_backend_thread_end(&tpm_pt->tbt);
|
tpm_backend_thread_end(&tpm_pt->tbt);
|
||||||
|
|
||||||
qemu_close(tpm_pt->tpm_fd);
|
qemu_close(tpm_pt->tpm_fd);
|
||||||
qemu_close(tb->s.tpm_pt->cancel_fd);
|
qemu_close(tpm_pt->cancel_fd);
|
||||||
|
|
||||||
g_free(tb->id);
|
g_free(tb->id);
|
||||||
g_free(tb->path);
|
g_free(tb->path);
|
||||||
g_free(tb->cancel_path);
|
g_free(tb->cancel_path);
|
||||||
g_free(tb->s.tpm_pt->tpm_dev);
|
g_free(tpm_pt->tpm_dev);
|
||||||
g_free(tb->s.tpm_pt);
|
|
||||||
g_free(tb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const TPMDriverOps tpm_passthrough_driver = {
|
const TPMDriverOps tpm_passthrough_driver = {
|
||||||
|
@ -522,8 +527,33 @@ const TPMDriverOps tpm_passthrough_driver = {
|
||||||
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
|
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void tpm_passthrough_inst_init(Object *obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tpm_passthrough_inst_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
|
||||||
|
|
||||||
|
tbc->ops = &tpm_passthrough_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo tpm_passthrough_info = {
|
||||||
|
.name = TYPE_TPM_PASSTHROUGH,
|
||||||
|
.parent = TYPE_TPM_BACKEND,
|
||||||
|
.instance_size = sizeof(TPMPassthruState),
|
||||||
|
.class_init = tpm_passthrough_class_init,
|
||||||
|
.instance_init = tpm_passthrough_inst_init,
|
||||||
|
.instance_finalize = tpm_passthrough_inst_finalize,
|
||||||
|
};
|
||||||
|
|
||||||
static void tpm_passthrough_register(void)
|
static void tpm_passthrough_register(void)
|
||||||
{
|
{
|
||||||
|
type_register_static(&tpm_passthrough_info);
|
||||||
tpm_register_driver(&tpm_passthrough_driver);
|
tpm_register_driver(&tpm_passthrough_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* specification.
|
* specification.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "backends/tpm.h"
|
||||||
#include "tpm_int.h"
|
#include "tpm_int.h"
|
||||||
#include "block/block.h"
|
#include "block/block.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
|
@ -160,7 +161,7 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
|
||||||
*/
|
*/
|
||||||
tis->loc[locty].state = TPM_TIS_STATE_EXECUTION;
|
tis->loc[locty].state = TPM_TIS_STATE_EXECUTION;
|
||||||
|
|
||||||
s->be_driver->ops->deliver_request(s->be_driver);
|
tpm_backend_deliver_request(s->be_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* raise an interrupt if allowed */
|
/* raise an interrupt if allowed */
|
||||||
|
@ -284,7 +285,7 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
|
||||||
* request the backend to cancel. Some backends may not
|
* request the backend to cancel. Some backends may not
|
||||||
* support it
|
* support it
|
||||||
*/
|
*/
|
||||||
s->be_driver->ops->cancel_cmd(s->be_driver);
|
tpm_backend_cancel_cmd(s->be_driver);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +427,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
|
||||||
uint8_t locty = tpm_tis_locality_from_addr(addr);
|
uint8_t locty = tpm_tis_locality_from_addr(addr);
|
||||||
uint32_t avail;
|
uint32_t avail;
|
||||||
|
|
||||||
if (s->be_driver->ops->had_startup_error(s->be_driver)) {
|
if (tpm_backend_had_startup_error(s->be_driver)) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +439,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
|
||||||
if (tpm_tis_check_request_use_except(s, locty)) {
|
if (tpm_tis_check_request_use_except(s, locty)) {
|
||||||
val |= TPM_TIS_ACCESS_PENDING_REQUEST;
|
val |= TPM_TIS_ACCESS_PENDING_REQUEST;
|
||||||
}
|
}
|
||||||
val |= !s->be_driver->ops->get_tpm_established_flag(s->be_driver);
|
val |= !tpm_backend_get_tpm_established_flag(s->be_driver);
|
||||||
break;
|
break;
|
||||||
case TPM_TIS_REG_INT_ENABLE:
|
case TPM_TIS_REG_INT_ENABLE:
|
||||||
val = tis->loc[locty].inte;
|
val = tis->loc[locty].inte;
|
||||||
|
@ -529,7 +530,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->be_driver->ops->had_startup_error(s->be_driver)) {
|
if (tpm_backend_had_startup_error(s->be_driver)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,7 +805,7 @@ static const MemoryRegionOps tpm_tis_memory_ops = {
|
||||||
|
|
||||||
static int tpm_tis_do_startup_tpm(TPMState *s)
|
static int tpm_tis_do_startup_tpm(TPMState *s)
|
||||||
{
|
{
|
||||||
return s->be_driver->ops->startup_tpm(s->be_driver);
|
return tpm_backend_startup_tpm(s->be_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -817,7 +818,7 @@ static void tpm_tis_reset(DeviceState *dev)
|
||||||
TPMTISEmuState *tis = &s->s.tis;
|
TPMTISEmuState *tis = &s->s.tis;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
s->be_driver->ops->reset(s->be_driver);
|
tpm_backend_reset(s->be_driver);
|
||||||
|
|
||||||
tis->active_locty = TPM_TIS_NO_LOCALITY;
|
tis->active_locty = TPM_TIS_NO_LOCALITY;
|
||||||
tis->next_locty = TPM_TIS_NO_LOCALITY;
|
tis->next_locty = TPM_TIS_NO_LOCALITY;
|
||||||
|
@ -831,9 +832,9 @@ static void tpm_tis_reset(DeviceState *dev)
|
||||||
tis->loc[c].state = TPM_TIS_STATE_IDLE;
|
tis->loc[c].state = TPM_TIS_STATE_IDLE;
|
||||||
|
|
||||||
tis->loc[c].w_offset = 0;
|
tis->loc[c].w_offset = 0;
|
||||||
s->be_driver->ops->realloc_buffer(&tis->loc[c].w_buffer);
|
tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer);
|
||||||
tis->loc[c].r_offset = 0;
|
tis->loc[c].r_offset = 0;
|
||||||
s->be_driver->ops->realloc_buffer(&tis->loc[c].r_buffer);
|
tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
tpm_tis_do_startup_tpm(s);
|
tpm_tis_do_startup_tpm(s);
|
||||||
|
@ -865,7 +866,7 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
|
s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
|
||||||
|
|
||||||
if (s->be_driver->ops->init(s->be_driver, s, tpm_tis_receive_cb)) {
|
if (tpm_backend_init(s->be_driver, s, tpm_tis_receive_cb)) {
|
||||||
error_setg(errp, "tpm_tis: backend driver with id %s could not be "
|
error_setg(errp, "tpm_tis: backend driver with id %s could not be "
|
||||||
"initialized", s->backend);
|
"initialized", s->backend);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue