/*
 * 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.\n");
        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(QemuOpts *opts, void *dummy)
{
    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, 1) != 0) {
        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;
}
