linux/drivers/acpi/system.c
<<
>>
Prefs
   1/*
   2 *  acpi_system.c - ACPI System Driver ($Revision: 63 $)
   3 *
   4 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   5 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   6 *
   7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   8 *
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation; either version 2 of the License, or (at
  12 *  your option) any later version.
  13 *
  14 *  This program is distributed in the hope that it will be useful, but
  15 *  WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 *  General Public License for more details.
  18 *
  19 *  You should have received a copy of the GNU General Public License along
  20 *  with this program; if not, write to the Free Software Foundation, Inc.,
  21 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  22 *
  23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  24 */
  25
  26#include <linux/proc_fs.h>
  27#include <linux/seq_file.h>
  28#include <linux/init.h>
  29#include <asm/uaccess.h>
  30
  31#include <acpi/acpi_drivers.h>
  32
  33#define _COMPONENT              ACPI_SYSTEM_COMPONENT
  34ACPI_MODULE_NAME("system");
  35#ifdef MODULE_PARAM_PREFIX
  36#undef MODULE_PARAM_PREFIX
  37#endif
  38#define MODULE_PARAM_PREFIX "acpi."
  39
  40#define ACPI_SYSTEM_CLASS               "system"
  41#define ACPI_SYSTEM_DEVICE_NAME         "System"
  42
  43/*
  44 * Make ACPICA version work as module param
  45 */
  46static int param_get_acpica_version(char *buffer, struct kernel_param *kp)
  47{
  48        int result;
  49
  50        result = sprintf(buffer, "%x", ACPI_CA_VERSION);
  51
  52        return result;
  53}
  54
  55module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
  56
  57/* --------------------------------------------------------------------------
  58                              FS Interface (/sys)
  59   -------------------------------------------------------------------------- */
  60static LIST_HEAD(acpi_table_attr_list);
  61static struct kobject tables_kobj;
  62
  63struct acpi_table_attr {
  64        struct bin_attribute attr;
  65        char name[8];
  66        int instance;
  67        struct list_head node;
  68};
  69
  70static ssize_t acpi_table_show(struct kobject *kobj,
  71                               struct bin_attribute *bin_attr, char *buf,
  72                               loff_t offset, size_t count)
  73{
  74        struct acpi_table_attr *table_attr =
  75            container_of(bin_attr, struct acpi_table_attr, attr);
  76        struct acpi_table_header *table_header = NULL;
  77        acpi_status status;
  78        ssize_t ret_count = count;
  79
  80        status =
  81            acpi_get_table(table_attr->name, table_attr->instance,
  82                           &table_header);
  83        if (ACPI_FAILURE(status))
  84                return -ENODEV;
  85
  86        if (offset >= table_header->length) {
  87                ret_count = 0;
  88                goto end;
  89        }
  90
  91        if (offset + ret_count > table_header->length)
  92                ret_count = table_header->length - offset;
  93
  94        memcpy(buf, ((char *)table_header) + offset, ret_count);
  95
  96      end:
  97        return ret_count;
  98}
  99
 100static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
 101                                 struct acpi_table_header *table_header)
 102{
 103        struct acpi_table_header *header = NULL;
 104        struct acpi_table_attr *attr = NULL;
 105
 106        memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE);
 107
 108        list_for_each_entry(attr, &acpi_table_attr_list, node) {
 109                if (!memcmp(table_header->signature, attr->name,
 110                            ACPI_NAME_SIZE))
 111                        if (table_attr->instance < attr->instance)
 112                                table_attr->instance = attr->instance;
 113        }
 114        table_attr->instance++;
 115
 116        if (table_attr->instance > 1 || (table_attr->instance == 1 &&
 117                                         !acpi_get_table(table_header->
 118                                                         signature, 2,
 119                                                         &header)))
 120                sprintf(table_attr->name + 4, "%d", table_attr->instance);
 121
 122        table_attr->attr.size = 0;
 123        table_attr->attr.read = acpi_table_show;
 124        table_attr->attr.attr.name = table_attr->name;
 125        table_attr->attr.attr.mode = 0444;
 126        table_attr->attr.attr.owner = THIS_MODULE;
 127
 128        return;
 129}
 130
 131static int acpi_system_sysfs_init(void)
 132{
 133        struct acpi_table_attr *table_attr;
 134        struct acpi_table_header *table_header = NULL;
 135        int table_index = 0;
 136        int result;
 137
 138        tables_kobj.parent = &acpi_subsys.kobj;
 139        kobject_set_name(&tables_kobj, "tables");
 140        result = kobject_register(&tables_kobj);
 141        if (result)
 142                return result;
 143
 144        do {
 145                result = acpi_get_table_by_index(table_index, &table_header);
 146                if (!result) {
 147                        table_index++;
 148                        table_attr = NULL;
 149                        table_attr =
 150                            kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);
 151                        if (!table_attr)
 152                                return -ENOMEM;
 153
 154                        acpi_table_attr_init(table_attr, table_header);
 155                        result =
 156                            sysfs_create_bin_file(&tables_kobj,
 157                                                  &table_attr->attr);
 158                        if (result) {
 159                                kfree(table_attr);
 160                                return result;
 161                        } else
 162                                list_add_tail(&table_attr->node,
 163                                              &acpi_table_attr_list);
 164                }
 165        } while (!result);
 166
 167        return 0;
 168}
 169
 170/* --------------------------------------------------------------------------
 171                              FS Interface (/proc)
 172   -------------------------------------------------------------------------- */
 173#ifdef CONFIG_ACPI_PROCFS
 174#define ACPI_SYSTEM_FILE_INFO           "info"
 175#define ACPI_SYSTEM_FILE_EVENT          "event"
 176#define ACPI_SYSTEM_FILE_DSDT           "dsdt"
 177#define ACPI_SYSTEM_FILE_FADT           "fadt"
 178
 179static int acpi_system_read_info(struct seq_file *seq, void *offset)
 180{
 181
 182        seq_printf(seq, "version:                 %x\n", ACPI_CA_VERSION);
 183        return 0;
 184}
 185
 186static int acpi_system_info_open_fs(struct inode *inode, struct file *file)
 187{
 188        return single_open(file, acpi_system_read_info, PDE(inode)->data);
 189}
 190
 191static const struct file_operations acpi_system_info_ops = {
 192        .open = acpi_system_info_open_fs,
 193        .read = seq_read,
 194        .llseek = seq_lseek,
 195        .release = single_release,
 196};
 197
 198static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
 199                                     loff_t *);
 200
 201static const struct file_operations acpi_system_dsdt_ops = {
 202        .read = acpi_system_read_dsdt,
 203};
 204
 205static ssize_t
 206acpi_system_read_dsdt(struct file *file,
 207                      char __user * buffer, size_t count, loff_t * ppos)
 208{
 209        acpi_status status = AE_OK;
 210        struct acpi_table_header *dsdt = NULL;
 211        ssize_t res;
 212
 213        status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt);
 214        if (ACPI_FAILURE(status))
 215                return -ENODEV;
 216
 217        res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length);
 218
 219        return res;
 220}
 221
 222static ssize_t acpi_system_read_fadt(struct file *, char __user *, size_t,
 223                                     loff_t *);
 224
 225static const struct file_operations acpi_system_fadt_ops = {
 226        .read = acpi_system_read_fadt,
 227};
 228
 229static ssize_t
 230acpi_system_read_fadt(struct file *file,
 231                      char __user * buffer, size_t count, loff_t * ppos)
 232{
 233        acpi_status status = AE_OK;
 234        struct acpi_table_header *fadt = NULL;
 235        ssize_t res;
 236
 237        status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt);
 238        if (ACPI_FAILURE(status))
 239                return -ENODEV;
 240
 241        res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length);
 242
 243        return res;
 244}
 245
 246static int acpi_system_procfs_init(void)
 247{
 248        struct proc_dir_entry *entry;
 249        int error = 0;
 250        char *name;
 251
 252        /* 'info' [R] */
 253        name = ACPI_SYSTEM_FILE_INFO;
 254        entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
 255        if (!entry)
 256                goto Error;
 257        else {
 258                entry->proc_fops = &acpi_system_info_ops;
 259        }
 260
 261        /* 'dsdt' [R] */
 262        name = ACPI_SYSTEM_FILE_DSDT;
 263        entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
 264        if (entry)
 265                entry->proc_fops = &acpi_system_dsdt_ops;
 266        else
 267                goto Error;
 268
 269        /* 'fadt' [R] */
 270        name = ACPI_SYSTEM_FILE_FADT;
 271        entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
 272        if (entry)
 273                entry->proc_fops = &acpi_system_fadt_ops;
 274        else
 275                goto Error;
 276
 277      Done:
 278        return error;
 279
 280      Error:
 281        remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
 282        remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
 283        remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir);
 284
 285        error = -EFAULT;
 286        goto Done;
 287}
 288#else
 289static int acpi_system_procfs_init(void)
 290{
 291        return 0;
 292}
 293#endif
 294
 295static int __init acpi_system_init(void)
 296{
 297        int result = 0;
 298
 299        if (acpi_disabled)
 300                return 0;
 301
 302        result = acpi_system_procfs_init();
 303        if (result)
 304                return result;
 305
 306        result = acpi_system_sysfs_init();
 307
 308        return result;
 309}
 310
 311subsys_initcall(acpi_system_init);
 312