+/* --------------------------------------------------------------------------
+ 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 = kobject_create_and_add("tables", acpi_kobj);
+ if (!tables_kobj)
+ return -ENOMEM;
+
+ 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);
+ kobject_uevent(tables_kobj, KOBJ_ADD);
+
+ return 0;
+}
+