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-$(CONFIG_BRLAPI) += baum.o
 | 
			
		||||
$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) 
 | 
			
		||||
 | 
			
		||||
common-obj-$(CONFIG_TPM) += tpm.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										154
									
								
								backends/tpm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								backends/tpm.c
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
			
		||||
							
								
								
									
										170
									
								
								include/backends/tpm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								include/backends/tpm.h
									
									
									
									
									
										Normal file
									
								
							@ -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"
 | 
			
		||||
 | 
			
		||||
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_init(void);
 | 
			
		||||
void tpm_cleanup(void);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								tpm/tpm.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								tpm/tpm.c
									
									
									
									
									
								
							@ -15,6 +15,7 @@
 | 
			
		||||
 | 
			
		||||
#include "monitor/monitor.h"
 | 
			
		||||
#include "qapi/qmp/qerror.h"
 | 
			
		||||
#include "backends/tpm.h"
 | 
			
		||||
#include "tpm_int.h"
 | 
			
		||||
#include "tpm/tpm.h"
 | 
			
		||||
#include "qemu/config-file.h"
 | 
			
		||||
@ -145,6 +146,7 @@ static int configure_tpm(QemuOpts *opts)
 | 
			
		||||
    const char *id;
 | 
			
		||||
    const TPMDriverOps *be;
 | 
			
		||||
    TPMBackend *drv;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    if (!QLIST_EMPTY(&tpm_backends)) {
 | 
			
		||||
        error_report("Only one TPM is allowed.\n");
 | 
			
		||||
@ -177,6 +179,13 @@ static int configure_tpm(QemuOpts *opts)
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
@ -197,7 +206,7 @@ void tpm_cleanup(void)
 | 
			
		||||
 | 
			
		||||
    QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
 | 
			
		||||
        QLIST_REMOVE(drv, list);
 | 
			
		||||
        drv->ops->destroy(drv);
 | 
			
		||||
        tpm_backend_destroy(drv);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -18,22 +18,6 @@
 | 
			
		||||
struct 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 */
 | 
			
		||||
typedef struct TPMState {
 | 
			
		||||
    ISADevice busdev;
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "qemu/sockets.h"
 | 
			
		||||
#include "backends/tpm.h"
 | 
			
		||||
#include "tpm_int.h"
 | 
			
		||||
#include "hw/hw.h"
 | 
			
		||||
#include "hw/pc.h"
 | 
			
		||||
@ -43,8 +44,11 @@
 | 
			
		||||
    do { } while (0)
 | 
			
		||||
#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 {
 | 
			
		||||
    TPMState *tpm_state;
 | 
			
		||||
 | 
			
		||||
@ -53,6 +57,8 @@ typedef struct TPMPassthruThreadParams {
 | 
			
		||||
} TPMPassthruThreadParams;
 | 
			
		||||
 | 
			
		||||
struct TPMPassthruState {
 | 
			
		||||
    TPMBackend parent;
 | 
			
		||||
 | 
			
		||||
    TPMBackendThread tbt;
 | 
			
		||||
 | 
			
		||||
    TPMPassthruThreadParams tpm_thread_params;
 | 
			
		||||
@ -65,6 +71,8 @@ struct TPMPassthruState {
 | 
			
		||||
    bool had_startup_error;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct TPMPassthruState TPMPassthruState;
 | 
			
		||||
 | 
			
		||||
#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
 | 
			
		||||
 | 
			
		||||
/* functions */
 | 
			
		||||
@ -149,7 +157,7 @@ static void tpm_passthrough_worker_thread(gpointer data,
 | 
			
		||||
                                          gpointer 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;
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
 | 
			
		||||
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 | 
			
		||||
 | 
			
		||||
    /* terminate a running TPM */
 | 
			
		||||
    tpm_backend_thread_end(&tpm_pt->tbt);
 | 
			
		||||
 | 
			
		||||
    tpm_backend_thread_create(&tpm_pt->tbt,
 | 
			
		||||
                              tpm_passthrough_worker_thread,
 | 
			
		||||
                              &tb->s.tpm_pt->tpm_thread_params);
 | 
			
		||||
                              &tpm_pt->tpm_thread_params);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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");
 | 
			
		||||
 | 
			
		||||
@ -204,7 +212,7 @@ static void tpm_passthrough_reset(TPMBackend *tb)
 | 
			
		||||
static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
 | 
			
		||||
                                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.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)
 | 
			
		||||
{
 | 
			
		||||
    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
 | 
			
		||||
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
 | 
			
		||||
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 | 
			
		||||
 | 
			
		||||
    tpm_backend_thread_deliver_request(&tpm_pt->tbt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
 | 
			
		||||
{
 | 
			
		||||
    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
 | 
			
		||||
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 | 
			
		||||
    const char *value;
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    if (tb->s.tpm_pt->tpm_fd < 0) {
 | 
			
		||||
    tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
 | 
			
		||||
    if (tpm_pt->tpm_fd < 0) {
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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",
 | 
			
		||||
                     tb->s.tpm_pt->tpm_dev);
 | 
			
		||||
                     tpm_pt->tpm_dev);
 | 
			
		||||
        goto err_close_tpmdev;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
 err_close_tpmdev:
 | 
			
		||||
    qemu_close(tb->s.tpm_pt->tpm_fd);
 | 
			
		||||
    tb->s.tpm_pt->tpm_fd = -1;
 | 
			
		||||
    qemu_close(tpm_pt->tpm_fd);
 | 
			
		||||
    tpm_pt->tpm_fd = -1;
 | 
			
		||||
 | 
			
		||||
 err_free_parameters:
 | 
			
		||||
    g_free(tb->path);
 | 
			
		||||
    tb->path = NULL;
 | 
			
		||||
 | 
			
		||||
    g_free(tb->s.tpm_pt->tpm_dev);
 | 
			
		||||
    tb->s.tpm_pt->tpm_dev = NULL;
 | 
			
		||||
    g_free(tpm_pt->tpm_dev);
 | 
			
		||||
    tpm_pt->tpm_dev = NULL;
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
    /* let frontend set the fe_model to proper value */
 | 
			
		||||
    tb->fe_model = -1;
 | 
			
		||||
@ -473,8 +482,8 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
 | 
			
		||||
        goto err_exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tb->s.tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
 | 
			
		||||
    if (tb->s.tpm_pt->cancel_fd < 0) {
 | 
			
		||||
    tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
 | 
			
		||||
    if (tpm_pt->cancel_fd < 0) {
 | 
			
		||||
        goto err_exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -482,29 +491,25 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
 | 
			
		||||
 | 
			
		||||
err_exit:
 | 
			
		||||
    g_free(tb->id);
 | 
			
		||||
    g_free(tb->s.tpm_pt);
 | 
			
		||||
    g_free(tb);
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_backend_thread_end(&tpm_pt->tbt);
 | 
			
		||||
 | 
			
		||||
    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->path);
 | 
			
		||||
    g_free(tb->cancel_path);
 | 
			
		||||
    g_free(tb->s.tpm_pt->tpm_dev);
 | 
			
		||||
    g_free(tb->s.tpm_pt);
 | 
			
		||||
    g_free(tb);
 | 
			
		||||
    g_free(tpm_pt->tpm_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TPMDriverOps tpm_passthrough_driver = {
 | 
			
		||||
@ -522,8 +527,33 @@ const TPMDriverOps tpm_passthrough_driver = {
 | 
			
		||||
    .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)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&tpm_passthrough_info);
 | 
			
		||||
    tpm_register_driver(&tpm_passthrough_driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@
 | 
			
		||||
 * specification.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "backends/tpm.h"
 | 
			
		||||
#include "tpm_int.h"
 | 
			
		||||
#include "block/block.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;
 | 
			
		||||
 | 
			
		||||
    s->be_driver->ops->deliver_request(s->be_driver);
 | 
			
		||||
    tpm_backend_deliver_request(s->be_driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
             * support it
 | 
			
		||||
             */
 | 
			
		||||
            s->be_driver->ops->cancel_cmd(s->be_driver);
 | 
			
		||||
            tpm_backend_cancel_cmd(s->be_driver);
 | 
			
		||||
            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);
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -438,7 +439,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
 | 
			
		||||
        if (tpm_tis_check_request_use_except(s, locty)) {
 | 
			
		||||
            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;
 | 
			
		||||
    case TPM_TIS_REG_INT_ENABLE:
 | 
			
		||||
        val = tis->loc[locty].inte;
 | 
			
		||||
@ -529,7 +530,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s->be_driver->ops->had_startup_error(s->be_driver)) {
 | 
			
		||||
    if (tpm_backend_had_startup_error(s->be_driver)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -804,7 +805,7 @@ static const MemoryRegionOps tpm_tis_memory_ops = {
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    int c;
 | 
			
		||||
 | 
			
		||||
    s->be_driver->ops->reset(s->be_driver);
 | 
			
		||||
    tpm_backend_reset(s->be_driver);
 | 
			
		||||
 | 
			
		||||
    tis->active_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].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;
 | 
			
		||||
        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);
 | 
			
		||||
@ -865,7 +866,7 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
 | 
			
		||||
 | 
			
		||||
    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 "
 | 
			
		||||
                   "initialized", s->backend);
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user