/*
 * Minimal TPM emulator for TPM test cases
 *
 * Copyright (c) 2018 Red Hat, Inc.
 *
 * Authors:
 *   Marc-André Lureau <marcandre.lureau@redhat.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.
 */

#include "qemu/osdep.h"
#include <glib/gstdio.h>

#include "backends/tpm/tpm_ioctl.h"
#include "io/channel-socket.h"
#include "qapi/error.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
#include "tpm-emu.h"

void tpm_emu_test_wait_cond(TPMTestState *s)
{
    gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;

    g_mutex_lock(&s->data_mutex);

    if (!s->data_cond_signal &&
        !g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
        g_assert_not_reached();
    }

    s->data_cond_signal = false;

    g_mutex_unlock(&s->data_mutex);
}

static void tpm_emu_close_ioc(void *ioc)
{
    qio_channel_close(ioc, NULL);
}

static void *tpm_emu_tpm_thread(void *data)
{
    TPMTestState *s = data;
    QIOChannel *ioc = s->tpm_ioc;

    qtest_add_abrt_handler(tpm_emu_close_ioc, ioc);

    s->tpm_msg = g_new(struct tpm_hdr, 1);
    while (true) {
        int minhlen = sizeof(s->tpm_msg->tag) + sizeof(s->tpm_msg->len);

        if (!qio_channel_read(ioc, (char *)s->tpm_msg, minhlen, &error_abort)) {
            break;
        }
        s->tpm_msg->tag = be16_to_cpu(s->tpm_msg->tag);
        s->tpm_msg->len = be32_to_cpu(s->tpm_msg->len);
        g_assert_cmpint(s->tpm_msg->len, >=, minhlen);

        s->tpm_msg = g_realloc(s->tpm_msg, s->tpm_msg->len);
        qio_channel_read(ioc, (char *)&s->tpm_msg->code,
                         s->tpm_msg->len - minhlen, &error_abort);
        s->tpm_msg->code = be32_to_cpu(s->tpm_msg->code);

        /* reply error */
        switch (s->tpm_version) {
        case TPM_VERSION_2_0:
            s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
            s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
            s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE);
            break;
        case TPM_VERSION_1_2:
            s->tpm_msg->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
            s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
            s->tpm_msg->code = cpu_to_be32(TPM_FAIL);
            break;
        default:
            g_debug("unsupported TPM version %u", s->tpm_version);
            g_assert_not_reached();
        }
        qio_channel_write(ioc, (char *)s->tpm_msg, be32_to_cpu(s->tpm_msg->len),
                          &error_abort);
    }

    qtest_remove_abrt_handler(ioc);
    g_free(s->tpm_msg);
    s->tpm_msg = NULL;
    object_unref(OBJECT(s->tpm_ioc));
    return NULL;
}

void *tpm_emu_ctrl_thread(void *data)
{
    TPMTestState *s = data;
    QIOChannelSocket *lioc = qio_channel_socket_new();
    QIOChannel *ioc;

    qio_channel_socket_listen_sync(lioc, s->addr, 1, &error_abort);

    g_mutex_lock(&s->data_mutex);
    s->data_cond_signal = true;
    g_mutex_unlock(&s->data_mutex);
    g_cond_signal(&s->data_cond);

    qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
    ioc = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
    g_assert(ioc);
    qtest_add_abrt_handler(tpm_emu_close_ioc, ioc);

    {
        uint32_t cmd = 0;
        struct iovec iov = { .iov_base = &cmd, .iov_len = sizeof(cmd) };
        int *pfd = NULL;
        size_t nfd = 0;

        qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, 0, &error_abort);
        cmd = be32_to_cpu(cmd);
        g_assert_cmpint(cmd, ==, CMD_SET_DATAFD);
        g_assert_cmpint(nfd, ==, 1);
        s->tpm_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(*pfd, &error_abort));
        g_free(pfd);

        cmd = 0;
        qio_channel_write(ioc, (char *)&cmd, sizeof(cmd), &error_abort);

        s->emu_tpm_thread = g_thread_new(NULL, tpm_emu_tpm_thread, s);
    }

    while (true) {
        uint32_t cmd;
        ssize_t ret;

        ret = qio_channel_read(ioc, (char *)&cmd, sizeof(cmd), NULL);
        if (ret <= 0) {
            break;
        }

        cmd = be32_to_cpu(cmd);
        switch (cmd) {
        case CMD_GET_CAPABILITY: {
            ptm_cap cap = cpu_to_be64(0x3fff);
            qio_channel_write(ioc, (char *)&cap, sizeof(cap), &error_abort);
            break;
        }
        case CMD_INIT: {
            ptm_init init;
            qio_channel_read(ioc, (char *)&init.u.req, sizeof(init.u.req),
                              &error_abort);
            init.u.resp.tpm_result = 0;
            qio_channel_write(ioc, (char *)&init.u.resp, sizeof(init.u.resp),
                              &error_abort);
            break;
        }
        case CMD_SHUTDOWN: {
            ptm_res res = 0;
            qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort);
            /* the tpm data thread is expected to finish now */
            g_thread_join(s->emu_tpm_thread);
            break;
        }
        case CMD_STOP: {
            ptm_res res = 0;
            qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort);
            break;
        }
        case CMD_SET_BUFFERSIZE: {
            ptm_setbuffersize sbs;
            qio_channel_read(ioc, (char *)&sbs.u.req, sizeof(sbs.u.req),
                             &error_abort);
            sbs.u.resp.buffersize = sbs.u.req.buffersize ?: cpu_to_be32(4096);
            sbs.u.resp.tpm_result = 0;
            sbs.u.resp.minsize = cpu_to_be32(128);
            sbs.u.resp.maxsize = cpu_to_be32(4096);
            qio_channel_write(ioc, (char *)&sbs.u.resp, sizeof(sbs.u.resp),
                              &error_abort);
            break;
        }
        case CMD_SET_LOCALITY: {
            ptm_loc loc;
            /* Note: this time it's not u.req / u.resp... */
            qio_channel_read(ioc, (char *)&loc, sizeof(loc), &error_abort);
            g_assert_cmpint(loc.u.req.loc, ==, 0);
            loc.u.resp.tpm_result = 0;
            qio_channel_write(ioc, (char *)&loc, sizeof(loc), &error_abort);
            break;
        }
        case CMD_GET_TPMESTABLISHED: {
            ptm_est est = {
                .u.resp.bit = 0,
            };
            qio_channel_write(ioc, (char *)&est, sizeof(est), &error_abort);
            break;
        }
        default:
            g_debug("unimplemented %u", cmd);
            g_assert_not_reached();
        }
    }

    qtest_remove_abrt_handler(ioc);
    object_unref(OBJECT(ioc));
    object_unref(OBJECT(lioc));
    return NULL;
}

bool tpm_model_is_available(const char *args, const char *tpm_if)
{
    QTestState *qts;
    QDict *rsp_tpm;
    bool ret = false;

    qts = qtest_init(args);
    if (!qts) {
        return false;
    }

    rsp_tpm = qtest_qmp(qts, "{ 'execute': 'query-tpm'}");
    if (!qdict_haskey(rsp_tpm, "error")) {
        QDict *rsp_models = qtest_qmp(qts,
                                      "{ 'execute': 'query-tpm-models'}");
        if (qdict_haskey(rsp_models, "return")) {
            QList *models = qdict_get_qlist(rsp_models, "return");
            QListEntry *e;

            QLIST_FOREACH_ENTRY(models, e) {
                QString *s = qobject_to(QString, qlist_entry_obj(e));
                const char *ename = qstring_get_str(s);
                if (!strcmp(ename, tpm_if)) {
                    ret = true;
                    break;
                }
            }
        }
        qobject_unref(rsp_models);
    }
    qobject_unref(rsp_tpm);
    qtest_quit(qts);

    return ret;
}
