Skip to content

Commit

Permalink
ACPI: Populate /sys/firmware/acpi/tables/
Browse files Browse the repository at this point in the history
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: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Zhang Rui authored and Len Brown committed Jul 22, 2007
1 parent d7fff6f commit d4c5f04
Showing 1 changed file with 144 additions and 21 deletions.
165 changes: 144 additions & 21 deletions drivers/acpi/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,12 @@ ACPI_MODULE_NAME("system");

#define ACPI_SYSTEM_CLASS "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
*/
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;

result = sprintf(buffer, "%x", ACPI_CA_VERSION);
Expand All @@ -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);

/* --------------------------------------------------------------------------
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)
-------------------------------------------------------------------------- */
#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)
{
Expand All @@ -80,7 +194,6 @@ static const struct file_operations acpi_system_info_ops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif

static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
loff_t *);
Expand All @@ -97,13 +210,11 @@ acpi_system_read_dsdt(struct file *file,
struct acpi_table_header *dsdt = NULL;
ssize_t res;


status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt);
if (ACPI_FAILURE(status))
return -ENODEV;

res = simple_read_from_buffer(buffer, count, ppos,
dsdt, dsdt->length);
res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length);

return res;
}
Expand All @@ -123,28 +234,21 @@ acpi_system_read_fadt(struct file *file,
struct acpi_table_header *fadt = NULL;
ssize_t res;


status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt);
if (ACPI_FAILURE(status))
return -ENODEV;

res = simple_read_from_buffer(buffer, count, ppos,
fadt, fadt->length);
res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length);

return res;
}

static int __init acpi_system_init(void)
static int acpi_system_procfs_init(void)
{
struct proc_dir_entry *entry;
int error = 0;
char *name;


if (acpi_disabled)
return 0;

#ifdef CONFIG_ACPI_PROCFS
/* 'info' [R] */
name = ACPI_SYSTEM_FILE_INFO;
entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
Expand All @@ -153,7 +257,6 @@ static int __init acpi_system_init(void)
else {
entry->proc_fops = &acpi_system_info_ops;
}
#endif

/* 'dsdt' [R] */
name = ACPI_SYSTEM_FILE_DSDT;
Expand All @@ -177,12 +280,32 @@ static int __init acpi_system_init(void)
Error:
remove_proc_entry(ACPI_SYSTEM_FILE_FADT, 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);
#endif

error = -EFAULT;
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);

0 comments on commit d4c5f04

Please sign in to comment.