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