Commit d4c5f047 authored by Zhang Rui's avatar Zhang Rui Committed by Len Brown

ACPI: Populate /sys/firmware/acpi/tables/

The file name is the signature, such as DSDT,
and the contents are the binary table image.

Some tables, such as the SSDT, can have multiple instances.
If just one, the file is SSDT, but if 3 instances,
for example, it will be SSDT1, SSDT2, SSDT3

All static tables (besides teh RSDP and RSDT themselves
are exported.  Dynamic tables, such as SSDT op-regions that
are not declared in the RSDT, will be added in a subsequent patch.
Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent d7fff6f4
...@@ -39,15 +39,12 @@ ACPI_MODULE_NAME("system"); ...@@ -39,15 +39,12 @@ ACPI_MODULE_NAME("system");
#define ACPI_SYSTEM_CLASS "system" #define ACPI_SYSTEM_CLASS "system"
#define ACPI_SYSTEM_DEVICE_NAME "System" #define ACPI_SYSTEM_DEVICE_NAME "System"
#define ACPI_SYSTEM_FILE_INFO "info"
#define ACPI_SYSTEM_FILE_EVENT "event"
#define ACPI_SYSTEM_FILE_DSDT "dsdt"
#define ACPI_SYSTEM_FILE_FADT "fadt"
/* /*
* Make ACPICA version work as module param * Make ACPICA version work as module param
*/ */
static int param_get_acpica_version(char *buffer, struct kernel_param *kp) { static int param_get_acpica_version(char *buffer, struct kernel_param *kp)
{
int result; int result;
result = sprintf(buffer, "%x", ACPI_CA_VERSION); result = sprintf(buffer, "%x", ACPI_CA_VERSION);
...@@ -57,10 +54,127 @@ static int param_get_acpica_version(char *buffer, struct kernel_param *kp) { ...@@ -57,10 +54,127 @@ static int param_get_acpica_version(char *buffer, struct kernel_param *kp) {
module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
/* --------------------------------------------------------------------------
FS Interface (/sys)
-------------------------------------------------------------------------- */
static LIST_HEAD(acpi_table_attr_list);
static struct kobject tables_kobj;
struct acpi_table_attr {
struct bin_attribute attr;
char name[8];
int instance;
struct list_head node;
};
static ssize_t acpi_table_show(struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf,
loff_t offset, size_t count)
{
struct acpi_table_attr *table_attr =
container_of(bin_attr, struct acpi_table_attr, attr);
struct acpi_table_header *table_header = NULL;
acpi_status status;
ssize_t ret_count = count;
status =
acpi_get_table(table_attr->name, table_attr->instance,
&table_header);
if (ACPI_FAILURE(status))
return -ENODEV;
if (offset >= table_header->length) {
ret_count = 0;
goto end;
}
if (offset + ret_count > table_header->length)
ret_count = table_header->length - offset;
memcpy(buf, ((char *)table_header) + offset, ret_count);
end:
return ret_count;
}
static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
struct acpi_table_header *table_header)
{
struct acpi_table_header *header = NULL;
struct acpi_table_attr *attr = NULL;
memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE);
list_for_each_entry(attr, &acpi_table_attr_list, node) {
if (!memcmp(table_header->signature, attr->name,
ACPI_NAME_SIZE))
if (table_attr->instance < attr->instance)
table_attr->instance = attr->instance;
}
table_attr->instance++;
if (table_attr->instance > 1 || (table_attr->instance == 1 &&
!acpi_get_table(table_header->
signature, 2,
&header)))
sprintf(table_attr->name + 4, "%d", table_attr->instance);
table_attr->attr.size = 0;
table_attr->attr.read = acpi_table_show;
table_attr->attr.attr.name = table_attr->name;
table_attr->attr.attr.mode = 0444;
table_attr->attr.attr.owner = THIS_MODULE;
return;
}
static int acpi_system_sysfs_init(void)
{
struct acpi_table_attr *table_attr;
struct acpi_table_header *table_header = NULL;
int table_index = 0;
int result;
tables_kobj.parent = &acpi_subsys.kobj;
kobject_set_name(&tables_kobj, "tables");
result = kobject_register(&tables_kobj);
if (result)
return result;
do {
result = acpi_get_table_by_index(table_index, &table_header);
if (!result) {
table_index++;
table_attr = NULL;
table_attr =
kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);
if (!table_attr)
return -ENOMEM;
acpi_table_attr_init(table_attr, table_header);
result =
sysfs_create_bin_file(&tables_kobj,
&table_attr->attr);
if (result) {
kfree(table_attr);
return result;
} else
list_add_tail(&table_attr->node,
&acpi_table_attr_list);
}
} while (!result);
return 0;
}
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
FS Interface (/proc) FS Interface (/proc)
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS
#define ACPI_SYSTEM_FILE_INFO "info"
#define ACPI_SYSTEM_FILE_EVENT "event"
#define ACPI_SYSTEM_FILE_DSDT "dsdt"
#define ACPI_SYSTEM_FILE_FADT "fadt"
static int acpi_system_read_info(struct seq_file *seq, void *offset) static int acpi_system_read_info(struct seq_file *seq, void *offset)
{ {
...@@ -80,7 +194,6 @@ static const struct file_operations acpi_system_info_ops = { ...@@ -80,7 +194,6 @@ static const struct file_operations acpi_system_info_ops = {
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
}; };
#endif
static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
loff_t *); loff_t *);
...@@ -97,13 +210,11 @@ acpi_system_read_dsdt(struct file *file, ...@@ -97,13 +210,11 @@ acpi_system_read_dsdt(struct file *file,
struct acpi_table_header *dsdt = NULL; struct acpi_table_header *dsdt = NULL;
ssize_t res; ssize_t res;
status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENODEV; return -ENODEV;
res = simple_read_from_buffer(buffer, count, ppos, res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length);
dsdt, dsdt->length);
return res; return res;
} }
...@@ -123,28 +234,21 @@ acpi_system_read_fadt(struct file *file, ...@@ -123,28 +234,21 @@ acpi_system_read_fadt(struct file *file,
struct acpi_table_header *fadt = NULL; struct acpi_table_header *fadt = NULL;
ssize_t res; ssize_t res;
status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENODEV; return -ENODEV;
res = simple_read_from_buffer(buffer, count, ppos, res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length);
fadt, fadt->length);
return res; return res;
} }
static int __init acpi_system_init(void) static int acpi_system_procfs_init(void)
{ {
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
int error = 0; int error = 0;
char *name; char *name;
if (acpi_disabled)
return 0;
#ifdef CONFIG_ACPI_PROCFS
/* 'info' [R] */ /* 'info' [R] */
name = ACPI_SYSTEM_FILE_INFO; name = ACPI_SYSTEM_FILE_INFO;
entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
...@@ -153,7 +257,6 @@ static int __init acpi_system_init(void) ...@@ -153,7 +257,6 @@ static int __init acpi_system_init(void)
else { else {
entry->proc_fops = &acpi_system_info_ops; entry->proc_fops = &acpi_system_info_ops;
} }
#endif
/* 'dsdt' [R] */ /* 'dsdt' [R] */
name = ACPI_SYSTEM_FILE_DSDT; name = ACPI_SYSTEM_FILE_DSDT;
...@@ -177,12 +280,32 @@ static int __init acpi_system_init(void) ...@@ -177,12 +280,32 @@ static int __init acpi_system_init(void)
Error: Error:
remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir);
#endif
error = -EFAULT; error = -EFAULT;
goto Done; goto Done;
} }
#else
static int acpi_system_procfs_init(void)
{
return 0;
}
#endif
static int __init acpi_system_init(void)
{
int result = 0;
if (acpi_disabled)
return 0;
result = acpi_system_procfs_init();
if (result)
return result;
result = acpi_system_sysfs_init();
return result;
}
subsys_initcall(acpi_system_init); subsys_initcall(acpi_system_init);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment