/*
 * SPAPR TPM Proxy/Hypercall
 *
 * Copyright IBM Corp. 2019
 *
 * Authors:
 *  Michael Roth      <mdroth@linux.vnet.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.
 */

#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/reset.h"
#include "hw/ppc/spapr.h"
#include "hw/qdev-properties.h"
#include "trace.h"

#define TPM_SPAPR_BUFSIZE 4096

enum {
    TPM_COMM_OP_EXECUTE = 1,
    TPM_COMM_OP_CLOSE_SESSION = 2,
};

static void spapr_tpm_proxy_reset(void *opaque)
{
    SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(opaque);

    if (tpm_proxy->host_fd != -1) {
        close(tpm_proxy->host_fd);
        tpm_proxy->host_fd = -1;
    }
}

static ssize_t tpm_execute(SpaprTpmProxy *tpm_proxy, target_ulong *args)
{
    uint64_t data_in = ppc64_phys_to_real(args[1]);
    target_ulong data_in_size = args[2];
    uint64_t data_out = ppc64_phys_to_real(args[3]);
    target_ulong data_out_size = args[4];
    uint8_t buf_in[TPM_SPAPR_BUFSIZE];
    uint8_t buf_out[TPM_SPAPR_BUFSIZE];
    ssize_t ret;

    trace_spapr_tpm_execute(data_in, data_in_size, data_out, data_out_size);

    if (data_in_size > TPM_SPAPR_BUFSIZE) {
        error_report("invalid TPM input buffer size: " TARGET_FMT_lu,
                     data_in_size);
        return H_P3;
    }

    if (data_out_size < TPM_SPAPR_BUFSIZE) {
        error_report("invalid TPM output buffer size: " TARGET_FMT_lu,
                     data_out_size);
        return H_P5;
    }

    if (tpm_proxy->host_fd == -1) {
        tpm_proxy->host_fd = open(tpm_proxy->host_path, O_RDWR);
        if (tpm_proxy->host_fd == -1) {
            error_report("failed to open TPM device %s: %d",
                         tpm_proxy->host_path, errno);
            return H_RESOURCE;
        }
    }

    cpu_physical_memory_read(data_in, buf_in, data_in_size);

    do {
        ret = write(tpm_proxy->host_fd, buf_in, data_in_size);
        if (ret > 0) {
            data_in_size -= ret;
        }
    } while ((ret >= 0 && data_in_size > 0) || (ret == -1 && errno == EINTR));

    if (ret == -1) {
        error_report("failed to write to TPM device %s: %d",
                     tpm_proxy->host_path, errno);
        return H_RESOURCE;
    }

    do {
        ret = read(tpm_proxy->host_fd, buf_out, data_out_size);
    } while (ret == 0 || (ret == -1 && errno == EINTR));

    if (ret == -1) {
        error_report("failed to read from TPM device %s: %d",
                     tpm_proxy->host_path, errno);
        return H_RESOURCE;
    }

    cpu_physical_memory_write(data_out, buf_out, ret);
    args[0] = ret;

    return H_SUCCESS;
}

static target_ulong h_tpm_comm(PowerPCCPU *cpu,
                               SpaprMachineState *spapr,
                               target_ulong opcode,
                               target_ulong *args)
{
    target_ulong op = args[0];
    SpaprTpmProxy *tpm_proxy = spapr->tpm_proxy;

    if (!tpm_proxy) {
        error_report("TPM proxy not available");
        return H_FUNCTION;
    }

    trace_spapr_h_tpm_comm(tpm_proxy->host_path, op);

    switch (op) {
    case TPM_COMM_OP_EXECUTE:
        return tpm_execute(tpm_proxy, args);
    case TPM_COMM_OP_CLOSE_SESSION:
        spapr_tpm_proxy_reset(tpm_proxy);
        return H_SUCCESS;
    default:
        return H_PARAMETER;
    }
}

static void spapr_tpm_proxy_realize(DeviceState *d, Error **errp)
{
    SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(d);

    if (tpm_proxy->host_path == NULL) {
        error_setg(errp, "must specify 'host-path' option for device");
        return;
    }

    tpm_proxy->host_fd = -1;
    qemu_register_reset(spapr_tpm_proxy_reset, tpm_proxy);
}

static void spapr_tpm_proxy_unrealize(DeviceState *d)
{
    SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(d);

    qemu_unregister_reset(spapr_tpm_proxy_reset, tpm_proxy);
}

static Property spapr_tpm_proxy_properties[] = {
    DEFINE_PROP_STRING("host-path", SpaprTpmProxy, host_path),
    DEFINE_PROP_END_OF_LIST(),
};

static void spapr_tpm_proxy_class_init(ObjectClass *k, void *data)
{
    DeviceClass *dk = DEVICE_CLASS(k);

    dk->realize = spapr_tpm_proxy_realize;
    dk->unrealize = spapr_tpm_proxy_unrealize;
    dk->user_creatable = true;
    device_class_set_props(dk, spapr_tpm_proxy_properties);
}

static const TypeInfo spapr_tpm_proxy_info = {
    .name          = TYPE_SPAPR_TPM_PROXY,
    .parent        = TYPE_DEVICE,
    .instance_size = sizeof(SpaprTpmProxy),
    .class_init    = spapr_tpm_proxy_class_init,
};

static void spapr_tpm_proxy_register_types(void)
{
    type_register_static(&spapr_tpm_proxy_info);
    spapr_register_hypercall(SVM_H_TPM_COMM, h_tpm_comm);
}

type_init(spapr_tpm_proxy_register_types)
