/*
 * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
 * Licensed under the GPL
 */

#include "linux/compiler.h"
#include "linux/stddef.h"
#include "linux/kernel.h"
#include "linux/string.h"
#include "linux/fs.h"
#include "linux/highmem.h"
#include "asm/page.h"
#include "asm/pgtable.h"
#include "asm/uaccess.h"
#include "kern_util.h"
#include "user_util.h"

extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
			     pte_t *pte_out);

static unsigned long maybe_map(unsigned long virt, int is_write)
{
	pte_t pte;
	int err;

	void *phys = um_virt_to_phys(current, virt, &pte);
	int dummy_code;

	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
		err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
		if(err)
			return(-1UL);
		phys = um_virt_to_phys(current, virt, NULL);
	}
        if(IS_ERR(phys))
                phys = (void *) -1;

	return((unsigned long) phys);
}

static int do_op(unsigned long addr, int len, int is_write,
		 int (*op)(unsigned long addr, int len, void *arg), void *arg)
{
	struct page *page;
	int n;

	addr = maybe_map(addr, is_write);
	if(addr == -1UL)
		return(-1);

	page = phys_to_page(addr);
	addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
	n = (*op)(addr, len, arg);
	kunmap(page);

	return(n);
}

static void do_buffer_op(void *jmpbuf, void *arg_ptr)
{
	va_list args;
	unsigned long addr;
	int len, is_write, size, remain, n;
	int (*op)(unsigned long, int, void *);
	void *arg;
	int *res;

	va_copy(args, *(va_list *)arg_ptr);
	addr = va_arg(args, unsigned long);
	len = va_arg(args, int);
	is_write = va_arg(args, int);
	op = va_arg(args, void *);
	arg = va_arg(args, void *);
	res = va_arg(args, int *);
	va_end(args);
	size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
	remain = len;

	current->thread.fault_catcher = jmpbuf;
	n = do_op(addr, size, is_write, op, arg);
	if(n != 0){
		*res = (n < 0 ? remain : 0);
		goto out;
	}

	addr += size;
	remain -= size;
	if(remain == 0){
		*res = 0;
		goto out;
	}

	while(addr < ((addr + remain) & PAGE_MASK)){
		n = do_op(addr, PAGE_SIZE, is_write, op, arg);
		if(n != 0){
			*res = (n < 0 ? remain : 0);
			goto out;
		}

		addr += PAGE_SIZE;
		remain -= PAGE_SIZE;
	}
	if(remain == 0){
		*res = 0;
		goto out;
	}

	n = do_op(addr, remain, is_write, op, arg);
	if(n != 0)
		*res = (n < 0 ? remain : 0);
	else *res = 0;
 out:
	current->thread.fault_catcher = NULL;
}

static int buffer_op(unsigned long addr, int len, int is_write,
		     int (*op)(unsigned long addr, int len, void *arg),
		     void *arg)
{
	int faulted, res;

	faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
				 &res);
	if(!faulted)
		return(res);

	return(addr + len - (unsigned long) current->thread.fault_addr);
}

static int copy_chunk_from_user(unsigned long from, int len, void *arg)
{
	unsigned long *to_ptr = arg, to = *to_ptr;

	memcpy((void *) to, (void *) from, len);
	*to_ptr += len;
	return(0);
}

int copy_from_user_skas(void *to, const void __user *from, int n)
{
	if(segment_eq(get_fs(), KERNEL_DS)){
		memcpy(to, (__force void*)from, n);
		return(0);
	}

	return(access_ok_skas(VERIFY_READ, from, n) ?
	       buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
	       n);
}

static int copy_chunk_to_user(unsigned long to, int len, void *arg)
{
	unsigned long *from_ptr = arg, from = *from_ptr;

	memcpy((void *) to, (void *) from, len);
	*from_ptr += len;
	return(0);
}

int copy_to_user_skas(void __user *to, const void *from, int n)
{
	if(segment_eq(get_fs(), KERNEL_DS)){
		memcpy((__force void*)to, from, n);
		return(0);
	}

	return(access_ok_skas(VERIFY_WRITE, to, n) ?
	       buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
	       n);
}

static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
{
	char **to_ptr = arg, *to = *to_ptr;
	int n;

	strncpy(to, (void *) from, len);
	n = strnlen(to, len);
	*to_ptr += n;

	if(n < len)
	        return(1);
	return(0);
}

int strncpy_from_user_skas(char *dst, const char __user *src, int count)
{
	int n;
	char *ptr = dst;

	if(segment_eq(get_fs(), KERNEL_DS)){
		strncpy(dst, (__force void*)src, count);
		return(strnlen(dst, count));
	}

	if(!access_ok_skas(VERIFY_READ, src, 1))
		return(-EFAULT);

	n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
		      &ptr);
	if(n != 0)
		return(-EFAULT);
	return(strnlen(dst, count));
}

static int clear_chunk(unsigned long addr, int len, void *unused)
{
	memset((void *) addr, 0, len);
	return(0);
}

int __clear_user_skas(void __user *mem, int len)
{
	return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL));
}

int clear_user_skas(void __user *mem, int len)
{
	if(segment_eq(get_fs(), KERNEL_DS)){
		memset((__force void*)mem, 0, len);
		return(0);
	}

	return(access_ok_skas(VERIFY_WRITE, mem, len) ?
	       buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
}

static int strnlen_chunk(unsigned long str, int len, void *arg)
{
	int *len_ptr = arg, n;

	n = strnlen((void *) str, len);
	*len_ptr += n;

	if(n < len)
		return(1);
	return(0);
}

int strnlen_user_skas(const void __user *str, int len)
{
	int count = 0, n;

	if(segment_eq(get_fs(), KERNEL_DS))
		return(strnlen((__force char*)str, len) + 1);

	n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
	if(n == 0)
		return(count + 1);
	return(-EFAULT);
}

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * Emacs will notice this stuff at the end of the file and automatically
 * adjust the settings for this buffer only.  This must remain at the end
 * of the file.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-file-style: "linux"
 * End:
 */
