/*
 * 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 "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)
