2008-04-10 06:50:41 +04:00
/*
2010-02-25 23:37:17 +03:00
* Copyright 2007 - 2010 Red Hat , Inc .
2008-04-10 06:50:41 +04:00
* by Peter Jones < pjones @ redhat . com >
* Copyright 2007 IBM , Inc .
* by Konrad Rzeszutek < konradr @ linux . vnet . ibm . com >
* Copyright 2008
* by Konrad Rzeszutek < ketuzsezr @ darnok . org >
*
* This code finds the iSCSI Boot Format Table .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License v2 .0 as published by
* the Free Software Foundation
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# include <linux/bootmem.h>
# include <linux/blkdev.h>
# include <linux/ctype.h>
# include <linux/device.h>
2010-02-25 23:37:17 +03:00
# include <linux/efi.h>
2008-04-10 06:50:41 +04:00
# include <linux/err.h>
# include <linux/init.h>
# include <linux/limits.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/stat.h>
# include <linux/string.h>
# include <linux/types.h>
2010-02-25 23:37:17 +03:00
# include <linux/acpi.h>
# include <linux/iscsi_ibft.h>
2008-04-10 06:50:41 +04:00
# include <asm/mmzone.h>
/*
* Physical location of iSCSI Boot Format Table .
*/
2010-02-25 23:37:17 +03:00
struct acpi_table_ibft * ibft_addr ;
2008-04-10 06:50:41 +04:00
EXPORT_SYMBOL_GPL ( ibft_addr ) ;
2011-04-15 07:50:57 +04:00
static const struct {
char * sign ;
} ibft_signs [ ] = {
{ " iBFT " } ,
{ " BIFT " } , /* Broadcom iSCSI Offload */
} ;
2008-04-10 06:50:41 +04:00
# define IBFT_SIGN_LEN 4
# define IBFT_START 0x80000 /* 512kB */
# define IBFT_END 0x100000 /* 1MB */
# define VGA_MEM 0xA0000 /* VGA buffer */
# define VGA_SIZE 0x20000 /* 128kB */
2010-04-08 20:35:55 +04:00
static int __init find_ibft_in_mem ( void )
2008-04-10 06:50:41 +04:00
{
unsigned long pos ;
unsigned int len = 0 ;
void * virt ;
2011-04-15 07:50:57 +04:00
int i ;
2008-04-10 06:50:41 +04:00
for ( pos = IBFT_START ; pos < IBFT_END ; pos + = 16 ) {
/* The table can't be inside the VGA BIOS reserved space,
* so skip that area */
if ( pos = = VGA_MEM )
pos + = VGA_SIZE ;
2009-10-02 19:12:39 +04:00
virt = isa_bus_to_virt ( pos ) ;
2011-04-15 07:50:57 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( ibft_signs ) ; i + + ) {
if ( memcmp ( virt , ibft_signs [ i ] . sign , IBFT_SIGN_LEN ) = =
0 ) {
unsigned long * addr =
( unsigned long * ) isa_bus_to_virt ( pos + 4 ) ;
len = * addr ;
/* if the length of the table extends past 1M,
* the table cannot be valid . */
if ( pos + len < = ( IBFT_END - 1 ) ) {
ibft_addr = ( struct acpi_table_ibft * ) virt ;
2011-12-13 00:39:14 +04:00
pr_info ( " iBFT found at 0x%lx. \n " , pos ) ;
2011-04-15 07:50:57 +04:00
goto done ;
}
2008-04-10 06:50:41 +04:00
}
}
}
2011-04-15 07:50:57 +04:00
done :
2010-04-08 20:35:55 +04:00
return len ;
}
/*
* Routine used to find the iSCSI Boot Format Table . The logical
* kernel address is set in the ibft_addr global variable .
*/
unsigned long __init find_ibft_region ( unsigned long * sizep )
{
ibft_addr = NULL ;
/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
* only use ACPI for this */
2012-11-14 13:42:35 +04:00
if ( ! efi_enabled ( EFI_BOOT ) )
2010-04-08 20:35:55 +04:00
find_ibft_in_mem ( ) ;
2010-04-02 01:32:43 +04:00
if ( ibft_addr ) {
2010-02-25 23:37:17 +03:00
* sizep = PAGE_ALIGN ( ibft_addr - > header . length ) ;
return ( u64 ) isa_virt_to_bus ( ibft_addr ) ;
2010-04-02 01:32:43 +04:00
}
* sizep = 0 ;
return 0 ;
2008-04-10 06:50:41 +04:00
}