@ -22,97 +22,14 @@ DECLARE_GLOBAL_DATA_PTR;
static uint8_t efi_obj_list_initalized ;
static uint8_t efi_obj_list_initalized ;
/*
static struct efi_device_path * bootefi_image_path ;
* When booting using the " bootefi " command , we don ' t know which
static struct efi_device_path * bootefi_device_path ;
* physical device the file came from . So we create a pseudo - device
* called " bootefi " with the device path / bootefi .
*
* In addition to the originating device we also declare the file path
* of " bootefi " based loads to be / bootefi .
*/
static struct efi_device_path_file_path bootefi_image_path [ ] = {
{
. dp . type = DEVICE_PATH_TYPE_MEDIA_DEVICE ,
. dp . sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH ,
. dp . length = sizeof ( bootefi_image_path [ 0 ] ) ,
. str = { ' b ' , ' o ' , ' o ' , ' t ' , ' e ' , ' f ' , ' i ' } ,
} , {
. dp . type = DEVICE_PATH_TYPE_END ,
. dp . sub_type = DEVICE_PATH_SUB_TYPE_END ,
. dp . length = sizeof ( bootefi_image_path [ 0 ] ) ,
}
} ;
static struct efi_device_path_file_path bootefi_device_path [ ] = {
{
. dp . type = DEVICE_PATH_TYPE_MEDIA_DEVICE ,
. dp . sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH ,
. dp . length = sizeof ( bootefi_image_path [ 0 ] ) ,
. str = { ' b ' , ' o ' , ' o ' , ' t ' , ' e ' , ' f ' , ' i ' } ,
} , {
. dp . type = DEVICE_PATH_TYPE_END ,
. dp . sub_type = DEVICE_PATH_SUB_TYPE_END ,
. dp . length = sizeof ( bootefi_image_path [ 0 ] ) ,
}
} ;
/* The EFI loaded_image interface for the image executed via "bootefi" */
static struct efi_loaded_image loaded_image_info = {
. device_handle = bootefi_device_path ,
. file_path = bootefi_image_path ,
} ;
/* The EFI object struct for the image executed via "bootefi" */
static struct efi_object loaded_image_info_obj = {
. handle = & loaded_image_info ,
. protocols = {
{
/*
* When asking for the loaded_image interface , just
* return handle which points to loaded_image_info
*/
. guid = & efi_guid_loaded_image ,
. protocol_interface = & loaded_image_info ,
} ,
{
/*
* When asking for the device path interface , return
* bootefi_device_path
*/
. guid = & efi_guid_device_path ,
. protocol_interface = bootefi_device_path ,
} ,
{
. guid = & efi_guid_console_control ,
. protocol_interface = ( void * ) & efi_console_control
} ,
{
. guid = & efi_guid_device_path_to_text_protocol ,
. protocol_interface = ( void * ) & efi_device_path_to_text
} ,
} ,
} ;
/* The EFI object struct for the device the "bootefi" image was loaded from */
static struct efi_object bootefi_device_obj = {
. handle = bootefi_device_path ,
. protocols = {
{
/* When asking for the device path interface, return
* bootefi_device_path */
. guid = & efi_guid_device_path ,
. protocol_interface = bootefi_device_path
}
} ,
} ;
/* Initialize and populate EFI object list */
/* Initialize and populate EFI object list */
static void efi_init_obj_list ( void )
static void efi_init_obj_list ( void )
{
{
efi_obj_list_initalized = 1 ;
efi_obj_list_initalized = 1 ;
list_add_tail ( & loaded_image_info_obj . link , & efi_obj_list ) ;
list_add_tail ( & bootefi_device_obj . link , & efi_obj_list ) ;
efi_console_register ( ) ;
efi_console_register ( ) ;
# ifdef CONFIG_PARTITIONS
# ifdef CONFIG_PARTITIONS
efi_disk_register ( ) ;
efi_disk_register ( ) ;
@ -121,13 +38,7 @@ static void efi_init_obj_list(void)
efi_gop_register ( ) ;
efi_gop_register ( ) ;
# endif
# endif
# ifdef CONFIG_NET
# ifdef CONFIG_NET
void * nethandle = loaded_image_info . device_handle ;
efi_net_register ( ) ;
efi_net_register ( & nethandle ) ;
if ( ! memcmp ( bootefi_device_path [ 0 ] . str , " N \0 e \0 t " , 6 ) )
loaded_image_info . device_handle = nethandle ;
else
loaded_image_info . device_handle = bootefi_device_path ;
# endif
# endif
# ifdef CONFIG_GENERATE_SMBIOS_TABLE
# ifdef CONFIG_GENERATE_SMBIOS_TABLE
efi_smbios_register ( ) ;
efi_smbios_register ( ) ;
@ -210,14 +121,27 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)(
* Load an EFI payload into a newly allocated piece of memory , register all
* Load an EFI payload into a newly allocated piece of memory , register all
* EFI objects it would want to access and jump to it .
* EFI objects it would want to access and jump to it .
*/
*/
static unsigned long do_bootefi_exec ( void * efi , void * fdt )
static unsigned long do_bootefi_exec ( void * efi , void * fdt ,
struct efi_device_path * device_path ,
struct efi_device_path * image_path )
{
{
struct efi_loaded_image loaded_image_info = { } ;
struct efi_object loaded_image_info_obj = { } ;
ulong ret ;
ulong ( * entry ) ( void * image_handle , struct efi_system_table * st )
ulong ( * entry ) ( void * image_handle , struct efi_system_table * st )
asmlinkage ;
asmlinkage ;
ulong fdt_pages , fdt_size , fdt_start , fdt_end ;
ulong fdt_pages , fdt_size , fdt_start , fdt_end ;
const efi_guid_t fdt_guid = EFI_FDT_GUID ;
const efi_guid_t fdt_guid = EFI_FDT_GUID ;
bootm_headers_t img = { 0 } ;
bootm_headers_t img = { 0 } ;
/* Initialize and populate EFI object list */
if ( ! efi_obj_list_initalized )
efi_init_obj_list ( ) ;
efi_setup_loaded_image ( & loaded_image_info , & loaded_image_info_obj ,
device_path , image_path ) ;
/*
/*
* gd lives in a fixed register which may get clobbered while we execute
* gd lives in a fixed register which may get clobbered while we execute
* the payload . So save it here and restore it on every callback entry
* the payload . So save it here and restore it on every callback entry
@ -252,18 +176,18 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
/* Load the EFI payload */
/* Load the EFI payload */
entry = efi_load_pe ( efi , & loaded_image_info ) ;
entry = efi_load_pe ( efi , & loaded_image_info ) ;
if ( ! entry )
if ( ! entry ) {
return - ENOENT ;
ret = - ENOENT ;
goto exit ;
/* Initialize and populate EFI object list */
}
if ( ! efi_obj_list_initalized )
efi_init_obj_list ( ) ;
/* Call our payload! */
/* Call our payload! */
debug ( " %s:%d Jumping to 0x%lx \n " , __func__ , __LINE__ , ( long ) entry ) ;
debug ( " %s:%d Jumping to 0x%lx \n " , __func__ , __LINE__ , ( long ) entry ) ;
if ( setjmp ( & loaded_image_info . exit_jmp ) ) {
if ( setjmp ( & loaded_image_info . exit_jmp ) ) {
return loaded_image_info . exit_status ;
ret = loaded_image_info . exit_status ;
EFI_EXIT ( ret ) ;
goto exit ;
}
}
# ifdef CONFIG_ARM64
# ifdef CONFIG_ARM64
@ -282,7 +206,13 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
}
}
# endif
# endif
return efi_do_enter ( & loaded_image_info , & systab , entry ) ;
ret = efi_do_enter ( & loaded_image_info , & systab , entry ) ;
exit :
/* image has returned, loaded-image obj goes *poof*: */
list_del ( & loaded_image_info_obj . link ) ;
return ret ;
}
}
/* Interpreter command to boot an arbitrary EFI image from memory */
/* Interpreter command to boot an arbitrary EFI image from memory */
@ -334,7 +264,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
printf ( " ## Starting EFI application at %08lx ... \n " , addr ) ;
printf ( " ## Starting EFI application at %08lx ... \n " , addr ) ;
r = do_bootefi_exec ( ( void * ) addr , ( void * ) fdt_addr ) ;
r = do_bootefi_exec ( ( void * ) addr , ( void * ) fdt_addr ,
bootefi_device_path , bootefi_image_path ) ;
printf ( " ## Application terminated, r = %lu \n " ,
printf ( " ## Application terminated, r = %lu \n " ,
r & ~ EFI_ERROR_MASK ) ;
r & ~ EFI_ERROR_MASK ) ;
@ -367,58 +298,44 @@ U_BOOT_CMD(
bootefi_help_text
bootefi_help_text
) ;
) ;
void efi_set_bootdev ( const char * dev , const char * devnr , const char * path )
static int parse_partnum ( const char * devnr )
{
{
__maybe_unused struct blk_desc * desc ;
const char * str = strchr ( devnr , ' : ' ) ;
char devname [ 32 ] = { 0 } ; /* dp->str is u16[32] long */
if ( str ) {
char * colon , * s ;
str + + ;
return simple_strtoul ( str , NULL , 16 ) ;
# if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION)
desc = blk_get_dev ( dev , simple_strtol ( devnr , NULL , 10 ) ) ;
# endif
# ifdef CONFIG_BLK
if ( desc ) {
snprintf ( devname , sizeof ( devname ) , " %s " , desc - > bdev - > name ) ;
} else
# endif
{
/* Assemble the condensed device name we use in efi_disk.c */
snprintf ( devname , sizeof ( devname ) , " %s%s " , dev , devnr ) ;
}
}
return 0 ;
}
colon = strchr ( devname , ' : ' ) ;
void efi_set_bootdev ( const char * dev , const char * devnr , const char * path )
{
# if CONFIG_IS_ENABLED(ISO_PARTITION)
char filename [ 32 ] = { 0 } ; /* dp->str is u16[32] long */
/* For ISOs we create partition block devices */
char * s ;
if ( desc & & ( desc - > type ! = DEV_TYPE_UNKNOWN ) & &
( desc - > part_type = = PART_TYPE_ISO ) ) {
if ( ! colon )
snprintf ( devname , sizeof ( devname ) , " %s:1 " , devname ) ;
colon = NULL ;
if ( strcmp ( dev , " Net " ) ) {
}
struct blk_desc * desc ;
# endif
int part ;
if ( colon )
desc = blk_get_dev ( dev , simple_strtol ( devnr , NULL , 10 ) ) ;
* colon = ' \0 ' ;
part = parse_partnum ( devnr ) ;
/* Patch bootefi_device_path to the target device */
bootefi_device_path = efi_dp_from_part ( desc , part ) ;
memset ( bootefi_device_path [ 0 ] . str , 0 , sizeof ( bootefi_device_path [ 0 ] . str ) ) ;
} else {
ascii2unicode ( bootefi_device_path [ 0 ] . str , devname ) ;
# ifdef CONFIG_NET
bootefi_device_path = efi_dp_from_eth ( ) ;
# endif
}
/* Patch bootefi_image_path to the target file path */
memset ( bootefi_image_path [ 0 ] . str , 0 , sizeof ( bootefi_image_path [ 0 ] . str ) ) ;
if ( strcmp ( dev , " Net " ) ) {
if ( strcmp ( dev , " Net " ) ) {
/* Add leading / to fs paths, because they're absolute */
/* Add leading / to fs paths, because they're absolute */
snprintf ( dev name, sizeof ( dev name) , " /%s " , path ) ;
snprintf ( file name, sizeof ( file name) , " /%s " , path ) ;
} else {
} else {
snprintf ( dev name, sizeof ( dev name) , " %s " , path ) ;
snprintf ( file name, sizeof ( file name) , " %s " , path ) ;
}
}
/* DOS style file path: */
/* DOS style file path: */
s = dev name;
s = file name;
while ( ( s = strchr ( s , ' / ' ) ) )
while ( ( s = strchr ( s , ' / ' ) ) )
* s + + = ' \\ ' ;
* s + + = ' \\ ' ;
ascii2unicode ( bootefi_image_path [ 0 ] . str , dev name) ;
bootefi_image_path = efi_dp_from_file ( NULL , 0 , file name) ;
}
}