Commit 8f0605cc authored by Stefan Berger's avatar Stefan Berger Committed by Anthony Liguori
Browse files

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: default avatarStefan Berger <stefanb@linux.vnet.ibm.com>
Message-id: 1364469981.24703.1.camel@d941e-10
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parent 684a096e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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

backends/tpm.c

0 → 100644
+154 −0
Original line number Diff line number Diff line
/*
 * 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);

include/backends/tpm.h

0 → 100644
+170 −0
Original line number Diff line number Diff line
/*
 * 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
+4 −0
Original line number Diff line number Diff line
@@ -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);
+10 −1
Original line number Diff line number Diff line
@@ -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);
    }
}

Loading