/*
 * 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 "tpm-emu.h"

void tpm_emu_test_wait_cond(TestState *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_tpm_thread(void *data)
{
    TestState *s = data;
    QIOChannel *ioc = s->tpm_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 */
        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);
        qio_channel_write(ioc, (char *)s->tpm_msg, be32_to_cpu(s->tpm_msg->len),
                          &error_abort);
    }

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

void *tpm_emu_ctrl_thread(void *data)
{
    TestState *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);

    {
        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, &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();
        }
    }

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