// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/*
 * Very basic TPM driver
 *
 * Assumptions:
 * - The system firmware is responsible for initializing the TPM and has
 *   already done so.
 */

#include <assert.h>
#include <endian.h>
#include <ddk/debug.h>
#include <ddk/driver.h>
#include <ddk/io-buffer.h>
#include <ddk/protocol/i2c.h>
#include <explicit-memory/bytes.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <fbl/unique_ptr.h>
#include <fbl/unique_free_ptr.h>
#include <zircon/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <threads.h>

#include <utility>

#include "i2c-cr50.h"
#include "tpm.h"
#include "tpm-commands.h"

// This is arbitrary, we just want to limit the size of the response buffer
// that we need to allocate.
#define MAX_RAND_BYTES 256

namespace tpm {

// implement tpm protocol:

static zx_status_t GetRandom(Device* dev, void* buf, uint16_t count, size_t* actual) {
    static_assert(MAX_RAND_BYTES <= UINT32_MAX, "");
    if (count > MAX_RAND_BYTES) {
        count = MAX_RAND_BYTES;
    }

    struct tpm_getrandom_cmd cmd;
    uint32_t resp_len = tpm_init_getrandom(&cmd, count);
    fbl::unique_free_ptr<tpm_getrandom_resp> resp(
            reinterpret_cast<tpm_getrandom_resp*>(malloc(resp_len)));
    size_t actual_read;
    uint16_t bytes_returned;
    if (!resp) {
        return ZX_ERR_NO_MEMORY;
    }

    zx_status_t status = dev->ExecuteCmd(0, (uint8_t*)&cmd, sizeof(cmd),
                                         (uint8_t*)resp.get(), resp_len, &actual_read);
    if (status != ZX_OK) {
        return status;
    }
    if (actual_read < sizeof(*resp) ||
        actual_read != betoh32(resp->hdr.total_len)) {

        return ZX_ERR_BAD_STATE;
    }
    bytes_returned = betoh16(resp->bytes_returned);
    if (actual_read != sizeof(*resp) + bytes_returned ||
        resp->hdr.tag != htobe16(TPM_ST_NO_SESSIONS) ||
        bytes_returned > count ||
        resp->hdr.return_code != htobe32(TPM_SUCCESS)) {

        return ZX_ERR_BAD_STATE;
    }
    memcpy(buf, resp->bytes, bytes_returned);
    mandatory_memset(resp->bytes, 0, bytes_returned);
    *actual = bytes_returned;
    return ZX_OK;
}

zx_status_t Device::ShutdownLocked(uint16_t type) {
    struct tpm_shutdown_cmd cmd;
    uint32_t resp_len = tpm_init_shutdown(&cmd, type);
    struct tpm_shutdown_resp resp;
    size_t actual;

    zx_status_t status = ExecuteCmdLocked(0, (uint8_t*)&cmd, sizeof(cmd),
                                          (uint8_t*)&resp, resp_len, &actual);
    if (status != ZX_OK) {
        return status;
    }
    if (actual < sizeof(resp) ||
        actual != betoh32(resp.hdr.total_len) ||
        resp.hdr.tag != htobe16(TPM_ST_NO_SESSIONS) ||
        resp.hdr.return_code != htobe32(TPM_SUCCESS)) {

        return ZX_ERR_BAD_STATE;
    }
    return ZX_OK;
}

zx_status_t Device::ExecuteCmd(Locality loc, const uint8_t* cmd, size_t len,
                               uint8_t* resp, size_t max_len, size_t* actual) {
    fbl::AutoLock guard(&lock_);
    return ExecuteCmdLocked(loc, cmd, len, resp, max_len, actual);
}

zx_status_t Device::ExecuteCmdLocked(Locality loc, const uint8_t* cmd, size_t len,
                                     uint8_t* resp, size_t max_len, size_t* actual) {
    zx_status_t status = SendCmdLocked(loc, cmd, len);
    if (status != ZX_OK) {
        return status;
    }
    return RecvRespLocked(loc, resp, max_len, actual);
}

void Device::DdkRelease() {
    delete this;
}

zx_status_t Device::DdkSuspend(uint32_t flags) {
    fbl::AutoLock guard(&lock_);

    if (flags == DEVICE_SUSPEND_FLAG_SUSPEND_RAM) {
        zx_status_t status = ShutdownLocked(TPM_SU_STATE);
        if (status != ZX_OK) {
            zxlogf(ERROR, "tpm: Failed to save state: %d\n", status);
            return status;
        }
    }

    zx_status_t status = ReleaseLocalityLocked(0);
    if (status != ZX_OK) {
        zxlogf(ERROR, "tpm: Failed to release locality: %d\n", status);
        return status;
    }
    return status;
}

zx_status_t Device::Bind() {
    zx_status_t status = DdkAdd("tpm", DEVICE_ADD_INVISIBLE);
    if (status != ZX_OK) {
        return status;
    }

    thrd_t thread;
    int ret = thrd_create_with_name(&thread, Init, this, "tpm:slow_bind");
    if (ret != thrd_success) {
        DdkRemove();
        return ZX_ERR_INTERNAL;
    }
    thrd_detach(thread);
    return ZX_OK;
}

zx_status_t Device::Init() {
    uint8_t buf[32] = { 0 };
    size_t bytes_read;

    auto cleanup = fbl::MakeAutoCall([&] {
        DdkRemove();
    });

    zx_status_t status = iface_->Validate();
    if (status != ZX_OK) {
        zxlogf(TRACE, "tpm: did not pass driver validation\n");
        return status;
    }

    {
        fbl::AutoLock guard(&lock_);

        // tpm_request_use will fail if we're not at least 30ms past _TPM_INIT.
        // The system firmware performs the init, so it's safe to assume that
        // is 30 ms past.  If we're on systems where we need to do init,
        // we need to wait up to 30ms for the TPM_ACCESS register to be valid.
        status = RequestLocalityLocked(0);
        if (status != ZX_OK) {
            zxlogf(ERROR, "tpm: Failed to request use: %d\n", status);
            return status;
        }

        status = WaitForLocalityLocked(0);
        if (status != ZX_OK) {
            zxlogf(ERROR, "tpm: Waiting for locality failed: %d\n", status);
            return status;
        }
    }

    DdkMakeVisible();

    // Make a best-effort attempt to give the kernel some more entropy
    // TODO(security): Perform a more recurring seeding
    status = tpm::GetRandom(this, buf, static_cast<uint16_t>(sizeof(buf)), &bytes_read);
    if (status == ZX_OK) {
        zx_cprng_add_entropy(buf, bytes_read);
        mandatory_memset(buf, 0, sizeof(buf));
    } else {
        zxlogf(ERROR, "tpm: Failed to add entropy to kernel CPRNG\n");
    }

    cleanup.cancel();
    return ZX_OK;
}

Device::Device(zx_device_t* parent, fbl::unique_ptr<HardwareInterface> iface)
    : DeviceType(parent), iface_(std::move(iface)) {
    ddk_proto_id_ = ZX_PROTOCOL_TPM;
}

Device::~Device() {
}

} // namespace tpm

zx_status_t tpm_bind(void* ctx, zx_device_t* parent) {
    zx::handle irq;
    i2c_protocol_t i2c;
    zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_I2C, &i2c);
    if (status != ZX_OK) {
        zxlogf(ERROR, "tpm: could not get I2C protocol: %d\n", status);
        return ZX_ERR_NOT_SUPPORTED;
    }

    status = i2c_get_interrupt(&i2c, 0, irq.reset_and_get_address());
    if (status == ZX_OK) {
        // irq contains garbage?
        zx_handle_t ignored __UNUSED = irq.release();
    }

    fbl::unique_ptr<tpm::I2cCr50Interface> i2c_iface;
    status = tpm::I2cCr50Interface::Create(parent, std::move(irq), &i2c_iface);
    if (status != ZX_OK) {
        return status;
    }

    fbl::AllocChecker ac;
    fbl::unique_ptr<tpm::Device> device(new (&ac) tpm::Device(parent, std::move(i2c_iface)));
    if (!ac.check()) {
        return status;
    }

    status = device->Bind();
    if (status == ZX_OK) {
        // DevMgr now owns this pointer, release it to avoid destroying the
        // object when device goes out of scope.
        __UNUSED auto ptr = device.release();
    }
    return status;
}
