1 /* 2 * Architecture specific debugfs files 3 * 4 * Copyright (C) 2007, Intel Corp. 5 * Huang Ying <ying.huang@intel.com> 6 * 7 * This file is released under the GPLv2. 8 */ 9 #include <linux/debugfs.h> 10 #include <linux/uaccess.h> 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/stat.h> 14 #include <linux/io.h> 15 #include <linux/mm.h> 16 17 #include <asm/setup.h> 18 19 struct dentry *arch_debugfs_dir; 20 EXPORT_SYMBOL(arch_debugfs_dir); 21 22 #ifdef CONFIG_DEBUG_BOOT_PARAMS 23 struct setup_data_node { 24 u64 paddr; 25 u32 type; 26 u32 len; 27 }; 28 29 static ssize_t setup_data_read(struct file *file, char __user *user_buf, 30 size_t count, loff_t *ppos) 31 { 32 struct setup_data_node *node = file->private_data; 33 unsigned long remain; 34 loff_t pos = *ppos; 35 struct page *pg; 36 void *p; 37 u64 pa; 38 39 if (pos < 0) 40 return -EINVAL; 41 42 if (pos >= node->len) 43 return 0; 44 45 if (count > node->len - pos) 46 count = node->len - pos; 47 48 pa = node->paddr + sizeof(struct setup_data) + pos; 49 pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT); 50 if (PageHighMem(pg)) { 51 p = ioremap_cache(pa, count); 52 if (!p) 53 return -ENXIO; 54 } else 55 p = __va(pa); 56 57 remain = copy_to_user(user_buf, p, count); 58 59 if (PageHighMem(pg)) 60 iounmap(p); 61 62 if (remain) 63 return -EFAULT; 64 65 *ppos = pos + count; 66 67 return count; 68 } 69 70 static int setup_data_open(struct inode *inode, struct file *file) 71 { 72 file->private_data = inode->i_private; 73 74 return 0; 75 } 76 77 static const struct file_operations fops_setup_data = { 78 .read = setup_data_read, 79 .open = setup_data_open, 80 }; 81 82 static int __init 83 create_setup_data_node(struct dentry *parent, int no, 84 struct setup_data_node *node) 85 { 86 struct dentry *d, *type, *data; 87 char buf[16]; 88 89 sprintf(buf, "%d", no); 90 d = debugfs_create_dir(buf, parent); 91 if (!d) 92 return -ENOMEM; 93 94 type = debugfs_create_x32("type", S_IRUGO, d, &node->type); 95 if (!type) 96 goto err_dir; 97 98 data = debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data); 99 if (!data) 100 goto err_type; 101 102 return 0; 103 104 err_type: 105 debugfs_remove(type); 106 err_dir: 107 debugfs_remove(d); 108 return -ENOMEM; 109 } 110 111 static int __init create_setup_data_nodes(struct dentry *parent) 112 { 113 struct setup_data_node *node; 114 struct setup_data *data; 115 int error = -ENOMEM; 116 struct dentry *d; 117 struct page *pg; 118 u64 pa_data; 119 int no = 0; 120 121 d = debugfs_create_dir("setup_data", parent); 122 if (!d) 123 return -ENOMEM; 124 125 pa_data = boot_params.hdr.setup_data; 126 127 while (pa_data) { 128 node = kmalloc(sizeof(*node), GFP_KERNEL); 129 if (!node) 130 goto err_dir; 131 132 pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT); 133 if (PageHighMem(pg)) { 134 data = ioremap_cache(pa_data, sizeof(*data)); 135 if (!data) { 136 kfree(node); 137 error = -ENXIO; 138 goto err_dir; 139 } 140 } else 141 data = __va(pa_data); 142 143 node->paddr = pa_data; 144 node->type = data->type; 145 node->len = data->len; 146 error = create_setup_data_node(d, no, node); 147 pa_data = data->next; 148 149 if (PageHighMem(pg)) 150 iounmap(data); 151 if (error) 152 goto err_dir; 153 no++; 154 } 155 156 return 0; 157 158 err_dir: 159 debugfs_remove(d); 160 return error; 161 } 162 163 static struct debugfs_blob_wrapper boot_params_blob = { 164 .data = &boot_params, 165 .size = sizeof(boot_params), 166 }; 167 168 static int __init boot_params_kdebugfs_init(void) 169 { 170 struct dentry *dbp, *version, *data; 171 int error = -ENOMEM; 172 173 dbp = debugfs_create_dir("boot_params", NULL); 174 if (!dbp) 175 return -ENOMEM; 176 177 version = debugfs_create_x16("version", S_IRUGO, dbp, 178 &boot_params.hdr.version); 179 if (!version) 180 goto err_dir; 181 182 data = debugfs_create_blob("data", S_IRUGO, dbp, 183 &boot_params_blob); 184 if (!data) 185 goto err_version; 186 187 error = create_setup_data_nodes(dbp); 188 if (error) 189 goto err_data; 190 191 return 0; 192 193 err_data: 194 debugfs_remove(data); 195 err_version: 196 debugfs_remove(version); 197 err_dir: 198 debugfs_remove(dbp); 199 return error; 200 } 201 #endif /* CONFIG_DEBUG_BOOT_PARAMS */ 202 203 static int __init arch_kdebugfs_init(void) 204 { 205 int error = 0; 206 207 arch_debugfs_dir = debugfs_create_dir("x86", NULL); 208 if (!arch_debugfs_dir) 209 return -ENOMEM; 210 211 #ifdef CONFIG_DEBUG_BOOT_PARAMS 212 error = boot_params_kdebugfs_init(); 213 #endif 214 215 return error; 216 } 217 arch_initcall(arch_kdebugfs_init); 218