395cf9691d
There are numerous broken references to Documentation files (in other Documentation files, in comments, etc.). These broken references are caused by typo's in the references, and by renames or removals of the Documentation files. Some broken references are simply odd. Fix these broken references, sometimes by dropping the irrelevant text they were part of. Signed-off-by: Paul Bolle <pebolle@tiscali.nl> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
301 lines
6.8 KiB
C
301 lines
6.8 KiB
C
/*
|
|
* srm_env.c - Access to SRM environment
|
|
* variables through linux' procfs
|
|
*
|
|
* (C) 2001,2002,2006 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
|
|
*
|
|
* This driver is a modified version of Erik Mouw's example proc
|
|
* interface, 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
|
|
*
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/seq_file.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.6" /* 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_proc_show(struct seq_file *m, void *v)
|
|
{
|
|
unsigned long ret;
|
|
srm_env_t *entry;
|
|
char *page;
|
|
|
|
entry = m->private;
|
|
page = (char *)__get_free_page(GFP_USER);
|
|
if (!page)
|
|
return -ENOMEM;
|
|
|
|
ret = callback_getenv(entry->id, page, PAGE_SIZE);
|
|
|
|
if ((ret >> 61) == 0) {
|
|
seq_write(m, page, ret);
|
|
ret = 0;
|
|
} else
|
|
ret = -EFAULT;
|
|
free_page((unsigned long)page);
|
|
return ret;
|
|
}
|
|
|
|
static int srm_env_proc_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, srm_env_proc_show, PDE(inode)->data);
|
|
}
|
|
|
|
static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer,
|
|
size_t count, loff_t *pos)
|
|
{
|
|
int res;
|
|
srm_env_t *entry = PDE(file->f_path.dentry->d_inode)->data;
|
|
char *buf = (char *) __get_free_page(GFP_USER);
|
|
unsigned long ret1, ret2;
|
|
|
|
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 const struct file_operations srm_env_proc_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = srm_env_proc_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
.write = srm_env_proc_write,
|
|
};
|
|
|
|
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", __func__);
|
|
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) {
|
|
printk(KERN_ERR "Couldn't create base dir /proc/%s\n",
|
|
BASE_DIR);
|
|
goto cleanup;
|
|
}
|
|
|
|
/*
|
|
* Create per-name subdirectory
|
|
*/
|
|
named_dir = proc_mkdir(NAMED_DIR, base_dir);
|
|
if (!named_dir) {
|
|
printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
|
|
BASE_DIR, NAMED_DIR);
|
|
goto cleanup;
|
|
}
|
|
|
|
/*
|
|
* Create per-number subdirectory
|
|
*/
|
|
numbered_dir = proc_mkdir(NUMBERED_DIR, base_dir);
|
|
if (!numbered_dir) {
|
|
printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
|
|
BASE_DIR, NUMBERED_DIR);
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
/*
|
|
* Create all named nodes
|
|
*/
|
|
entry = srm_named_entries;
|
|
while (entry->name && entry->id) {
|
|
entry->proc_entry = proc_create_data(entry->name, 0644, named_dir,
|
|
&srm_env_proc_fops, entry);
|
|
if (!entry->proc_entry)
|
|
goto cleanup;
|
|
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 = proc_create_data(entry->name, 0644, numbered_dir,
|
|
&srm_env_proc_fops, entry);
|
|
if (!entry->proc_entry)
|
|
goto cleanup;
|
|
|
|
entry->id = var_num;
|
|
}
|
|
|
|
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);
|