/*
 * linux/fs/binfmt_som.c
 *
 * These are the functions used to load SOM format executables as used
 * by HP-UX.  
 *
 * Copyright 1999 Matthew Wilcox <willy@bofh.ai>
 * based on binfmt_elf which is
 * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
 */

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/binfmts.h>
#include <linux/som.h>
#include <linux/string.h>
#include <linux/file.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/shm.h>
#include <linux/personality.h>
#include <linux/init.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>

#include <linux/config.h>

#include <linux/elf.h>

static int load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs);
static int load_som_library(struct file *);

/*
 * If we don't support core dumping, then supply a NULL so we
 * don't even try.
 */
#if 0
static int som_core_dump(long signr, struct pt_regs * regs);
#else
#define som_core_dump	NULL
#endif

#define SOM_PAGESTART(_v) ((_v) & ~(unsigned long)(SOM_PAGESIZE-1))
#define SOM_PAGEOFFSET(_v) ((_v) & (SOM_PAGESIZE-1))
#define SOM_PAGEALIGN(_v) (((_v) + SOM_PAGESIZE - 1) & ~(SOM_PAGESIZE - 1))

static struct linux_binfmt som_format = {
	.module		= THIS_MODULE,
	.load_binary	= load_som_binary,
	.load_shlib	= load_som_library,
	.core_dump	= som_core_dump,
	.min_coredump	= SOM_PAGESIZE
};

/*
 * create_som_tables() parses the env- and arg-strings in new user
 * memory and creates the pointer tables from them, and puts their
 * addresses on the "stack", returning the new stack pointer value.
 */
static void create_som_tables(struct linux_binprm *bprm)
{
	char **argv, **envp;
	int argc = bprm->argc;
	int envc = bprm->envc;
	unsigned long p;
	unsigned long *sp;

	/* Word-align the stack pointer */
	sp = (unsigned long *)((bprm->p + 3) & ~3);

	envp = (char **) sp;
	sp += envc + 1;
	argv = (char **) sp;
	sp += argc + 1;

	__put_user((unsigned long) envp,++sp);
	__put_user((unsigned long) argv,++sp);

	__put_user(argc, ++sp);

	bprm->p = (unsigned long) sp;

	p = current->mm->arg_start;
	while (argc-- > 0) {
		__put_user((char *)p,argv++);
		p += strlen_user((char *)p);
	}
	__put_user(NULL, argv);
	current->mm->arg_end = current->mm->env_start = p;
	while (envc-- > 0) {
		__put_user((char *)p,envp++);
		p += strlen_user((char *)p);
	}
	__put_user(NULL, envp);
	current->mm->env_end = p;
}

static int check_som_header(struct som_hdr *som_ex)
{
	int *buf = (int *)som_ex;
	int i, ck;

	if (som_ex->system_id != SOM_SID_PARISC_1_0 &&
	    som_ex->system_id != SOM_SID_PARISC_1_1 &&
	    som_ex->system_id != SOM_SID_PARISC_2_0)
		return -ENOEXEC;

	if (som_ex->a_magic != SOM_EXEC_NONSHARE &&
	    som_ex->a_magic != SOM_EXEC_SHARE &&
	    som_ex->a_magic != SOM_EXEC_DEMAND)
		return -ENOEXEC;

	if (som_ex->version_id != SOM_ID_OLD &&
	    som_ex->version_id != SOM_ID_NEW)
		return -ENOEXEC;

	ck = 0;
	for (i=0; i<32; i++)
		ck ^= buf[i];
	if (ck != 0)
		return -ENOEXEC;

	return 0;
}

static int map_som_binary(struct file *file,
		const struct som_exec_auxhdr *hpuxhdr)
{
	unsigned long code_start, code_size, data_start, data_size;
	unsigned long bss_start, som_brk;
	int retval;
	int prot = PROT_READ | PROT_EXEC;
	int flags = MAP_FIXED|MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;

	mm_segment_t old_fs = get_fs();
	set_fs(get_ds());

	code_start = SOM_PAGESTART(hpuxhdr->exec_tmem);
	code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
	current->mm->start_code = code_start;
	current->mm->end_code = code_start + code_size;
	down_write(&current->mm->mmap_sem);
	retval = do_mmap(file, code_start, code_size, prot,
			flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
	up_write(&current->mm->mmap_sem);
	if (retval < 0 && retval > -1024)
		goto out;

	data_start = SOM_PAGESTART(hpuxhdr->exec_dmem);
	data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
	current->mm->start_data = data_start;
	current->mm->end_data = bss_start = data_start + data_size;
	down_write(&current->mm->mmap_sem);
	retval = do_mmap(file, data_start, data_size,
			prot | PROT_WRITE, flags,
			SOM_PAGESTART(hpuxhdr->exec_dfile));
	up_write(&current->mm->mmap_sem);
	if (retval < 0 && retval > -1024)
		goto out;

	som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
	current->mm->start_brk = current->mm->brk = som_brk;
	down_write(&current->mm->mmap_sem);
	retval = do_mmap(NULL, bss_start, som_brk - bss_start,
			prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
	up_write(&current->mm->mmap_sem);
	if (retval > 0 || retval < -1024)
		retval = 0;
out:
	set_fs(old_fs);
	return retval;
}


/*
 * These are the functions used to load SOM executables and shared
 * libraries.  There is no binary dependent code anywhere else.
 */

static int
load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	int som_exec_fileno;
	int retval;
	unsigned int size;
	unsigned long som_entry;
	struct som_hdr *som_ex;
	struct som_exec_auxhdr *hpuxhdr;

	/* Get the exec-header */
	som_ex = (struct som_hdr *) bprm->buf;

	retval = check_som_header(som_ex);
	if (retval != 0)
		goto out;

	/* Now read in the auxiliary header information */

	retval = -ENOMEM;
	size = som_ex->aux_header_size;
	if (size > SOM_PAGESIZE)
		goto out;
	hpuxhdr = (struct som_exec_auxhdr *) kmalloc(size, GFP_KERNEL);
	if (!hpuxhdr)
		goto out;

	retval = kernel_read(bprm->file, som_ex->aux_header_location,
			(char *) hpuxhdr, size);
	if (retval < 0)
		goto out_free;
#error "Fix security hole before enabling me"
	retval = get_unused_fd();
	if (retval < 0)
		goto out_free;
	get_file(bprm->file);
	fd_install(som_exec_fileno = retval, bprm->file);

	/* Flush all traces of the currently running executable */
	retval = flush_old_exec(bprm);
	if (retval)
		goto out_free;

	/* OK, This is the point of no return */
	current->flags &= ~PF_FORKNOEXEC;
	current->personality = PER_HPUX;

	/* Set the task size for HP-UX processes such that
	 * the gateway page is outside the address space.
	 * This can be fixed later, but for now, this is much
	 * easier.
	 */

	current->thread.task_size = 0xc0000000;

	/* Set map base to allow enough room for hp-ux heap growth */

	current->thread.map_base = 0x80000000;

	retval = map_som_binary(bprm->file, hpuxhdr);
	if (retval < 0)
		goto out_free;

	som_entry = hpuxhdr->exec_entry;
	kfree(hpuxhdr);

	set_binfmt(&som_format);
	compute_creds(bprm);
	setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);

	create_som_tables(bprm);

	current->mm->start_stack = bprm->p;

#if 0
	printk("(start_brk) %08lx\n" , (unsigned long) current->mm->start_brk);
	printk("(end_code) %08lx\n" , (unsigned long) current->mm->end_code);
	printk("(start_code) %08lx\n" , (unsigned long) current->mm->start_code);
	printk("(end_data) %08lx\n" , (unsigned long) current->mm->end_data);
	printk("(start_stack) %08lx\n" , (unsigned long) current->mm->start_stack);
	printk("(brk) %08lx\n" , (unsigned long) current->mm->brk);
#endif

	map_hpux_gateway_page(current,current->mm);

	start_thread_som(regs, som_entry, bprm->p);
	if (current->ptrace & PT_PTRACED)
		send_sig(SIGTRAP, current, 0);
	return 0;

	/* error cleanup */
out_free:
	kfree(hpuxhdr);
out:
	return retval;
}

static int load_som_library(struct file *f)
{
/* No lib support in SOM yet.  gizza chance.. */
	return -ENOEXEC;
}
	/* Install the SOM loader.
	 * N.B. We *rely* on the table being the right size with the
	 * right number of free slots...
	 */

static int __init init_som_binfmt(void)
{
	return register_binfmt(&som_format);
}

static void __exit exit_som_binfmt(void)
{
	/* Remove the SOM loader. */
	unregister_binfmt(&som_format);
}

core_initcall(init_som_binfmt);
module_exit(exit_som_binfmt);
