/*
 * srm_env.c - Access to SRM environment
 *             variables through linux' procfs
 *
 * Copyright (C) 2001-2002 Jan-Benedict Glaw <jbglaw@lug-owl.de>
 *
 * This driver is at all a modified version of Erik Mouw's
 * Documentation/DocBook/procfs_example.c, so: thank
 * you, Erik! He can be reached via email at
 * <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea
 * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They
 * included a patch like this as well. Thanks for idea!
 *
 * This program is free software; you can redistribute
 * it and/or modify it under the terms of the GNU General
 * Public License version 2 as published by the Free Software
 * Foundation.
 *
 * 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, write to the
 * Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA  02111-1307  USA
 *
 */

/*
 * Changelog
 * ~~~~~~~~~
 *
 * Thu, 22 Aug 2002 15:10:43 +0200
 * 	- Update Config.help entry. I got a number of emails asking
 * 	  me to tell their senders if they could make use of this
 * 	  piece of code... So: "SRM is something like BIOS for your
 * 	  Alpha"
 * 	- Update code formatting a bit to better conform CodingStyle
 * 	  rules.
 * 	- So this is v0.0.5, with no changes (except formatting)
 * 	
 * Wed, 22 May 2002 00:11:21 +0200
 * 	- Fix typo on comment (SRC -> SRM)
 * 	- Call this "Version 0.0.4"
 *
 * Tue,  9 Apr 2002 18:44:40 +0200
 * 	- Implement access by variable name and additionally
 * 	  by number. This is done by creating two subdirectories
 * 	  where one holds all names (like the old directory
 * 	  did) and the other holding 256 files named like "0",
 * 	  "1" and so on.
 * 	- Call this "Version 0.0.3"
 *
 */

#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/console.h>
#include <asm/uaccess.h>
#include <asm/machvec.h>

#define BASE_DIR	"srm_environment"	/* Subdir in /proc/		*/
#define NAMED_DIR	"named_variables"	/* Subdir for known variables	*/
#define NUMBERED_DIR	"numbered_variables"	/* Subdir for all variables	*/
#define VERSION		"0.0.5"			/* Module version		*/
#define NAME		"srm_env"		/* Module name			*/

MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
MODULE_DESCRIPTION("Accessing Alpha SRM environment through procfs interface");
MODULE_LICENSE("GPL");

typedef struct _srm_env {
	char			*name;
	unsigned long		id;
	struct proc_dir_entry	*proc_entry;
} srm_env_t;

static struct proc_dir_entry	*base_dir;
static struct proc_dir_entry	*named_dir;
static struct proc_dir_entry	*numbered_dir;
static char			number[256][4];

static srm_env_t	srm_named_entries[] = {
	{ "auto_action",	ENV_AUTO_ACTION		},
	{ "boot_dev",		ENV_BOOT_DEV		},
	{ "bootdef_dev",	ENV_BOOTDEF_DEV		},
	{ "booted_dev",		ENV_BOOTED_DEV		},
	{ "boot_file",		ENV_BOOT_FILE		},
	{ "booted_file",	ENV_BOOTED_FILE		},
	{ "boot_osflags",	ENV_BOOT_OSFLAGS	},
	{ "booted_osflags",	ENV_BOOTED_OSFLAGS	},
	{ "boot_reset",		ENV_BOOT_RESET		},
	{ "dump_dev",		ENV_DUMP_DEV		},
	{ "enable_audit",	ENV_ENABLE_AUDIT	},
	{ "license",		ENV_LICENSE		},
	{ "char_set",		ENV_CHAR_SET		},
	{ "language",		ENV_LANGUAGE		},
	{ "tty_dev",		ENV_TTY_DEV		},
	{ NULL,			0			},
};
static srm_env_t	srm_numbered_entries[256];



static int
srm_env_read(char *page, char **start, off_t off, int count, int *eof,
		void *data)
{
	int		nbytes;
	unsigned long	ret;
	srm_env_t	*entry;

	if(off != 0)
		return -EFAULT;

	entry	= (srm_env_t *) data;
	ret	= callback_getenv(entry->id, page, count);

	if((ret >> 61) == 0)
		nbytes = (int) ret;
	else
		nbytes = -EFAULT;

	return nbytes;
}


static int
srm_env_write(struct file *file, const char __user *buffer, unsigned long count,
		void *data)
{
	int res;
	srm_env_t	*entry;
	char		*buf = (char *) __get_free_page(GFP_USER);
	unsigned long	ret1, ret2;

	entry = (srm_env_t *) data;

	if (!buf)
		return -ENOMEM;

	res = -EINVAL;
	if (count >= PAGE_SIZE)
		goto out;

	res = -EFAULT;
	if (copy_from_user(buf, buffer, count))
		goto out;
	buf[count] = '\0';

	ret1 = callback_setenv(entry->id, buf, count);
	if ((ret1 >> 61) == 0) {
		do 
			ret2 = callback_save_env();
		while((ret2 >> 61) == 1);
		res = (int) ret1;
	}

 out:
	free_page((unsigned long)buf);
	return res;
}

static void
srm_env_cleanup(void)
{
	srm_env_t	*entry;
	unsigned long	var_num;

	if(base_dir) {
		/*
		 * Remove named entries
		 */
		if(named_dir) {
			entry = srm_named_entries;
			while(entry->name != NULL && entry->id != 0) {
				if(entry->proc_entry) {
					remove_proc_entry(entry->name,
							named_dir);
					entry->proc_entry = NULL;
				}
				entry++;
			}
			remove_proc_entry(NAMED_DIR, base_dir);
		}

		/*
		 * Remove numbered entries
		 */
		if(numbered_dir) {
			for(var_num = 0; var_num <= 255; var_num++) {
				entry =	&srm_numbered_entries[var_num];

				if(entry->proc_entry) {
					remove_proc_entry(entry->name,
							numbered_dir);
					entry->proc_entry	= NULL;
					entry->name		= NULL;
				}
			}
			remove_proc_entry(NUMBERED_DIR, base_dir);
		}

		remove_proc_entry(BASE_DIR, NULL);
	}

	return;
}


static int __init
srm_env_init(void)
{
	srm_env_t	*entry;
	unsigned long	var_num;

	/*
	 * Check system
	 */
	if(!alpha_using_srm) {
		printk(KERN_INFO "%s: This Alpha system doesn't "
				"know about SRM (or you've booted "
				"SRM->MILO->Linux, which gets "
				"misdetected)...\n", __FUNCTION__);
		return -ENODEV;
	}

	/*
	 * Init numbers
	 */
	for(var_num = 0; var_num <= 255; var_num++)
		sprintf(number[var_num], "%ld", var_num);

	/*
	 * Create base directory
	 */
	base_dir = proc_mkdir(BASE_DIR, NULL);
	if(base_dir == NULL) {
		printk(KERN_ERR "Couldn't create base dir /proc/%s\n",
				BASE_DIR);
		goto cleanup;
	}
	base_dir->owner = THIS_MODULE;

	/*
	 * Create per-name subdirectory
	 */
	named_dir = proc_mkdir(NAMED_DIR, base_dir);
	if(named_dir == NULL) {
		printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
				BASE_DIR, NAMED_DIR);
		goto cleanup;
	}
	named_dir->owner = THIS_MODULE;

	/*
	 * Create per-number subdirectory
	 */
	numbered_dir = proc_mkdir(NUMBERED_DIR, base_dir);
	if(numbered_dir == NULL) {
		printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
				BASE_DIR, NUMBERED_DIR);
		goto cleanup;

	}
	numbered_dir->owner = THIS_MODULE;

	/*
	 * Create all named nodes
	 */
	entry = srm_named_entries;
	while(entry->name != NULL && entry->id != 0) {
		entry->proc_entry = create_proc_entry(entry->name,
				0644, named_dir);
		if(entry->proc_entry == NULL)
			goto cleanup;

		entry->proc_entry->data		= (void *) entry;
		entry->proc_entry->owner	= THIS_MODULE;
		entry->proc_entry->read_proc	= srm_env_read;
		entry->proc_entry->write_proc	= srm_env_write;

		entry++;
	}

	/*
	 * Create all numbered nodes
	 */
	for(var_num = 0; var_num <= 255; var_num++) {
		entry = &srm_numbered_entries[var_num];
		entry->name = number[var_num];

		entry->proc_entry = create_proc_entry(entry->name,
				0644, numbered_dir);
		if(entry->proc_entry == NULL)
			goto cleanup;

		entry->id			= var_num;
		entry->proc_entry->data		= (void *) entry;
		entry->proc_entry->owner	= THIS_MODULE;
		entry->proc_entry->read_proc	= srm_env_read;
		entry->proc_entry->write_proc	= srm_env_write;
	}

	printk(KERN_INFO "%s: version %s loaded successfully\n", NAME,
			VERSION);

	return 0;

cleanup:
	srm_env_cleanup();

	return -ENOMEM;
}


static void __exit
srm_env_exit(void)
{
	srm_env_cleanup();
	printk(KERN_INFO "%s: unloaded successfully\n", NAME);

	return;
}


module_init(srm_env_init);
module_exit(srm_env_exit);

