Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Architecture specific debugfs files
0004  *
0005  * Copyright (C) 2007, Intel Corp.
0006  *  Huang Ying <ying.huang@intel.com>
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     /* Is it direct data or invalid indirect one? */
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 /* CONFIG_DEBUG_BOOT_PARAMS */
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);