/*
 * TPM configuration
 *
 * Copyright (C) 2011-2013 IBM Corporation
 *
 * 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 net.c
 */
#include "config-host.h"

#include "monitor/monitor.h"
#include "qapi/qmp/qerror.h"
#include "sysemu/tpm_backend.h"
#include "sysemu/tpm.h"
#include "qemu/config-file.h"
#include "qmp-commands.h"

static QLIST_HEAD(, TPMBackend) tpm_backends =
    QLIST_HEAD_INITIALIZER(tpm_backends);


#define TPM_MAX_MODELS      1
#define TPM_MAX_DRIVERS     1

static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
    NULL,
};

static enum TpmModel tpm_models[TPM_MAX_MODELS] = {
    TPM_MODEL_MAX,
};

int tpm_register_model(enum TpmModel model)
{
    int i;

    for (i = 0; i < TPM_MAX_MODELS; i++) {
        if (tpm_models[i] == TPM_MODEL_MAX) {
            tpm_models[i] = model;
            return 0;
        }
    }
    error_report("Could not register TPM model");
    return 1;
}

static bool tpm_model_is_registered(enum TpmModel model)
{
    int i;

    for (i = 0; i < TPM_MAX_MODELS; i++) {
        if (tpm_models[i] == model) {
            return true;
        }
    }
    return false;
}

const TPMDriverOps *tpm_get_backend_driver(const char *type)
{
    int i;

    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
        if (!strcmp(TpmType_lookup[be_drivers[i]->type], type)) {
            return be_drivers[i];
        }
    }

    return NULL;
}

#ifdef CONFIG_TPM

int tpm_register_driver(const TPMDriverOps *tdo)
{
    int i;

    for (i = 0; i < TPM_MAX_DRIVERS; i++) {
        if (!be_drivers[i]) {
            be_drivers[i] = tdo;
            return 0;
        }
    }
    error_report("Could not register TPM driver");
    return 1;
}

/*
 * Walk the list of available TPM backend drivers and display them on the
 * screen.
 */
static void tpm_display_backend_drivers(void)
{
    int i;

    fprintf(stderr, "Supported TPM types (choose only one):\n");

    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
        fprintf(stderr, "%12s   %s\n",
                TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc());
    }
    fprintf(stderr, "\n");
}

/*
 * Find the TPM with the given Id
 */
TPMBackend *qemu_find_tpm(const char *id)
{
    TPMBackend *drv;

    if (id) {
        QLIST_FOREACH(drv, &tpm_backends, list) {
            if (!strcmp(drv->id, id)) {
                return drv;
            }
        }
    }

    return NULL;
}

static int configure_tpm(QemuOpts *opts)
{
    const char *value;
    const char *id;
    const TPMDriverOps *be;
    TPMBackend *drv;
    Error *local_err = NULL;

    if (!QLIST_EMPTY(&tpm_backends)) {
        error_report("Only one TPM is allowed.");
        return 1;
    }

    id = qemu_opts_id(opts);
    if (id == NULL) {
        qerror_report(QERR_MISSING_PARAMETER, "id");
        return 1;
    }

    value = qemu_opt_get(opts, "type");
    if (!value) {
        qerror_report(QERR_MISSING_PARAMETER, "type");
        tpm_display_backend_drivers();
        return 1;
    }

    be = tpm_get_backend_driver(value);
    if (be == NULL) {
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
                      "a TPM backend type");
        tpm_display_backend_drivers();
        return 1;
    }

    /* validate backend specific opts */
    qemu_opts_validate(opts, be->opts, &local_err);
    if (local_err) {
        error_report_err(local_err);
        return 1;
    }

    drv = be->create(opts, id);
    if (!drv) {
        return 1;
    }

    tpm_backend_open(drv, &local_err);
    if (local_err) {
        error_report_err(local_err);
        return 1;
    }

    QLIST_INSERT_HEAD(&tpm_backends, drv, list);

    return 0;
}

static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp)
{
    return configure_tpm(opts);
}

/*
 * Walk the list of TPM backend drivers that are in use and call their
 * destroy function to have them cleaned up.
 */
void tpm_cleanup(void)
{
    TPMBackend *drv, *next;

    QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
        QLIST_REMOVE(drv, list);
        tpm_backend_destroy(drv);
    }
}

/*
 * Initialize the TPM. Process the tpmdev command line options describing the
 * TPM backend.
 */
int tpm_init(void)
{
    if (qemu_opts_foreach(qemu_find_opts("tpmdev"),
                          tpm_init_tpmdev, NULL, NULL)) {
        return -1;
    }

    atexit(tpm_cleanup);
    return 0;
}

/*
 * Parse the TPM configuration options.
 * To display all available TPM backends the user may use '-tpmdev help'
 */
int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
{
    QemuOpts *opts;

    if (!strcmp(optarg, "help")) {
        tpm_display_backend_drivers();
        return -1;
    }
    opts = qemu_opts_parse(opts_list, optarg, 1);
    if (!opts) {
        return -1;
    }
    return 0;
}

#endif /* CONFIG_TPM */

static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
{
    int i;

    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
        if (be_drivers[i]->type == type) {
            return be_drivers[i];
        }
    }
    return NULL;
}

static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
{
    TPMInfo *res = g_new0(TPMInfo, 1);
    TPMPassthroughOptions *tpo;

    res->id = g_strdup(drv->id);
    res->model = drv->fe_model;
    res->options = g_new0(TpmTypeOptions, 1);

    switch (drv->ops->type) {
    case TPM_TYPE_PASSTHROUGH:
        res->options->kind = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
        tpo = g_new0(TPMPassthroughOptions, 1);
        res->options->passthrough = tpo;
        if (drv->path) {
            tpo->path = g_strdup(drv->path);
            tpo->has_path = true;
        }
        if (drv->cancel_path) {
            tpo->cancel_path = g_strdup(drv->cancel_path);
            tpo->has_cancel_path = true;
        }
        break;
    case TPM_TYPE_MAX:
        break;
    }

    return res;
}

/*
 * Walk the list of active TPM backends and collect information about them
 * following the schema description in qapi-schema.json.
 */
TPMInfoList *qmp_query_tpm(Error **errp)
{
    TPMBackend *drv;
    TPMInfoList *info, *head = NULL, *cur_item = NULL;

    QLIST_FOREACH(drv, &tpm_backends, list) {
        if (!tpm_model_is_registered(drv->fe_model)) {
            continue;
        }
        info = g_new0(TPMInfoList, 1);
        info->value = qmp_query_tpm_inst(drv);

        if (!cur_item) {
            head = cur_item = info;
        } else {
            cur_item->next = info;
            cur_item = info;
        }
    }

    return head;
}

TpmTypeList *qmp_query_tpm_types(Error **errp)
{
    unsigned int i = 0;
    TpmTypeList *head = NULL, *prev = NULL, *cur_item;

    for (i = 0; i < TPM_TYPE_MAX; i++) {
        if (!tpm_driver_find_by_type(i)) {
            continue;
        }
        cur_item = g_new0(TpmTypeList, 1);
        cur_item->value = i;

        if (prev) {
            prev->next = cur_item;
        }
        if (!head) {
            head = cur_item;
        }
        prev = cur_item;
    }

    return head;
}

TpmModelList *qmp_query_tpm_models(Error **errp)
{
    unsigned int i = 0;
    TpmModelList *head = NULL, *prev = NULL, *cur_item;

    for (i = 0; i < TPM_MODEL_MAX; i++) {
        if (!tpm_model_is_registered(i)) {
            continue;
        }
        cur_item = g_new0(TpmModelList, 1);
        cur_item->value = i;

        if (prev) {
            prev->next = cur_item;
        }
        if (!head) {
            head = cur_item;
        }
        prev = cur_item;
    }

    return head;
}
