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

#include <trusty_std.h>
#include <interface/hwrng/hwrng.h>

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

#define LOCAL_TRACE       1
#define LOG_TAG           "hwrng_srv"

#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;
}
