0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/debugfs.h>
0009 #include <linux/uaccess.h>
0010 #include <linux/export.h>
0011 #include <linux/slab.h>
0012 #include <linux/init.h>
0013 #include <linux/stat.h>
0014 #include <linux/io.h>
0015 #include <linux/mm.h>
0016
0017 #include <asm/setup.h>
0018
0019 struct dentry *arch_debugfs_dir;
0020 EXPORT_SYMBOL(arch_debugfs_dir);
0021
0022 #ifdef CONFIG_DEBUG_BOOT_PARAMS
0023 struct setup_data_node {
0024 u64 paddr;
0025 u32 type;
0026 u32 len;
0027 };
0028
0029 static ssize_t setup_data_read(struct file *file, char __user *user_buf,
0030 size_t count, loff_t *ppos)
0031 {
0032 struct setup_data_node *node = file->private_data;
0033 unsigned long remain;
0034 loff_t pos = *ppos;
0035 void *p;
0036 u64 pa;
0037
0038 if (pos < 0)
0039 return -EINVAL;
0040
0041 if (pos >= node->len)
0042 return 0;
0043
0044 if (count > node->len - pos)
0045 count = node->len - pos;
0046
0047 pa = node->paddr + pos;
0048
0049
0050 if (!(node->type & SETUP_INDIRECT) || node->type == SETUP_INDIRECT)
0051 pa += sizeof(struct setup_data);
0052
0053 p = memremap(pa, count, MEMREMAP_WB);
0054 if (!p)
0055 return -ENOMEM;
0056
0057 remain = copy_to_user(user_buf, p, count);
0058
0059 memunmap(p);
0060
0061 if (remain)
0062 return -EFAULT;
0063
0064 *ppos = pos + count;
0065
0066 return count;
0067 }
0068
0069 static const struct file_operations fops_setup_data = {
0070 .read = setup_data_read,
0071 .open = simple_open,
0072 .llseek = default_llseek,
0073 };
0074
0075 static void __init
0076 create_setup_data_node(struct dentry *parent, int no,
0077 struct setup_data_node *node)
0078 {
0079 struct dentry *d;
0080 char buf[16];
0081
0082 sprintf(buf, "%d", no);
0083 d = debugfs_create_dir(buf, parent);
0084
0085 debugfs_create_x32("type", S_IRUGO, d, &node->type);
0086 debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
0087 }
0088
0089 static int __init create_setup_data_nodes(struct dentry *parent)
0090 {
0091 struct setup_indirect *indirect;
0092 struct setup_data_node *node;
0093 struct setup_data *data;
0094 u64 pa_data, pa_next;
0095 struct dentry *d;
0096 int error;
0097 u32 len;
0098 int no = 0;
0099
0100 d = debugfs_create_dir("setup_data", parent);
0101
0102 pa_data = boot_params.hdr.setup_data;
0103
0104 while (pa_data) {
0105 node = kmalloc(sizeof(*node), GFP_KERNEL);
0106 if (!node) {
0107 error = -ENOMEM;
0108 goto err_dir;
0109 }
0110
0111 data = memremap(pa_data, sizeof(*data), MEMREMAP_WB);
0112 if (!data) {
0113 kfree(node);
0114 error = -ENOMEM;
0115 goto err_dir;
0116 }
0117 pa_next = data->next;
0118
0119 if (data->type == SETUP_INDIRECT) {
0120 len = sizeof(*data) + data->len;
0121 memunmap(data);
0122 data = memremap(pa_data, len, MEMREMAP_WB);
0123 if (!data) {
0124 kfree(node);
0125 error = -ENOMEM;
0126 goto err_dir;
0127 }
0128
0129 indirect = (struct setup_indirect *)data->data;
0130
0131 if (indirect->type != SETUP_INDIRECT) {
0132 node->paddr = indirect->addr;
0133 node->type = indirect->type;
0134 node->len = indirect->len;
0135 } else {
0136 node->paddr = pa_data;
0137 node->type = data->type;
0138 node->len = data->len;
0139 }
0140 } else {
0141 node->paddr = pa_data;
0142 node->type = data->type;
0143 node->len = data->len;
0144 }
0145
0146 create_setup_data_node(d, no, node);
0147 pa_data = pa_next;
0148
0149 memunmap(data);
0150 no++;
0151 }
0152
0153 return 0;
0154
0155 err_dir:
0156 debugfs_remove_recursive(d);
0157 return error;
0158 }
0159
0160 static struct debugfs_blob_wrapper boot_params_blob = {
0161 .data = &boot_params,
0162 .size = sizeof(boot_params),
0163 };
0164
0165 static int __init boot_params_kdebugfs_init(void)
0166 {
0167 struct dentry *dbp;
0168 int error;
0169
0170 dbp = debugfs_create_dir("boot_params", arch_debugfs_dir);
0171
0172 debugfs_create_x16("version", S_IRUGO, dbp, &boot_params.hdr.version);
0173 debugfs_create_blob("data", S_IRUGO, dbp, &boot_params_blob);
0174
0175 error = create_setup_data_nodes(dbp);
0176 if (error)
0177 debugfs_remove_recursive(dbp);
0178
0179 return error;
0180 }
0181 #endif
0182
0183 static int __init arch_kdebugfs_init(void)
0184 {
0185 int error = 0;
0186
0187 arch_debugfs_dir = debugfs_create_dir("x86", NULL);
0188
0189 #ifdef CONFIG_DEBUG_BOOT_PARAMS
0190 error = boot_params_kdebugfs_init();
0191 #endif
0192
0193 return error;
0194 }
0195 arch_initcall(arch_kdebugfs_init);