| Zhang Rui | a25ee92 | 2010-07-15 10:46:15 +0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * debugfs.c - ACPI debugfs interface to userspace. | 
|  | 3 | */ | 
|  | 4 |  | 
|  | 5 | #include <linux/init.h> | 
|  | 6 | #include <linux/module.h> | 
|  | 7 | #include <linux/kernel.h> | 
|  | 8 | #include <linux/uaccess.h> | 
|  | 9 | #include <linux/debugfs.h> | 
|  | 10 | #include <acpi/acpi_drivers.h> | 
|  | 11 |  | 
|  | 12 | #define _COMPONENT		ACPI_SYSTEM_COMPONENT | 
|  | 13 | ACPI_MODULE_NAME("debugfs"); | 
|  | 14 |  | 
| Zhang Rui | c637e48 | 2010-07-15 10:46:17 +0800 | [diff] [blame] | 15 |  | 
|  | 16 | /* /sys/modules/acpi/parameters/aml_debug_output */ | 
|  | 17 |  | 
|  | 18 | module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, | 
|  | 19 | bool, 0644); | 
|  | 20 | MODULE_PARM_DESC(aml_debug_output, | 
|  | 21 | "To enable/disable the ACPI Debug Object output."); | 
|  | 22 |  | 
| Zhang Rui | a25ee92 | 2010-07-15 10:46:15 +0800 | [diff] [blame] | 23 | /* /sys/kernel/debug/acpi/custom_method */ | 
|  | 24 |  | 
|  | 25 | static ssize_t cm_write(struct file *file, const char __user * user_buf, | 
|  | 26 | size_t count, loff_t *ppos) | 
|  | 27 | { | 
|  | 28 | static char *buf; | 
|  | 29 | static int uncopied_bytes; | 
|  | 30 | struct acpi_table_header table; | 
|  | 31 | acpi_status status; | 
|  | 32 |  | 
|  | 33 | if (!(*ppos)) { | 
|  | 34 | /* parse the table header to get the table length */ | 
|  | 35 | if (count <= sizeof(struct acpi_table_header)) | 
|  | 36 | return -EINVAL; | 
|  | 37 | if (copy_from_user(&table, user_buf, | 
|  | 38 | sizeof(struct acpi_table_header))) | 
|  | 39 | return -EFAULT; | 
|  | 40 | uncopied_bytes = table.length; | 
|  | 41 | buf = kzalloc(uncopied_bytes, GFP_KERNEL); | 
|  | 42 | if (!buf) | 
|  | 43 | return -ENOMEM; | 
|  | 44 | } | 
|  | 45 |  | 
|  | 46 | if (uncopied_bytes < count) { | 
|  | 47 | kfree(buf); | 
|  | 48 | return -EINVAL; | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | if (copy_from_user(buf + (*ppos), user_buf, count)) { | 
|  | 52 | kfree(buf); | 
|  | 53 | return -EFAULT; | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | uncopied_bytes -= count; | 
|  | 57 | *ppos += count; | 
|  | 58 |  | 
|  | 59 | if (!uncopied_bytes) { | 
|  | 60 | status = acpi_install_method(buf); | 
|  | 61 | kfree(buf); | 
|  | 62 | if (ACPI_FAILURE(status)) | 
|  | 63 | return -EINVAL; | 
|  | 64 | add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); | 
|  | 65 | } | 
|  | 66 |  | 
|  | 67 | return count; | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | static const struct file_operations cm_fops = { | 
|  | 71 | .write = cm_write, | 
|  | 72 | }; | 
|  | 73 |  | 
|  | 74 | int __init acpi_debugfs_init(void) | 
|  | 75 | { | 
|  | 76 | struct dentry *acpi_dir, *cm_dentry; | 
|  | 77 |  | 
|  | 78 | acpi_dir = debugfs_create_dir("acpi", NULL); | 
|  | 79 | if (!acpi_dir) | 
|  | 80 | goto err; | 
|  | 81 |  | 
|  | 82 | cm_dentry = debugfs_create_file("custom_method", S_IWUGO, | 
|  | 83 | acpi_dir, NULL, &cm_fops); | 
|  | 84 | if (!cm_dentry) | 
|  | 85 | goto err; | 
|  | 86 |  | 
|  | 87 | return 0; | 
|  | 88 |  | 
|  | 89 | err: | 
|  | 90 | if (acpi_dir) | 
|  | 91 | debugfs_remove(acpi_dir); | 
|  | 92 | return -EINVAL; | 
|  | 93 | } |