/*
 * Copyright (C) 2016-2017 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 <lk/list.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trusty_ipc.h>
#include <uapi/err.h>

#include <interface/hwrng/hwrng.h>

#include "common.h"
#include "hwrng_srv_priv.h"

#define TLOG_LVL TLOG_LVL_DEFAULT
#define TLOG_TAG "hwrng_srv"
#include "tlog.h"

#define HWRNG_SRV_NAME HWRNG_PORT
#define MAX_HWRNG_MSG_SIZE 4096

struct hwrng_chan_ctx {
    tipc_event_handler_t evt_handler;
    struct list_node node;
    handle_t chan;
    size_t req_size;
    bool send_blocked;
};

static void hwrng_port_handler(const uevent_t* ev, void* priv);
static void hwrng_chan_handler(const uevent_t* ev, void* priv);

static handle_t hwrng_port = INVALID_IPC_HANDLE;

static tipc_event_handler_t hwrng_port_evt_handler = {
        .proc = hwrng_port_handler,
};

static uint8_t rng_data[MAX_HWRNG_MSG_SIZE];

static struct list_node hwrng_req_list = LIST_INITIAL_VALUE(hwrng_req_list);

/****************************************************************************/

/*
 *  Hexdump content of memory region
 */
static void _hexdump8(const void* ptr, size_t len) {
    addr_t address = (addr_t)ptr;
    size_t count;
    size_t i;

    for (count = 0; count < len; count += 16) {
        fprintf(stderr, "0x%08lx: ", address);
        for (i = 0; i < MIN(len - count, 16); i++) {
            fprintf(stderr, "0x%02hhx ", *(const uint8_t*)(address + i));
        }
        fprintf(stderr, "\n");
        address += 16;
    }
}

/*
 * Close specified HWRNG service channel
 */
static void hwrng_close_chan(struct hwrng_chan_ctx* ctx) {
    close(ctx->chan);

    if (list_in_list(&ctx->node))
        list_delete(&ctx->node);

    free(ctx);
}

/*
 * Handle HWRNG request queue
 */
static bool hwrng_handle_req_queue(void) {
    struct hwrng_chan_ctx* ctx;
    struct hwrng_chan_ctx* temp;

    /* service channels */
    bool need_more = false;

    /* for all pending requests */
    list_for_every_entry_safe(&hwrng_req_list, ctx, temp, struct hwrng_chan_ctx,
                              node) {
        if (ctx->send_blocked)
            continue; /* cant service it rignt now */

        size_t len = ctx->req_size;

        if (len > MAX_HWRNG_MSG_SIZE)
            len = MAX_HWRNG_MSG_SIZE;

        /* get rng data */
        hwrng_dev_get_rng_data(rng_data, len);

        /* send reply */
        int rc = tipc_send_single_buf(ctx->chan, rng_data, len);
        if (rc < 0) {
            if (rc == ERR_NOT_ENOUGH_BUFFER) {
                /* mark it as send_blocked */
                ctx->send_blocked = true;
            } else {
                /* just close HWRNG request channel */
                TLOGE("failed (%d) to send_reply\n", rc);
                hwrng_close_chan(ctx);
            }
            continue;
        }

        ctx->req_size -= len;

        if (ctx->req_size == 0) {
            /* remove it from pending list */
            list_delete(&ctx->node);
        } else {
            need_more = true;
        }
    }

    return need_more;
}

/*
 * Check if we can handle request queue
 */
static void hwrng_kick_req_queue(void) {
    hwrng_handle_req_queue();
}

/*
 *  Read and queue HWRNG request message
 */
static int hwrng_chan_handle_msg(struct hwrng_chan_ctx* ctx) {
    int rc;
    struct hwrng_req req;

    assert(ctx);

    /* read request */
    rc = tipc_recv_single_buf(ctx->chan, &req, sizeof(req));
    if (rc != sizeof(req)) {
        TLOGE("failed (%d) to receive msg for chan %d\n", rc, ctx->chan);
        return rc;
    }

    /* check if we already have request in progress */
    if (list_in_list(&ctx->node)) {
        /* extend it */
        ctx->req_size += req.len;
    } else {
        /* queue it */
        ctx->req_size = req.len;
        list_add_tail(&hwrng_req_list, &ctx->node);
    }

    return 0;
}

/*
 *  Channel handler where HWRNG requests are coming from
 */
static void hwrng_chan_handler(const uevent_t* ev, void* priv) {
    struct hwrng_chan_ctx* ctx = priv;

    assert(ctx);
    assert(ev->handle == ctx->chan);

    tipc_handle_chan_errors(ev);

    if (ev->event & IPC_HANDLE_POLL_HUP) {
        hwrng_close_chan(ctx);
    } else {
        if (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
            ctx->send_blocked = false;
        }

        if (ev->event & IPC_HANDLE_POLL_MSG) {
            int rc = hwrng_chan_handle_msg(ctx);
            if (rc) {
                hwrng_close_chan(ctx);
            }
        }
    }

    /* kick state machine */
    hwrng_kick_req_queue();
}

/*
 * Port were HWRNG requests are coming from
 */
static void hwrng_port_handler(const uevent_t* ev, void* priv) {
    uuid_t peer_uuid;

    tipc_handle_port_errors(ev);

    if (ev->event & IPC_HANDLE_POLL_READY) {
        handle_t chan;

        /* incoming connection: accept it */
        int rc = accept(ev->handle, &peer_uuid);
        if (rc < 0) {
            TLOGE("failed (%d) to accept on port %d\n", rc, ev->handle);
            return;
        }
        chan = (handle_t)rc;

        /* allocate state */
        struct hwrng_chan_ctx* ctx = calloc(1, sizeof(*ctx));
        if (!ctx) {
            TLOGE("failed to alloc state for chan %d\n", chan);
            close(chan);
            return;
        }

        /* init channel state */
        ctx->evt_handler.priv = ctx;
        ctx->evt_handler.proc = hwrng_chan_handler;
        ctx->chan = chan;

        /* attach channel handler */
        rc = set_cookie(chan, &ctx->evt_handler);
        if (rc) {
            TLOGE("failed (%d) to set_cookie on chan %d\n", rc, chan);
            free(ctx);
            close(chan);
            return;
        }
    }
}

/*
 *  Initialize HWRNG services
 */
int hwrng_start_service(void) {
    int rc;

    TLOGI("Start HWRNG service\n");

    /* create HWRNG port */
    rc = port_create(HWRNG_SRV_NAME, 1, MAX_HWRNG_MSG_SIZE,
                     IPC_PORT_ALLOW_TA_CONNECT);
    if (rc < 0) {
        TLOGE("Failed (%d) to create port '%s'\n", rc, HWRNG_SRV_NAME);
        return rc;
    } else {
        hwrng_port = (handle_t)rc;
        set_cookie(hwrng_port, &hwrng_port_evt_handler);
    }

    return NO_ERROR;
}
