linux/arch/alpha/kernel/srm_env.c
<<
>>
Prefs
   1/*
   2 * srm_env.c - Access to SRM environment
   3 *             variables through linux' procfs
   4 *
   5 * (C) 2001,2002,2006 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
   6 *
   7 * This driver is a modified version of Erik Mouw's example proc
   8 * interface, so: thank you, Erik! He can be reached via email at
   9 * <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea
  10 * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They
  11 * included a patch like this as well. Thanks for idea!
  12 *
  13 * This program is free software; you can redistribute
  14 * it and/or modify it under the terms of the GNU General
  15 * Public License version 2 as published by the Free Software
  16 * Foundation.
  17 *
  18 * This program is distributed in the hope that it will be
  19 * useful, but WITHOUT ANY WARRANTY; without even the implied
  20 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  21 * PURPOSE.  See the GNU General Public License for more
  22 * details.
  23 *
  24 * You should have received a copy of the GNU General Public
  25 * License along with this program; if not, write to the
  26 * Free Software Foundation, Inc., 59 Temple Place,
  27 * Suite 330, Boston, MA  02111-1307  USA
  28 *
  29 */
  30
  31#include <linux/kernel.h>
  32#include <linux/gfp.h>
  33#include <linux/module.h>
  34#include <linux/init.h>
  35#include <linux/proc_fs.h>
  36#include <linux/seq_file.h>
  37#include <asm/console.h>
  38#include <asm/uaccess.h>
  39#include <asm/machvec.h>
  40
  41#define BASE_DIR        "srm_environment"       /* Subdir in /proc/             */
  42#define NAMED_DIR       "named_variables"       /* Subdir for known variables   */
  43#define NUMBERED_DIR    "numbered_variables"    /* Subdir for all variables     */
  44#define VERSION         "0.0.6"                 /* Module version               */
  45#define NAME            "srm_env"               /* Module name                  */
  46
  47MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
  48MODULE_DESCRIPTION("Accessing Alpha SRM environment through procfs interface");
  49MODULE_LICENSE("GPL");
  50
  51typedef struct _srm_env {
  52        char                    *name;
  53        unsigned long           id;
  54} srm_env_t;
  55
  56static struct proc_dir_entry    *base_dir;
  57static struct proc_dir_entry    *named_dir;
  58static struct proc_dir_entry    *numbered_dir;
  59
  60static srm_env_t        srm_named_entries[] = {
  61        { "auto_action",        ENV_AUTO_ACTION         },
  62        { "boot_dev",           ENV_BOOT_DEV            },
  63        { "bootdef_dev",        ENV_BOOTDEF_DEV         },
  64        { "booted_dev",         ENV_BOOTED_DEV          },
  65        { "boot_file",          ENV_BOOT_FILE           },
  66        { "booted_file",        ENV_BOOTED_FILE         },
  67        { "boot_osflags",       ENV_BOOT_OSFLAGS        },
  68        { "booted_osflags",     ENV_BOOTED_OSFLAGS      },
  69        { "boot_reset",         ENV_BOOT_RESET          },
  70        { "dump_dev",           ENV_DUMP_DEV            },
  71        { "enable_audit",       ENV_ENABLE_AUDIT        },
  72        { "license",            ENV_LICENSE             },
  73        { "char_set",           ENV_CHAR_SET            },
  74        { "language",           ENV_LANGUAGE            },
  75        { "tty_dev",            ENV_TTY_DEV             },
  76        { NULL,                 0                       },
  77};
  78
  79static int srm_env_proc_show(struct seq_file *m, void *v)
  80{
  81        unsigned long   ret;
  82        unsigned long   id = (unsigned long)m->private;
  83        char            *page;
  84
  85        page = (char *)__get_free_page(GFP_USER);
  86        if (!page)
  87                return -ENOMEM;
  88
  89        ret = callback_getenv(id, page, PAGE_SIZE);
  90
  91        if ((ret >> 61) == 0) {
  92                seq_write(m, page, ret);
  93                ret = 0;
  94        } else
  95                ret = -EFAULT;
  96        free_page((unsigned long)page);
  97        return ret;
  98}
  99
 100static int srm_env_proc_open(struct inode *inode, struct file *file)
 101{
 102        return single_open(file, srm_env_proc_show, PDE_DATA(inode));
 103}
 104
 105static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer,
 106                                  size_t count, loff_t *pos)
 107{
 108        int res;
 109        unsigned long   id = (unsigned long)PDE_DATA(file_inode(file));
 110        char            *buf = (char *) __get_free_page(GFP_USER);
 111        unsigned long   ret1, ret2;
 112
 113        if (!buf)
 114                return -ENOMEM;
 115
 116        res = -EINVAL;
 117        if (count >= PAGE_SIZE)
 118                goto out;
 119
 120        res = -EFAULT;
 121        if (copy_from_user(buf, buffer, count))
 122                goto out;
 123        buf[count] = '\0';
 124
 125        ret1 = callback_setenv(id, buf, count);
 126        if ((ret1 >> 61) == 0) {
 127                do
 128                        ret2 = callback_save_env();
 129                while((ret2 >> 61) == 1);
 130                res = (int) ret1;
 131        }
 132
 133 out:
 134        free_page((unsigned long)buf);
 135        return res;
 136}
 137
 138static const struct file_operations srm_env_proc_fops = {
 139        .owner          = THIS_MODULE,
 140        .open           = srm_env_proc_open,
 141        .read           = seq_read,
 142        .llseek         = seq_lseek,
 143        .release        = single_release,
 144        .write          = srm_env_proc_write,
 145};
 146
 147static int __init
 148srm_env_init(void)
 149{
 150        srm_env_t       *entry;
 151        unsigned long   var_num;
 152
 153        /*
 154         * Check system
 155         */
 156        if (!alpha_using_srm) {
 157                printk(KERN_INFO "%s: This Alpha system doesn't "
 158                                "know about SRM (or you've booted "
 159                                "SRM->MILO->Linux, which gets "
 160                                "misdetected)...\n", __func__);
 161                return -ENODEV;
 162        }
 163
 164        /*
 165         * Create base directory
 166         */
 167        base_dir = proc_mkdir(BASE_DIR, NULL);
 168        if (!base_dir) {
 169                printk(KERN_ERR "Couldn't create base dir /proc/%s\n",
 170                                BASE_DIR);
 171                return -ENOMEM;
 172        }
 173
 174        /*
 175         * Create per-name subdirectory
 176         */
 177        named_dir = proc_mkdir(NAMED_DIR, base_dir);
 178        if (!named_dir) {
 179                printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
 180                                BASE_DIR, NAMED_DIR);
 181                goto cleanup;
 182        }
 183
 184        /*
 185         * Create per-number subdirectory
 186         */
 187        numbered_dir = proc_mkdir(NUMBERED_DIR, base_dir);
 188        if (!numbered_dir) {
 189                printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
 190                                BASE_DIR, NUMBERED_DIR);
 191                goto cleanup;
 192
 193        }
 194
 195        /*
 196         * Create all named nodes
 197         */
 198        entry = srm_named_entries;
 199        while (entry->name && entry->id) {
 200                if (!proc_create_data(entry->name, 0644, named_dir,
 201                             &srm_env_proc_fops, (void *)entry->id))
 202                        goto cleanup;
 203                entry++;
 204        }
 205
 206        /*
 207         * Create all numbered nodes
 208         */
 209        for (var_num = 0; var_num <= 255; var_num++) {
 210                char name[4];
 211                sprintf(name, "%ld", var_num);
 212                if (!proc_create_data(name, 0644, numbered_dir,
 213                             &srm_env_proc_fops, (void *)var_num))
 214                        goto cleanup;
 215        }
 216
 217        printk(KERN_INFO "%s: version %s loaded successfully\n", NAME,
 218                        VERSION);
 219
 220        return 0;
 221
 222cleanup:
 223        remove_proc_subtree(BASE_DIR, NULL);
 224        return -ENOMEM;
 225}
 226
 227static void __exit
 228srm_env_exit(void)
 229{
 230        remove_proc_subtree(BASE_DIR, NULL);
 231        printk(KERN_INFO "%s: unloaded successfully\n", NAME);
 232}
 233
 234module_init(srm_env_init);
 235module_exit(srm_env_exit);
 236