155716d26SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 26d7d7433SHuang, Ying /* 36d7d7433SHuang, Ying * Architecture specific debugfs files 46d7d7433SHuang, Ying * 56d7d7433SHuang, Ying * Copyright (C) 2007, Intel Corp. 66d7d7433SHuang, Ying * Huang Ying <ying.huang@intel.com> 76d7d7433SHuang, Ying */ 86d7d7433SHuang, Ying #include <linux/debugfs.h> 9c14b2adfSHuang, Ying #include <linux/uaccess.h> 10186f4360SPaul Gortmaker #include <linux/export.h> 115a0e3ad6STejun Heo #include <linux/slab.h> 126d7d7433SHuang, Ying #include <linux/init.h> 13390cd85cSJaswinder Singh Rajput #include <linux/stat.h> 14c14b2adfSHuang, Ying #include <linux/io.h> 15c14b2adfSHuang, Ying #include <linux/mm.h> 166d7d7433SHuang, Ying 176d7d7433SHuang, Ying #include <asm/setup.h> 186d7d7433SHuang, Ying 19ae79cdaaSvenkatesh.pallipadi@intel.com struct dentry *arch_debugfs_dir; 20ae79cdaaSvenkatesh.pallipadi@intel.com EXPORT_SYMBOL(arch_debugfs_dir); 21ae79cdaaSvenkatesh.pallipadi@intel.com 226d7d7433SHuang, Ying #ifdef CONFIG_DEBUG_BOOT_PARAMS 23c14b2adfSHuang, Ying struct setup_data_node { 24c14b2adfSHuang, Ying u64 paddr; 25c14b2adfSHuang, Ying u32 type; 26c14b2adfSHuang, Ying u32 len; 27c14b2adfSHuang, Ying }; 28c14b2adfSHuang, Ying 29390cd85cSJaswinder Singh Rajput static ssize_t setup_data_read(struct file *file, char __user *user_buf, 30390cd85cSJaswinder Singh Rajput size_t count, loff_t *ppos) 31c14b2adfSHuang, Ying { 32c14b2adfSHuang, Ying struct setup_data_node *node = file->private_data; 33c14b2adfSHuang, Ying unsigned long remain; 34c14b2adfSHuang, Ying loff_t pos = *ppos; 35c14b2adfSHuang, Ying void *p; 36c14b2adfSHuang, Ying u64 pa; 37c14b2adfSHuang, Ying 38c14b2adfSHuang, Ying if (pos < 0) 39c14b2adfSHuang, Ying return -EINVAL; 40390cd85cSJaswinder Singh Rajput 41c14b2adfSHuang, Ying if (pos >= node->len) 42c14b2adfSHuang, Ying return 0; 43c14b2adfSHuang, Ying 44c14b2adfSHuang, Ying if (count > node->len - pos) 45c14b2adfSHuang, Ying count = node->len - pos; 46390cd85cSJaswinder Singh Rajput 47b3c72fc9SDaniel Kiper pa = node->paddr + pos; 48b3c72fc9SDaniel Kiper 49b3c72fc9SDaniel Kiper /* Is it direct data or invalid indirect one? */ 50b3c72fc9SDaniel Kiper if (!(node->type & SETUP_INDIRECT) || node->type == SETUP_INDIRECT) 51b3c72fc9SDaniel Kiper pa += sizeof(struct setup_data); 52b3c72fc9SDaniel Kiper 53f7750a79STom Lendacky p = memremap(pa, count, MEMREMAP_WB); 54c14b2adfSHuang, Ying if (!p) 55f7750a79STom Lendacky return -ENOMEM; 56c14b2adfSHuang, Ying 57c14b2adfSHuang, Ying remain = copy_to_user(user_buf, p, count); 58c14b2adfSHuang, Ying 59f7750a79STom Lendacky memunmap(p); 60c14b2adfSHuang, Ying 61c14b2adfSHuang, Ying if (remain) 62c14b2adfSHuang, Ying return -EFAULT; 63c14b2adfSHuang, Ying 64c14b2adfSHuang, Ying *ppos = pos + count; 65c14b2adfSHuang, Ying 66c14b2adfSHuang, Ying return count; 67c14b2adfSHuang, Ying } 68c14b2adfSHuang, Ying 69c14b2adfSHuang, Ying static const struct file_operations fops_setup_data = { 70c14b2adfSHuang, Ying .read = setup_data_read, 71234e3405SStephen Boyd .open = simple_open, 726038f373SArnd Bergmann .llseek = default_llseek, 73c14b2adfSHuang, Ying }; 74c14b2adfSHuang, Ying 750fc811e5SGreg Kroah-Hartman static void __init 76c14b2adfSHuang, Ying create_setup_data_node(struct dentry *parent, int no, 77c14b2adfSHuang, Ying struct setup_data_node *node) 78c14b2adfSHuang, Ying { 790fc811e5SGreg Kroah-Hartman struct dentry *d; 80c14b2adfSHuang, Ying char buf[16]; 81c14b2adfSHuang, Ying 82c14b2adfSHuang, Ying sprintf(buf, "%d", no); 83c14b2adfSHuang, Ying d = debugfs_create_dir(buf, parent); 84390cd85cSJaswinder Singh Rajput 850fc811e5SGreg Kroah-Hartman debugfs_create_x32("type", S_IRUGO, d, &node->type); 860fc811e5SGreg Kroah-Hartman debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data); 87c14b2adfSHuang, Ying } 88c14b2adfSHuang, Ying 89c14b2adfSHuang, Ying static int __init create_setup_data_nodes(struct dentry *parent) 90c14b2adfSHuang, Ying { 91*7228918bSRoss Philipson struct setup_indirect *indirect; 92c14b2adfSHuang, Ying struct setup_data_node *node; 93c14b2adfSHuang, Ying struct setup_data *data; 94*7228918bSRoss Philipson u64 pa_data, pa_next; 95c14b2adfSHuang, Ying struct dentry *d; 96*7228918bSRoss Philipson int error; 97*7228918bSRoss Philipson u32 len; 98390cd85cSJaswinder Singh Rajput int no = 0; 99c14b2adfSHuang, Ying 100c14b2adfSHuang, Ying d = debugfs_create_dir("setup_data", parent); 101c14b2adfSHuang, Ying 102c14b2adfSHuang, Ying pa_data = boot_params.hdr.setup_data; 103c14b2adfSHuang, Ying 104c14b2adfSHuang, Ying while (pa_data) { 105c14b2adfSHuang, Ying node = kmalloc(sizeof(*node), GFP_KERNEL); 10641fb433bSJulia Lawall if (!node) { 10741fb433bSJulia Lawall error = -ENOMEM; 108c14b2adfSHuang, Ying goto err_dir; 10941fb433bSJulia Lawall } 110390cd85cSJaswinder Singh Rajput 111f7750a79STom Lendacky data = memremap(pa_data, sizeof(*data), MEMREMAP_WB); 112c14b2adfSHuang, Ying if (!data) { 113f461a1d8SJulia Lawall kfree(node); 114f7750a79STom Lendacky error = -ENOMEM; 115c14b2adfSHuang, Ying goto err_dir; 116c14b2adfSHuang, Ying } 117*7228918bSRoss Philipson pa_next = data->next; 118c14b2adfSHuang, Ying 119*7228918bSRoss Philipson if (data->type == SETUP_INDIRECT) { 120*7228918bSRoss Philipson len = sizeof(*data) + data->len; 121*7228918bSRoss Philipson memunmap(data); 122*7228918bSRoss Philipson data = memremap(pa_data, len, MEMREMAP_WB); 123*7228918bSRoss Philipson if (!data) { 124*7228918bSRoss Philipson kfree(node); 125*7228918bSRoss Philipson error = -ENOMEM; 126*7228918bSRoss Philipson goto err_dir; 127*7228918bSRoss Philipson } 128*7228918bSRoss Philipson 129*7228918bSRoss Philipson indirect = (struct setup_indirect *)data->data; 130*7228918bSRoss Philipson 131*7228918bSRoss Philipson if (indirect->type != SETUP_INDIRECT) { 132*7228918bSRoss Philipson node->paddr = indirect->addr; 133*7228918bSRoss Philipson node->type = indirect->type; 134*7228918bSRoss Philipson node->len = indirect->len; 135*7228918bSRoss Philipson } else { 136*7228918bSRoss Philipson node->paddr = pa_data; 137*7228918bSRoss Philipson node->type = data->type; 138*7228918bSRoss Philipson node->len = data->len; 139*7228918bSRoss Philipson } 140b3c72fc9SDaniel Kiper } else { 141c14b2adfSHuang, Ying node->paddr = pa_data; 142c14b2adfSHuang, Ying node->type = data->type; 143c14b2adfSHuang, Ying node->len = data->len; 144b3c72fc9SDaniel Kiper } 145b3c72fc9SDaniel Kiper 1460fc811e5SGreg Kroah-Hartman create_setup_data_node(d, no, node); 147*7228918bSRoss Philipson pa_data = pa_next; 148c14b2adfSHuang, Ying 149f7750a79STom Lendacky memunmap(data); 150c14b2adfSHuang, Ying no++; 151c14b2adfSHuang, Ying } 152390cd85cSJaswinder Singh Rajput 153c14b2adfSHuang, Ying return 0; 154c14b2adfSHuang, Ying 155c14b2adfSHuang, Ying err_dir: 1560fc811e5SGreg Kroah-Hartman debugfs_remove_recursive(d); 157c14b2adfSHuang, Ying return error; 158c14b2adfSHuang, Ying } 159c14b2adfSHuang, Ying 1606d7d7433SHuang, Ying static struct debugfs_blob_wrapper boot_params_blob = { 1616d7d7433SHuang, Ying .data = &boot_params, 1626d7d7433SHuang, Ying .size = sizeof(boot_params), 1636d7d7433SHuang, Ying }; 1646d7d7433SHuang, Ying 1656d7d7433SHuang, Ying static int __init boot_params_kdebugfs_init(void) 1666d7d7433SHuang, Ying { 1670fc811e5SGreg Kroah-Hartman struct dentry *dbp; 1680fc811e5SGreg Kroah-Hartman int error; 1696d7d7433SHuang, Ying 17010bce841SBorislav Petkov dbp = debugfs_create_dir("boot_params", arch_debugfs_dir); 171390cd85cSJaswinder Singh Rajput 1720fc811e5SGreg Kroah-Hartman debugfs_create_x16("version", S_IRUGO, dbp, &boot_params.hdr.version); 1730fc811e5SGreg Kroah-Hartman debugfs_create_blob("data", S_IRUGO, dbp, &boot_params_blob); 174390cd85cSJaswinder Singh Rajput 175c14b2adfSHuang, Ying error = create_setup_data_nodes(dbp); 176c14b2adfSHuang, Ying if (error) 1770fc811e5SGreg Kroah-Hartman debugfs_remove_recursive(dbp); 178390cd85cSJaswinder Singh Rajput 1796d7d7433SHuang, Ying return error; 1806d7d7433SHuang, Ying } 181390cd85cSJaswinder Singh Rajput #endif /* CONFIG_DEBUG_BOOT_PARAMS */ 1826d7d7433SHuang, Ying 1836d7d7433SHuang, Ying static int __init arch_kdebugfs_init(void) 1846d7d7433SHuang, Ying { 1856d7d7433SHuang, Ying int error = 0; 1866d7d7433SHuang, Ying 187ae79cdaaSvenkatesh.pallipadi@intel.com arch_debugfs_dir = debugfs_create_dir("x86", NULL); 188ae79cdaaSvenkatesh.pallipadi@intel.com 1896d7d7433SHuang, Ying #ifdef CONFIG_DEBUG_BOOT_PARAMS 1906d7d7433SHuang, Ying error = boot_params_kdebugfs_init(); 1916d7d7433SHuang, Ying #endif 1926d7d7433SHuang, Ying 1936d7d7433SHuang, Ying return error; 1946d7d7433SHuang, Ying } 1956d7d7433SHuang, Ying arch_initcall(arch_kdebugfs_init); 196