2012-01-31 13:19:20 -05:00
/*
* Copyright 2012 Red Hat , Inc < mjg @ redhat . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/device.h>
# include <linux/sysfs.h>
2012-05-09 14:04:02 -07:00
# include <linux/io.h>
2012-01-31 13:19:20 -05:00
# include <acpi/acpi.h>
# include <acpi/acpi_bus.h>
static struct acpi_table_bgrt * bgrt_tab ;
static struct kobject * bgrt_kobj ;
struct bmp_header {
u16 id ;
u32 size ;
} __attribute ( ( packed ) ) ;
static struct bmp_header bmp_header ;
static ssize_t show_version ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %d \n " , bgrt_tab - > version ) ;
}
static DEVICE_ATTR ( version , S_IRUGO , show_version , NULL ) ;
static ssize_t show_status ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %d \n " , bgrt_tab - > status ) ;
}
static DEVICE_ATTR ( status , S_IRUGO , show_status , NULL ) ;
static ssize_t show_type ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %d \n " , bgrt_tab - > image_type ) ;
}
static DEVICE_ATTR ( type , S_IRUGO , show_type , NULL ) ;
static ssize_t show_xoffset ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %d \n " , bgrt_tab - > image_offset_x ) ;
}
static DEVICE_ATTR ( xoffset , S_IRUGO , show_xoffset , NULL ) ;
static ssize_t show_yoffset ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %d \n " , bgrt_tab - > image_offset_y ) ;
}
static DEVICE_ATTR ( yoffset , S_IRUGO , show_yoffset , NULL ) ;
static ssize_t show_image ( struct file * file , struct kobject * kobj ,
struct bin_attribute * attr , char * buf , loff_t off , size_t count )
{
int size = attr - > size ;
void __iomem * image = attr - > private ;
if ( off > = size ) {
count = 0 ;
} else {
if ( off + count > size )
count = size - off ;
memcpy_fromio ( buf , image + off , count ) ;
}
return count ;
}
static struct bin_attribute image_attr = {
. attr = {
. name = " image " ,
. mode = S_IRUGO ,
} ,
. read = show_image ,
} ;
static struct attribute * bgrt_attributes [ ] = {
& dev_attr_version . attr ,
& dev_attr_status . attr ,
& dev_attr_type . attr ,
& dev_attr_xoffset . attr ,
& dev_attr_yoffset . attr ,
NULL ,
} ;
static struct attribute_group bgrt_attribute_group = {
. attrs = bgrt_attributes ,
} ;
static int __init bgrt_init ( void )
{
acpi_status status ;
int ret ;
void __iomem * bgrt ;
if ( acpi_disabled )
return - ENODEV ;
status = acpi_get_table ( " BGRT " , 0 ,
( struct acpi_table_header * * ) & bgrt_tab ) ;
if ( ACPI_FAILURE ( status ) )
return - ENODEV ;
sysfs_bin_attr_init ( & image_attr ) ;
bgrt = ioremap ( bgrt_tab - > image_address , sizeof ( struct bmp_header ) ) ;
if ( ! bgrt ) {
ret = - EINVAL ;
goto out_err ;
}
memcpy_fromio ( & bmp_header , bgrt , sizeof ( bmp_header ) ) ;
image_attr . size = bmp_header . size ;
iounmap ( bgrt ) ;
image_attr . private = ioremap ( bgrt_tab - > image_address , image_attr . size ) ;
if ( ! image_attr . private ) {
ret = - EINVAL ;
goto out_err ;
}
bgrt_kobj = kobject_create_and_add ( " bgrt " , acpi_kobj ) ;
if ( ! bgrt_kobj ) {
ret = - EINVAL ;
goto out_iounmap ;
}
ret = sysfs_create_group ( bgrt_kobj , & bgrt_attribute_group ) ;
if ( ret )
goto out_kobject ;
ret = sysfs_create_bin_file ( bgrt_kobj , & image_attr ) ;
if ( ret )
goto out_group ;
return 0 ;
out_group :
sysfs_remove_group ( bgrt_kobj , & bgrt_attribute_group ) ;
out_kobject :
kobject_put ( bgrt_kobj ) ;
out_iounmap :
iounmap ( image_attr . private ) ;
out_err :
return ret ;
}
static void __exit bgrt_exit ( void )
{
iounmap ( image_attr . private ) ;
sysfs_remove_group ( bgrt_kobj , & bgrt_attribute_group ) ;
sysfs_remove_bin_file ( bgrt_kobj , & image_attr ) ;
}
module_init ( bgrt_init ) ;
module_exit ( bgrt_exit ) ;
MODULE_AUTHOR ( " Matthew Garrett " ) ;
MODULE_DESCRIPTION ( " BGRT boot graphic support " ) ;
MODULE_LICENSE ( " GPL " ) ;