2020-02-18 09:54:05 +01:00
// SPDX-License-Identifier: GPL-2.0-only
# define pr_fmt(fmt) "efi: " fmt
# include <linux/module.h>
# include <linux/init.h>
# include <linux/efi.h>
2020-02-19 15:29:06 +01:00
# include <linux/libfdt.h>
2020-02-18 09:54:05 +01:00
# include <linux/of_fdt.h>
2020-02-19 15:29:06 +01:00
# include <asm/unaligned.h>
2020-02-18 09:54:05 +01:00
2020-02-19 15:29:06 +01:00
enum {
SYSTAB ,
MMBASE ,
MMSIZE ,
DCSIZE ,
DCVERS ,
2020-02-18 09:54:05 +01:00
2020-02-19 15:29:06 +01:00
PARAMCOUNT
2020-02-18 09:54:05 +01:00
} ;
2020-02-19 15:29:06 +01:00
static __initconst const char name [ ] [ 22 ] = {
[ SYSTAB ] = " System Table " ,
[ MMBASE ] = " MemMap Address " ,
[ MMSIZE ] = " MemMap Size " ,
[ DCSIZE ] = " MemMap Desc. Size " ,
[ DCVERS ] = " MemMap Desc. Version " ,
2020-02-18 09:54:05 +01:00
} ;
2020-02-19 15:29:06 +01:00
static __initconst const struct {
const char path [ 17 ] ;
const char params [ PARAMCOUNT ] [ 26 ] ;
2020-02-18 09:54:05 +01:00
} dt_params [ ] = {
2020-02-19 15:29:06 +01:00
{
# ifdef CONFIG_XEN // <-------17------>
. path = " /hypervisor/uefi " ,
. params = {
[ SYSTAB ] = " xen,uefi-system-table " ,
[ MMBASE ] = " xen,uefi-mmap-start " ,
[ MMSIZE ] = " xen,uefi-mmap-size " ,
[ DCSIZE ] = " xen,uefi-mmap-desc-size " ,
[ DCVERS ] = " xen,uefi-mmap-desc-ver " ,
}
} , {
# endif
. path = " /chosen " ,
. params = { // <-----------26----------->
[ SYSTAB ] = " linux,uefi-system-table " ,
[ MMBASE ] = " linux,uefi-mmap-start " ,
[ MMSIZE ] = " linux,uefi-mmap-size " ,
[ DCSIZE ] = " linux,uefi-mmap-desc-size " ,
[ DCVERS ] = " linux,uefi-mmap-desc-ver " ,
}
}
2020-02-18 09:54:05 +01:00
} ;
2020-02-19 15:29:06 +01:00
static int __init efi_get_fdt_prop ( const void * fdt , int node , const char * pname ,
const char * rname , void * var , int size )
2020-02-18 09:54:05 +01:00
{
const void * prop ;
2020-02-19 15:29:06 +01:00
int len ;
2020-02-18 09:54:05 +01:00
u64 val ;
2020-02-19 15:29:06 +01:00
prop = fdt_getprop ( fdt , node , pname , & len ) ;
if ( ! prop )
return 1 ;
2020-02-18 09:54:05 +01:00
2020-02-19 15:29:06 +01:00
val = ( len = = 4 ) ? ( u64 ) be32_to_cpup ( prop ) : get_unaligned_be64 ( prop ) ;
2020-02-18 09:54:05 +01:00
2020-02-19 15:29:06 +01:00
if ( size = = 8 )
* ( u64 * ) var = val ;
else
* ( u32 * ) var = ( val < U32_MAX ) ? val : U32_MAX ; // saturate
2020-02-18 09:54:05 +01:00
2020-02-19 15:29:06 +01:00
if ( efi_enabled ( EFI_DBG ) )
pr_info ( " %s: 0x%0*llx \n " , rname , size * 2 , val ) ;
2020-02-18 09:54:05 +01:00
2020-02-19 15:29:06 +01:00
return 0 ;
2020-02-18 09:54:05 +01:00
}
2020-02-19 15:29:06 +01:00
u64 __init efi_get_fdt_params ( struct efi_memory_map_data * mm )
2020-02-18 09:54:05 +01:00
{
2020-02-19 15:29:06 +01:00
const void * fdt = initial_boot_params ;
unsigned long systab ;
int i , j , node ;
struct {
void * var ;
int size ;
} target [ ] = {
[ SYSTAB ] = { & systab , sizeof ( systab ) } ,
[ MMBASE ] = { & mm - > phys_map , sizeof ( mm - > phys_map ) } ,
[ MMSIZE ] = { & mm - > size , sizeof ( mm - > size ) } ,
[ DCSIZE ] = { & mm - > desc_size , sizeof ( mm - > desc_size ) } ,
[ DCVERS ] = { & mm - > desc_version , sizeof ( mm - > desc_version ) } ,
} ;
BUILD_BUG_ON ( ARRAY_SIZE ( target ) ! = ARRAY_SIZE ( name ) ) ;
BUILD_BUG_ON ( ARRAY_SIZE ( target ) ! = ARRAY_SIZE ( dt_params [ 0 ] . params ) ) ;
2020-02-18 09:54:05 +01:00
for ( i = 0 ; i < ARRAY_SIZE ( dt_params ) ; i + + ) {
2020-02-19 15:29:06 +01:00
node = fdt_path_offset ( fdt , dt_params [ i ] . path ) ;
if ( node < 0 )
2020-02-18 09:54:05 +01:00
continue ;
2020-02-19 15:29:06 +01:00
if ( efi_enabled ( EFI_DBG ) )
pr_info ( " Getting UEFI parameters from %s in DT: \n " ,
dt_params [ i ] . path ) ;
for ( j = 0 ; j < ARRAY_SIZE ( target ) ; j + + ) {
const char * pname = dt_params [ i ] . params [ j ] ;
if ( ! efi_get_fdt_prop ( fdt , node , pname , name [ j ] ,
target [ j ] . var , target [ j ] . size ) )
continue ;
if ( ! j )
goto notfound ;
pr_err ( " Can't find property '%s' in DT! \n " , pname ) ;
return 0 ;
2020-02-18 09:54:05 +01:00
}
2020-02-19 15:29:06 +01:00
return systab ;
2020-02-18 09:54:05 +01:00
}
2020-02-19 15:29:06 +01:00
notfound :
pr_info ( " UEFI not found. \n " ) ;
2020-02-18 09:54:05 +01:00
return 0 ;
}