// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
 *
 * (C) COPYRIGHT 2017, 2020-2021 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU license.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 */

/* Kernel UTF test helpers */
#include <kutf/kutf_helpers.h>
#include <linux/err.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/preempt.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/export.h>

static DEFINE_SPINLOCK(kutf_input_lock);

bool kutf_helper_pending_input(struct kutf_context *context)
{
	bool input_pending;

	spin_lock(&kutf_input_lock);

	input_pending = !list_empty(&context->userdata.input_head);

	spin_unlock(&kutf_input_lock);

	return input_pending;
}
EXPORT_SYMBOL(kutf_helper_pending_input);

char *kutf_helper_input_dequeue(struct kutf_context *context, size_t *str_size)
{
	struct kutf_userdata_line *line;

	spin_lock(&kutf_input_lock);

	while (list_empty(&context->userdata.input_head)) {
		int err;

		kutf_set_waiting_for_input(context->result_set);

		spin_unlock(&kutf_input_lock);

		err = wait_event_interruptible(context->userdata.input_waitq,
				kutf_helper_pending_input(context));

		if (err)
			return ERR_PTR(-EINTR);

		spin_lock(&kutf_input_lock);
	}

	line = list_first_entry(&context->userdata.input_head,
			struct kutf_userdata_line, node);
	if (line->str) {
		/*
		 * Unless it is the end-of-input marker,
		 * remove it from the list
		 */
		list_del(&line->node);
	}

	spin_unlock(&kutf_input_lock);

	if (str_size)
		*str_size = line->size;
	return line->str;
}

int kutf_helper_input_enqueue(struct kutf_context *context,
		const char __user *str, size_t size)
{
	struct kutf_userdata_line *line;

	line = kutf_mempool_alloc(&context->fixture_pool,
			sizeof(*line) + size + 1);
	if (!line)
		return -ENOMEM;
	if (str) {
		unsigned long bytes_not_copied;

		line->size = size;
		line->str = (void *)(line + 1);
		bytes_not_copied = copy_from_user(line->str, str, size);
		if (bytes_not_copied != 0)
			return -EFAULT;
		/* Zero terminate the string */
		line->str[size] = '\0';
	} else {
		/* This is used to mark the end of input */
		WARN_ON(size);
		line->size = 0;
		line->str = NULL;
	}

	spin_lock(&kutf_input_lock);

	list_add_tail(&line->node, &context->userdata.input_head);

	kutf_clear_waiting_for_input(context->result_set);

	spin_unlock(&kutf_input_lock);

	wake_up(&context->userdata.input_waitq);

	return 0;
}

void kutf_helper_input_enqueue_end_of_data(struct kutf_context *context)
{
	kutf_helper_input_enqueue(context, NULL, 0);
}
