// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.

#define _GNU_SOURCE /* fallocate */
#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "mbox.h"
#include "flash.h"
#include "lpc.h"
#include "transport_mbox.h"
#include "windows.h"

#include "test/mbox.h"

#define STEP 16

void dump_buf(const void *buf, size_t len)
{
	const uint8_t *buf8 = buf;
	int i;

	for (i = 0; i < len; i += STEP) {
		int delta;
		int max;
		int j;

		delta = len - i;
		max = delta > STEP ? STEP : delta;

		printf("0x%08x:\t", i);
		for (j = 0; j < max; j++)
			printf("0x%02x, ", buf8[i + j]);

		printf("\n");
	}
	printf("\n");
}

/*
 * Because we are using a file and not a pipe for the mbox file descriptor we
 * need to handle a difference in behaviour. For a given command and response
 * sequence the first 16 bytes of the file are occupied by the mbox command.
 * The response occupies the following 14 bytes for a total of 30 bytes.
 *
 * We also have to ensure we lseek() to reset the file descriptor offset back
 * to the start of the file before dispatching the mbox command.
 */

/* Macros for handling the pipe/file discrepancy */
#define RESPONSE_OFFSET	16
#define RESPONSE_SIZE	14

int mbox_cmp(struct mbox_context *context, const uint8_t *expected, size_t len)
{
	struct stat details;
	uint8_t *map;
	int rc;
	int fd;

	fd = context->fds[MBOX_FD].fd;
	fstat(fd, &details);

	map = mmap(NULL, details.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	assert(map != MAP_FAILED);
	assert(details.st_size >= (RESPONSE_OFFSET + len));

	rc = memcmp(expected, &map[RESPONSE_OFFSET], len);

	if (rc != 0) {
		printf("\nMBOX state (%ld):\n", details.st_size);
		dump_buf(map, details.st_size);
		printf("Expected response (%lu):\n", len);
		dump_buf(expected, len);
	}

	munmap(map, details.st_size);

	return rc;
}

void mbox_rspcpy(struct mbox_context *context, struct mbox_msg *msg)
{
	struct stat details;
	uint8_t *map;
	int fd;

	fd = context->fds[MBOX_FD].fd;
	fstat(fd, &details);

	map = mmap(NULL, details.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	assert(map != MAP_FAILED);
	assert(details.st_size >= (RESPONSE_OFFSET + RESPONSE_SIZE));

	memcpy(msg, &map[RESPONSE_OFFSET], RESPONSE_SIZE);

	munmap(map, details.st_size);
}

int mbox_command_write(struct mbox_context *context, const uint8_t *command,
		size_t len)
{
	size_t remaining;
	int rc;
	int fd;

	fd = context->fds[MBOX_FD].fd;
	rc = lseek(fd, 0, SEEK_SET);
	if (rc != 0)
		return -1;

	remaining = len;
	while (remaining > 0) {
		rc = write(fd, command, remaining);
		if (rc < 0)
			goto out;
		remaining -= rc;
	}

	rc = lseek(fd, 0, SEEK_SET);
	if (rc != 0)
		return -1;

out:
	return rc;
}

int mbox_command_dispatch(struct mbox_context *context, const uint8_t *command,
		size_t len)
{
	uint8_t status;
	int rc;

	rc = mbox_command_write(context, command, len);
	if (rc < 0)
		return rc;

	rc = dispatch_mbox(context);
	if (rc < 0)
		return -rc;

	/*
	 * The aspeed-lpc-ctrl driver implements mailbox register access
	 * through the usual read()/write() chardev interface.
	 *
	 * The typical access sequence is:
	 *
	 * 1. Read all the registers out
	 * 2. Perform the action specified
	 * 3. Write a response to the registers.
	 *
	 * For the tests the "device" file descriptor is backed by a temporary
	 * file. The above sequence leads to a file-size of 30 bytes: 16 bytes
	 * for the issued command, followed by a 14-byte response.
	 *
	 * However, the typical access pattern isn't the only access pattern.
	 * Individual byte registers can be accessed by lseek()'ing on the
	 * device's file descriptor and issuing read() or write() as desired.
	 * The daemon uses this property to manage the BMC status byte, and the
	 * implementation cleans up after status byte operations by lseek()'ing
	 * back to offset zero.
	 *
	 * Thus for the BMC_EVENT_ACK command the file only reaches a size of
	 * 16 bytes; the daemon's response overwrites the first 14 bytes of the
	 * command injected by the tests.
	 *
	 * The consequence of this is that the response status byte can either
	 * appear at offset 13, or offset 29, depending on the command.
	 *
	 * However, regardless of what command is issued the response data is
	 * written to the device and the file descriptor is left in the
	 * post-write() state. This means the status byte can always be
	 * accessed relative to the current position by an lseek() of type
	 * SEEK_CUR for offset -1.
	 *
	 */
	rc = lseek(context->fds[MBOX_FD].fd, -1, SEEK_CUR);
	if (rc < 0)
		return rc;

	rc = read(context->fds[MBOX_FD].fd, &status, sizeof(status));
	if (rc < 0)
		return rc;

	return status;
}

struct mbox_test_context {
	struct tmpf mbox;
	struct tmpf flash;
	struct tmpf lpc;
	struct mbox_context context;
} test;

void cleanup(void)
{
	tmpf_destroy(&test.mbox);
	tmpf_destroy(&test.flash);
	tmpf_destroy(&test.lpc);
}

int __init_mbox_dev(struct mbox_context *context, const char *path);
int __lpc_dev_init(struct mbox_context *context, const char *path);

struct mbox_context *mbox_create_test_context(int n_windows, size_t len)
{
	int rc;

	mbox_vlog = &mbox_log_console;
	verbosity = 2;

	atexit(cleanup);

	rc = tmpf_init(&test.mbox, "mbox-store.XXXXXX");
	assert(rc == 0);

	rc = tmpf_init(&test.flash, "flash-store.XXXXXX");
	assert(rc == 0);

	rc = tmpf_init(&test.lpc, "lpc-store.XXXXXX");
	assert(rc == 0);

	test.context.windows.num = n_windows;
	test.context.windows.default_size = len;

	rc = protocol_init(&test.context);
	assert(rc == 0);

	/*
	 * We need to call __init_mbox_dev() to initialise the handler table.
	 * However, afterwards we need to discard the fd of the clearly useless
	 * /dev/null and replace it with our own fd for mbox device emulation
	 * by the test framework.
	 */
	__init_mbox_dev(&test.context, "/dev/null");
	rc = close(test.context.fds[MBOX_FD].fd);
	assert(rc == 0);
	test.context.fds[MBOX_FD].fd = test.mbox.fd;

	rc = flash_dev_init(&test.context);
	assert(rc == 0);

	rc = fallocate(test.flash.fd, 0, 0, test.context.mtd_info.size);
	assert(rc == 0);

	rc = __lpc_dev_init(&test.context, test.lpc.path);
	assert(rc == 0);

	rc = fallocate(test.lpc.fd, 0, 0, test.context.mem_size);
	assert(rc == 0);

	rc = windows_init(&test.context);
	assert(rc == 0);

	return rc ? NULL : &test.context;
}

/* From ccan's container_of module, CC0 license */
#define container_of(member_ptr, containing_type, member)		\
	 ((containing_type *)						\
	  ((char *)(member_ptr)						\
	   - container_off(containing_type, member))			\
	  + check_types_match(*(member_ptr), ((containing_type *)0)->member))

/* From ccan's container_of module, CC0 license */
#define container_off(containing_type, member)	\
		offsetof(containing_type, member)

/* From ccan's check_type module, CC0 license */
#define check_type(expr, type)			\
	((typeof(expr) *)0 != (type *)0)

/* From ccan's check_type module, CC0 license */
#define check_types_match(expr1, expr2)		\
	((typeof(expr1) *)0 != (typeof(expr2) *)0)

int mbox_set_mtd_data(struct mbox_context *context, const void *data,
		size_t len)
{
	struct mbox_test_context *arg;
	void *map;

	/* Sanity check */
	arg = container_of(context, struct mbox_test_context, context);
	if (&test != arg)
		return -1;

	if (len > test.context.mtd_info.size)
		return -2;

	map = mmap(NULL, test.context.mtd_info.size, PROT_WRITE, MAP_SHARED,
			test.flash.fd, 0);
	assert(map != MAP_FAILED);
	memcpy(map, data, len);
	munmap(map, test.context.mtd_info.size);

	return 0;
}

char *get_dev_mtd(void)
{
	return strdup(test.flash.path);
}
