at v2.6.23 8.0 kB view raw
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);