2012-09-28 17:57:05 -07:00
/*
* Copyright 2012 Intel Corporation
* Author : Josh Triplett < josh @ joshtriplett . org >
*
* Based on the bgrt driver :
* Copyright 2012 Red Hat , Inc < mjg @ redhat . com >
* Author : Matthew Garrett
*
* 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 .
*/
2015-10-25 10:26:35 +00:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2012-09-28 17:57:05 -07:00
# include <linux/kernel.h>
2012-11-23 16:30:07 +00:00
# include <linux/init.h>
2012-09-28 17:57:05 -07:00
# include <linux/acpi.h>
# include <linux/efi.h>
# include <linux/efi-bgrt.h>
struct acpi_table_bgrt * bgrt_tab ;
2012-11-23 16:30:07 +00:00
void * __initdata bgrt_image ;
size_t __initdata bgrt_image_size ;
2012-09-28 17:57:05 -07:00
struct bmp_header {
u16 id ;
u32 size ;
} __packed ;
2012-11-23 16:30:07 +00:00
void __init efi_bgrt_init ( void )
2012-09-28 17:57:05 -07:00
{
acpi_status status ;
void __iomem * image ;
bool ioremapped = false ;
struct bmp_header bmp_header ;
if ( acpi_disabled )
return ;
status = acpi_get_table ( " BGRT " , 0 ,
( struct acpi_table_header * * ) & bgrt_tab ) ;
if ( ACPI_FAILURE ( status ) )
return ;
2014-07-30 12:23:32 -07:00
if ( bgrt_tab - > header . length < sizeof ( * bgrt_tab ) ) {
pr_err ( " Ignoring BGRT: invalid length %u (expected %zu) \n " ,
bgrt_tab - > header . length , sizeof ( * bgrt_tab ) ) ;
2012-11-07 16:46:08 +00:00
return ;
2014-07-30 12:23:32 -07:00
}
if ( bgrt_tab - > version ! = 1 ) {
pr_err ( " Ignoring BGRT: invalid version %u (expected 1) \n " ,
bgrt_tab - > version ) ;
return ;
}
2015-08-07 09:36:55 +01:00
if ( bgrt_tab - > status & 0xfe ) {
pr_err ( " Ignoring BGRT: reserved status bits are non-zero %u \n " ,
2014-07-30 12:23:32 -07:00
bgrt_tab - > status ) ;
return ;
}
2015-08-07 09:36:55 +01:00
if ( bgrt_tab - > status ! = 1 ) {
pr_debug ( " Ignoring BGRT: invalid status %u (expected 1) \n " ,
bgrt_tab - > status ) ;
return ;
}
2014-07-30 12:23:32 -07:00
if ( bgrt_tab - > image_type ! = 0 ) {
pr_err ( " Ignoring BGRT: invalid image type %u (expected 0) \n " ,
bgrt_tab - > image_type ) ;
2012-09-28 17:57:05 -07:00
return ;
2014-07-30 12:23:32 -07:00
}
if ( ! bgrt_tab - > image_address ) {
pr_err ( " Ignoring BGRT: null image address \n " ) ;
2012-09-28 17:57:05 -07:00
return ;
2014-07-30 12:23:32 -07:00
}
2012-09-28 17:57:05 -07:00
image = efi_lookup_mapped_addr ( bgrt_tab - > image_address ) ;
if ( ! image ) {
2015-02-24 10:13:31 +01:00
image = early_ioremap ( bgrt_tab - > image_address ,
2014-01-14 12:40:09 +00:00
sizeof ( bmp_header ) ) ;
2012-09-28 17:57:05 -07:00
ioremapped = true ;
2014-07-30 12:23:32 -07:00
if ( ! image ) {
pr_err ( " Ignoring BGRT: failed to map image header memory \n " ) ;
2012-09-28 17:57:05 -07:00
return ;
2014-07-30 12:23:32 -07:00
}
2012-09-28 17:57:05 -07:00
}
memcpy_fromio ( & bmp_header , image , sizeof ( bmp_header ) ) ;
if ( ioremapped )
2014-01-14 12:40:09 +00:00
early_iounmap ( image , sizeof ( bmp_header ) ) ;
2012-09-28 17:57:05 -07:00
bgrt_image_size = bmp_header . size ;
2014-07-30 12:23:32 -07:00
bgrt_image = kmalloc ( bgrt_image_size , GFP_KERNEL | __GFP_NOWARN ) ;
if ( ! bgrt_image ) {
pr_err ( " Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes) \n " ,
bgrt_image_size ) ;
2012-09-28 17:57:05 -07:00
return ;
2014-07-30 12:23:32 -07:00
}
2012-09-28 17:57:05 -07:00
if ( ioremapped ) {
2015-02-24 10:13:31 +01:00
image = early_ioremap ( bgrt_tab - > image_address ,
2014-01-14 12:40:09 +00:00
bmp_header . size ) ;
2012-09-28 17:57:05 -07:00
if ( ! image ) {
2014-07-30 12:23:32 -07:00
pr_err ( " Ignoring BGRT: failed to map image memory \n " ) ;
2012-09-28 17:57:05 -07:00
kfree ( bgrt_image ) ;
bgrt_image = NULL ;
return ;
}
}
memcpy_fromio ( bgrt_image , image , bgrt_image_size ) ;
if ( ioremapped )
2014-01-14 12:40:09 +00:00
early_iounmap ( image , bmp_header . size ) ;
2012-09-28 17:57:05 -07:00
}