@ -729,32 +729,68 @@ fail:
* need to create one ourselves ( usually the bootloader would create
* one for us ) .
*/
static efi_status_t make_boot_params ( struct boot_params * boot_params ,
efi_loaded_image_t * image ,
void * handle )
struct boot_params * make_boot_params ( void * handle , efi_system_table_t * _table )
{
struct efi_info * efi = & boot_params - > efi_info ;
struct apm_bios_info * bi = & boot_params - > apm_bios_info ;
struct sys_desc_table * sdt = & boot_params - > sys_desc_table ;
struct e820entry * e820_map = & boot_params - > e820_map [ 0 ] ;
struct e820entry * prev = NULL ;
struct setup_header * hdr = & boot_params - > hdr ;
unsigned long size , key , desc_size , _size ;
efi_memory_desc_t * mem_map ;
void * options = image - > load_options ;
u32 load_options_size = image - > load_options_size / 2 ; /* ASCII */
struct boot_params * boot_params ;
struct sys_desc_table * sdt ;
struct apm_bios_info * bi ;
struct setup_header * hdr ;
struct efi_info * efi ;
efi_loaded_image_t * image ;
void * options ;
u32 load_options_size ;
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID ;
int options_size = 0 ;
efi_status_t status ;
__u32 desc_version ;
unsigned long cmdline ;
u8 nr_entries ;
u16 * s2 ;
u8 * s1 ;
int i ;
sys_table = _table ;
/* Check if we were booted by the EFI firmware */
if ( sys_table - > hdr . signature ! = EFI_SYSTEM_TABLE_SIGNATURE )
return NULL ;
status = efi_call_phys3 ( sys_table - > boottime - > handle_protocol ,
handle , & proto , ( void * ) & image ) ;
if ( status ! = EFI_SUCCESS ) {
efi_printk ( " Failed to get handle for LOADED_IMAGE_PROTOCOL \n " ) ;
return NULL ;
}
status = low_alloc ( 0x4000 , 1 , ( unsigned long * ) & boot_params ) ;
if ( status ! = EFI_SUCCESS ) {
efi_printk ( " Failed to alloc lowmem for boot params \n " ) ;
return NULL ;
}
memset ( boot_params , 0x0 , 0x4000 ) ;
hdr = & boot_params - > hdr ;
efi = & boot_params - > efi_info ;
bi = & boot_params - > apm_bios_info ;
sdt = & boot_params - > sys_desc_table ;
/* Copy the second sector to boot_params */
memcpy ( & hdr - > jump , image - > image_base + 512 , 512 ) ;
/*
* Fill out some of the header fields ourselves because the
* EFI firmware loader doesn ' t load the first sector .
*/
hdr - > root_flags = 1 ;
hdr - > vid_mode = 0xffff ;
hdr - > boot_flag = 0xAA55 ;
hdr - > code32_start = ( __u64 ) ( unsigned long ) image - > image_base ;
hdr - > type_of_loader = 0x21 ;
/* Convert unicode cmdline to ascii */
options = image - > load_options ;
load_options_size = image - > load_options_size / 2 ; /* ASCII */
cmdline = 0 ;
s2 = ( u16 * ) options ;
@ -791,18 +827,36 @@ static efi_status_t make_boot_params(struct boot_params *boot_params,
hdr - > ramdisk_image = 0 ;
hdr - > ramdisk_size = 0 ;
status = handle_ramdisks ( image , hdr ) ;
if ( status ! = EFI_SUCCESS )
goto free_cmdline ;
setup_graphics ( boot_params ) ;
/* Clear APM BIOS info */
memset ( bi , 0 , sizeof ( * bi ) ) ;
memset ( sdt , 0 , sizeof ( * sdt ) ) ;
memcpy ( & efi - > efi_loader_signature , EFI_LOADER_SIGNATURE , sizeof ( __u32 ) ) ;
status = handle_ramdisks ( image , hdr ) ;
if ( status ! = EFI_SUCCESS )
goto fail2 ;
return boot_params ;
fail2 :
if ( options_size )
low_free ( options_size , hdr - > cmd_line_ptr ) ;
fail :
low_free ( 0x4000 , ( unsigned long ) boot_params ) ;
return NULL ;
}
static efi_status_t exit_boot ( struct boot_params * boot_params ,
void * handle )
{
struct efi_info * efi = & boot_params - > efi_info ;
struct e820entry * e820_map = & boot_params - > e820_map [ 0 ] ;
struct e820entry * prev = NULL ;
unsigned long size , key , desc_size , _size ;
efi_memory_desc_t * mem_map ;
efi_status_t status ;
__u32 desc_version ;
u8 nr_entries ;
int i ;
size = sizeof ( * mem_map ) * 32 ;
@ -811,7 +865,7 @@ again:
_size = size ;
status = low_alloc ( size , 1 , ( unsigned long * ) & mem_map ) ;
if ( status ! = EFI_SUCCESS )
goto free_cmdline ;
return status ;
status = efi_call_phys5 ( sys_table - > boottime - > get_memory_map , & size ,
mem_map , & key , & desc_size , & desc_version ) ;
@ -823,6 +877,7 @@ again:
if ( status ! = EFI_SUCCESS )
goto free_mem_map ;
memcpy ( & efi - > efi_loader_signature , EFI_LOADER_SIGNATURE , sizeof ( __u32 ) ) ;
efi - > efi_systab = ( unsigned long ) sys_table ;
efi - > efi_memdesc_size = desc_size ;
efi - > efi_memdesc_version = desc_version ;
@ -906,61 +961,13 @@ again:
free_mem_map :
low_free ( _size , ( unsigned long ) mem_map ) ;
free_cmdline :
if ( options_size )
low_free ( options_size , hdr - > cmd_line_ptr ) ;
fail :
return status ;
}
/*
* On success we return a pointer to a boot_params structure , and NULL
* on failure .
*/
struct boot_params * efi_main ( void * handle , efi_system_table_t * _table )
static efi_status_t relocate_kernel ( struct setup_header * hdr )
{
struct boot_params * boot_params ;
unsigned long start , nr_pages ;
struct desc_ptr * gdt , * idt ;
efi_loaded_image_t * image ;
struct setup_header * hdr ;
efi_status_t status ;
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID ;
struct desc_struct * desc ;
sys_table = _table ;
/* Check if we were booted by the EFI firmware */
if ( sys_table - > hdr . signature ! = EFI_SYSTEM_TABLE_SIGNATURE )
goto fail ;
status = efi_call_phys3 ( sys_table - > boottime - > handle_protocol ,
handle , & proto , ( void * ) & image ) ;
if ( status ! = EFI_SUCCESS ) {
efi_printk ( " Failed to get handle for LOADED_IMAGE_PROTOCOL \n " ) ;
goto fail ;
}
status = low_alloc ( 0x4000 , 1 , ( unsigned long * ) & boot_params ) ;
if ( status ! = EFI_SUCCESS ) {
efi_printk ( " Failed to alloc lowmem for boot params \n " ) ;
goto fail ;
}
memset ( boot_params , 0x0 , 0x4000 ) ;
hdr = & boot_params - > hdr ;
/* Copy the second sector to boot_params */
memcpy ( & hdr - > jump , image - > image_base + 512 , 512 ) ;
/*
* Fill out some of the header fields ourselves because the
* EFI firmware loader doesn ' t load the first sector .
*/
hdr - > root_flags = 1 ;
hdr - > vid_mode = 0xffff ;
hdr - > boot_flag = 0xAA55 ;
/*
* The EFI firmware loader could have placed the kernel image
@ -978,16 +985,40 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table)
if ( status ! = EFI_SUCCESS ) {
status = low_alloc ( hdr - > init_size , hdr - > kernel_alignment ,
& start ) ;
if ( status ! = EFI_SUCCESS ) {
if ( status ! = EFI_SUCCESS )
efi_printk ( " Failed to alloc mem for kernel \n " ) ;
goto fail ;
}
}
if ( status = = EFI_SUCCESS )
memcpy ( ( void * ) start , ( void * ) ( unsigned long ) hdr - > code32_start ,
hdr - > init_size ) ;
hdr - > pref_address = hdr - > code32_start ;
hdr - > code32_start = ( __u32 ) start ;
hdr - > pref_address = ( __u64 ) ( unsigned long ) image - > image_base ;
memcpy ( ( void * ) start , image - > image_base , image - > image_size ) ;
return status ;
}
/*
* On success we return a pointer to a boot_params structure , and NULL
* on failure .
*/
struct boot_params * efi_main ( void * handle , efi_system_table_t * _table ,
struct boot_params * boot_params )
{
struct desc_ptr * gdt , * idt ;
efi_loaded_image_t * image ;
struct setup_header * hdr = & boot_params - > hdr ;
efi_status_t status ;
struct desc_struct * desc ;
sys_table = _table ;
/* Check if we were booted by the EFI firmware */
if ( sys_table - > hdr . signature ! = EFI_SYSTEM_TABLE_SIGNATURE )
goto fail ;
setup_graphics ( boot_params ) ;
status = efi_call_phys3 ( sys_table - > boottime - > allocate_pool ,
EFI_LOADER_DATA , sizeof ( * gdt ) ,
@ -1015,7 +1046,18 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table)
idt - > size = 0 ;
idt - > address = 0 ;
status = make_boot_params ( boot_params , image , handle ) ;
/*
* If the kernel isn ' t already loaded at the preferred load
* address , relocate it .
*/
if ( hdr - > pref_address ! = hdr - > code32_start ) {
status = relocate_kernel ( hdr ) ;
if ( status ! = EFI_SUCCESS )
goto fail ;
}
status = exit_boot ( boot_params , handle ) ;
if ( status ! = EFI_SUCCESS )
goto fail ;