/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <trusty/hwbcc.h>
#include <trusty/trusty_ipc.h>
#include <trusty/util.h>
#include <uapi/uapi/err.h>

static struct trusty_ipc_chan hwbcc_chan;
static bool initialized;

#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif

int hwbcc_tipc_init(struct trusty_ipc_dev* dev) {
    trusty_assert(dev);
    trusty_ipc_chan_init(&hwbcc_chan, dev);

    /* connect to hwbcc service and wait for connect to complete */
    trusty_debug("In hwbcc_tipc_init: connecting to hwbcc service.\n");
    int rc = trusty_ipc_connect(&hwbcc_chan, HWBCC_PORT, true);
    if (rc < 0) {
        trusty_error("In hwbcc_tipc_init:: failed (%d) to connect to '%s'.\n",
                     rc, HWBCC_PORT);
        return rc;
    }
    initialized = true;
    return TRUSTY_ERR_NONE;
}

void hwbcc_tipc_shutdown() {
    if (!initialized) {
        return;
    }
    trusty_ipc_close(&hwbcc_chan);
    initialized = false;
}

static int send_header_only_request(struct hwbcc_req_hdr* hdr,
                                    size_t hdr_size) {
    int num_iovec = 1;
    struct trusty_ipc_iovec req_iov = {.base = hdr, .len = hdr_size};
    return trusty_ipc_send(&hwbcc_chan, &req_iov, num_iovec, true);
}

static int read_response_with_data(struct hwbcc_req_hdr* hdr,
                                   uint8_t* buf,
                                   size_t buf_size,
                                   size_t* out_size) {
    struct hwbcc_resp_hdr resp_hdr = {};

    trusty_assert(buf);
    trusty_assert(out_size);

    int num_iovec = 2;
    struct trusty_ipc_iovec resp_iovecs[2] = {
            {.base = &resp_hdr, .len = sizeof(resp_hdr)},
            {.base = buf, .len = buf_size},
    };

    int rc = trusty_ipc_recv(&hwbcc_chan, resp_iovecs, num_iovec, true);
    if (rc < 0) {
        trusty_error("Failure on receiving response: %d\n", rc);
        return rc;
    }

    if ((size_t)rc < sizeof(resp_hdr)) {
        trusty_error("Invalid response size (%d).\n", rc);
        return TRUSTY_ERR_GENERIC;
    }

    if (resp_hdr.cmd != (hdr->cmd | HWBCC_CMD_RESP_BIT)) {
        trusty_error("Unknown response cmd: %x\n", resp_hdr.cmd);
        return TRUSTY_ERR_GENERIC;
    }

    if (resp_hdr.status != NO_ERROR) {
        trusty_error("Status (%d) is not SUCCESS.\n", resp_hdr.status);
        return TRUSTY_ERR_GENERIC;
    }

    if (resp_hdr.payload_size != (size_t)rc - sizeof(resp_hdr)) {
        trusty_error("Invalid payload size: %d.", resp_hdr.payload_size);
        return TRUSTY_ERR_GENERIC;
    }

    if (resp_hdr.payload_size > HWBCC_MAX_RESP_PAYLOAD_SIZE ||
        resp_hdr.payload_size > buf_size) {
        trusty_error("Response payload size is too large: %d\n",
                     resp_hdr.payload_size);
        return TRUSTY_ERR_GENERIC;
    }

    *out_size = resp_hdr.payload_size;
    return rc;
}

static int read_header_only_response(struct hwbcc_req_hdr* hdr) {
    struct hwbcc_resp_hdr resp_hdr = {};

    struct trusty_ipc_iovec resp_iovec = {.base = &resp_hdr,
                                          .len = sizeof(resp_hdr)};

    int rc = trusty_ipc_recv(&hwbcc_chan, &resp_iovec, 1, true);
    if (rc < 0) {
        trusty_error("Failure on receiving response: %d\n", rc);
        return rc;
    }

    if ((size_t)rc < sizeof(resp_hdr)) {
        trusty_error("Invalid response size (%d).\n", rc);
        return TRUSTY_ERR_GENERIC;
    }

    if (resp_hdr.cmd != (hdr->cmd | HWBCC_CMD_RESP_BIT)) {
        trusty_error("Unknown response cmd: %x\n", resp_hdr.cmd);
        return TRUSTY_ERR_GENERIC;
    }

    if (resp_hdr.status != NO_ERROR) {
        trusty_error("Status (%d) is not SUCCESS.\n", resp_hdr.status);
        return TRUSTY_ERR_GENERIC;
    }

    return rc;
}

int hwbcc_get_dice_artifacts(uint64_t context,
                             uint8_t* dice_artifacts,
                             size_t dice_artifacts_buf_size,
                             size_t* dice_artifacts_size) {
    assert(dice_artifacts);
    assert(dice_artifacts_size);

    struct hwbcc_req_hdr hdr;
    hdr.cmd = HWBCC_CMD_GET_DICE_ARTIFACTS;
    hdr.context = context;

    int rc = send_header_only_request(&hdr, sizeof(hdr));

    if (rc < 0) {
        trusty_error(
                "In hwbcc_get_dice_artifacts: failed (%d) to send request to HWBCC.",
                rc);
        return rc;
    }

    rc = read_response_with_data(&hdr, dice_artifacts, dice_artifacts_buf_size,
                                 dice_artifacts_size);

    if (rc < 0) {
        trusty_error(
                "In hwbcc_get_dice_artifacts: failed (%d) to read the response.",
                rc);
        return rc;
    }

    return TRUSTY_ERR_NONE;
}

int hwbcc_ns_deprivilege(void) {
    struct hwbcc_req_hdr hdr = {.cmd = HWBCC_CMD_NS_DEPRIVILEGE};
    int rc = send_header_only_request(&hdr, sizeof(hdr));

    if (rc < 0) {
        trusty_error(
                "In hwbcc_deprivilege: failed (%d) to send request to HWBCC.",
                rc);
        return rc;
    }

    rc = read_header_only_response(&hdr);

    if (rc < 0) {
        trusty_error("In hwbcc_deprivilege: failed (%d) to read the response.",
                     rc);
        return rc;
    }

    return TRUSTY_ERR_NONE;
}
