2008-01-30 13:32:51 +01:00
/*
* Architecture specific debugfs files
*
* Copyright ( C ) 2007 , Intel Corp .
* Huang Ying < ying . huang @ intel . com >
*
* This file is released under the GPLv2 .
*/
# include <linux/debugfs.h>
2008-03-28 10:49:48 +08:00
# include <linux/uaccess.h>
2009-03-21 16:55:45 +05:30
# include <linux/module.h>
2008-01-30 13:32:51 +01:00
# include <linux/init.h>
2009-03-21 16:55:45 +05:30
# include <linux/stat.h>
2008-03-28 10:49:48 +08:00
# include <linux/io.h>
# include <linux/mm.h>
2008-01-30 13:32:51 +01:00
# include <asm/setup.h>
2008-07-18 16:08:13 -07:00
struct dentry * arch_debugfs_dir ;
EXPORT_SYMBOL ( arch_debugfs_dir ) ;
2008-01-30 13:32:51 +01:00
# ifdef CONFIG_DEBUG_BOOT_PARAMS
2008-03-28 10:49:48 +08:00
struct setup_data_node {
u64 paddr ;
u32 type ;
u32 len ;
} ;
2009-03-21 16:55:45 +05:30
static ssize_t setup_data_read ( struct file * file , char __user * user_buf ,
size_t count , loff_t * ppos )
2008-03-28 10:49:48 +08:00
{
struct setup_data_node * node = file - > private_data ;
unsigned long remain ;
loff_t pos = * ppos ;
struct page * pg ;
void * p ;
u64 pa ;
if ( pos < 0 )
return - EINVAL ;
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
if ( pos > = node - > len )
return 0 ;
if ( count > node - > len - pos )
count = node - > len - pos ;
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
pa = node - > paddr + sizeof ( struct setup_data ) + pos ;
pg = pfn_to_page ( ( pa + count - 1 ) > > PAGE_SHIFT ) ;
if ( PageHighMem ( pg ) ) {
p = ioremap_cache ( pa , count ) ;
if ( ! p )
return - ENXIO ;
2009-03-21 16:55:45 +05:30
} else
2008-03-28 10:49:48 +08:00
p = __va ( pa ) ;
remain = copy_to_user ( user_buf , p , count ) ;
if ( PageHighMem ( pg ) )
iounmap ( p ) ;
if ( remain )
return - EFAULT ;
* ppos = pos + count ;
return count ;
}
static int setup_data_open ( struct inode * inode , struct file * file )
{
file - > private_data = inode - > i_private ;
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
return 0 ;
}
static const struct file_operations fops_setup_data = {
2009-03-21 16:55:45 +05:30
. read = setup_data_read ,
. open = setup_data_open ,
2008-03-28 10:49:48 +08:00
} ;
static int __init
create_setup_data_node ( struct dentry * parent , int no ,
struct setup_data_node * node )
{
struct dentry * d , * type , * data ;
char buf [ 16 ] ;
sprintf ( buf , " %d " , no ) ;
d = debugfs_create_dir ( buf , parent ) ;
2009-03-21 16:55:45 +05:30
if ( ! d )
return - ENOMEM ;
2008-03-28 10:49:48 +08:00
type = debugfs_create_x32 ( " type " , S_IRUGO , d , & node - > type ) ;
2009-03-21 16:55:45 +05:30
if ( ! type )
2008-03-28 10:49:48 +08:00
goto err_dir ;
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
data = debugfs_create_file ( " data " , S_IRUGO , d , node , & fops_setup_data ) ;
2009-03-21 16:55:45 +05:30
if ( ! data )
2008-03-28 10:49:48 +08:00
goto err_type ;
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
return 0 ;
err_type :
debugfs_remove ( type ) ;
err_dir :
debugfs_remove ( d ) ;
2009-03-21 16:55:45 +05:30
return - ENOMEM ;
2008-03-28 10:49:48 +08:00
}
static int __init create_setup_data_nodes ( struct dentry * parent )
{
struct setup_data_node * node ;
struct setup_data * data ;
2009-03-21 16:55:45 +05:30
int error = - ENOMEM ;
2008-03-28 10:49:48 +08:00
struct dentry * d ;
struct page * pg ;
u64 pa_data ;
2009-03-21 16:55:45 +05:30
int no = 0 ;
2008-03-28 10:49:48 +08:00
d = debugfs_create_dir ( " setup_data " , parent ) ;
2009-03-21 16:55:45 +05:30
if ( ! d )
return - ENOMEM ;
2008-03-28 10:49:48 +08:00
pa_data = boot_params . hdr . setup_data ;
while ( pa_data ) {
node = kmalloc ( sizeof ( * node ) , GFP_KERNEL ) ;
2009-03-21 16:55:45 +05:30
if ( ! node )
2008-03-28 10:49:48 +08:00
goto err_dir ;
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
pg = pfn_to_page ( ( pa_data + sizeof ( * data ) - 1 ) > > PAGE_SHIFT ) ;
if ( PageHighMem ( pg ) ) {
data = ioremap_cache ( pa_data , sizeof ( * data ) ) ;
if ( ! data ) {
2008-09-10 13:57:43 +02:00
kfree ( node ) ;
2008-03-28 10:49:48 +08:00
error = - ENXIO ;
goto err_dir ;
}
2009-03-21 16:55:45 +05:30
} else
2008-03-28 10:49:48 +08:00
data = __va ( pa_data ) ;
node - > paddr = pa_data ;
node - > type = data - > type ;
node - > len = data - > len ;
error = create_setup_data_node ( d , no , node ) ;
pa_data = data - > next ;
if ( PageHighMem ( pg ) )
iounmap ( data ) ;
if ( error )
goto err_dir ;
no + + ;
}
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
return 0 ;
err_dir :
debugfs_remove ( d ) ;
return error ;
}
2008-01-30 13:32:51 +01:00
static struct debugfs_blob_wrapper boot_params_blob = {
2008-03-28 10:49:48 +08:00
. data = & boot_params ,
. size = sizeof ( boot_params ) ,
2008-01-30 13:32:51 +01:00
} ;
static int __init boot_params_kdebugfs_init ( void )
{
struct dentry * dbp , * version , * data ;
2009-03-21 16:55:45 +05:30
int error = - ENOMEM ;
2008-01-30 13:32:51 +01:00
dbp = debugfs_create_dir ( " boot_params " , NULL ) ;
2009-03-21 16:55:45 +05:30
if ( ! dbp )
return - ENOMEM ;
2008-01-30 13:32:51 +01:00
version = debugfs_create_x16 ( " version " , S_IRUGO , dbp ,
& boot_params . hdr . version ) ;
2009-03-21 16:55:45 +05:30
if ( ! version )
2008-01-30 13:32:51 +01:00
goto err_dir ;
2009-03-21 16:55:45 +05:30
2008-01-30 13:32:51 +01:00
data = debugfs_create_blob ( " data " , S_IRUGO , dbp ,
& boot_params_blob ) ;
2009-03-21 16:55:45 +05:30
if ( ! data )
2008-01-30 13:32:51 +01:00
goto err_version ;
2009-03-21 16:55:45 +05:30
2008-03-28 10:49:48 +08:00
error = create_setup_data_nodes ( dbp ) ;
if ( error )
goto err_data ;
2009-03-21 16:55:45 +05:30
2008-01-30 13:32:51 +01:00
return 0 ;
2008-03-28 10:49:48 +08:00
err_data :
debugfs_remove ( data ) ;
2008-01-30 13:32:51 +01:00
err_version :
debugfs_remove ( version ) ;
err_dir :
debugfs_remove ( dbp ) ;
return error ;
}
2009-03-21 16:55:45 +05:30
# endif /* CONFIG_DEBUG_BOOT_PARAMS */
2008-01-30 13:32:51 +01:00
static int __init arch_kdebugfs_init ( void )
{
int error = 0 ;
2008-07-18 16:08:13 -07:00
arch_debugfs_dir = debugfs_create_dir ( " x86 " , NULL ) ;
if ( ! arch_debugfs_dir )
return - ENOMEM ;
2008-01-30 13:32:51 +01:00
# ifdef CONFIG_DEBUG_BOOT_PARAMS
error = boot_params_kdebugfs_init ( ) ;
# endif
return error ;
}
arch_initcall ( arch_kdebugfs_init ) ;