2019-02-02 10:41:15 +01:00
// SPDX-License-Identifier: GPL-2.0
2015-09-23 20:17:54 -07:00
/*
* Copyright ( C ) 2013 Linaro Ltd ; < roy . franz @ linaro . org >
*/
# include <linux/efi.h>
# include <asm/efi.h>
2017-04-04 17:09:09 +01:00
# include "efistub.h"
efi/libstub: arm: Print CPU boot mode and MMU state at boot
On 32-bit ARM, we may boot at HYP mode, or with the MMU and caches off
(or both), even though the EFI spec does not actually support this.
While booting at HYP mode is something we might tolerate, fiddling
with the caches is a more serious issue, as disabling the caches is
tricky to do safely from C code, and running without the Dcache makes
it impossible to support unaligned memory accesses, which is another
explicit requirement imposed by the EFI spec.
So take note of the CPU mode and MMU state in the EFI stub diagnostic
output so that we can easily diagnose any issues that may arise from
this. E.g.,
EFI stub: Entering in SVC mode with MMU enabled
Also, capture the CPSR and SCTLR system register values at EFI stub
entry, and after ExitBootServices() returns, and check whether the
MMU and Dcache were disabled at any point. If this is the case, a
diagnostic message like the following will be emitted:
efi: [Firmware Bug]: EFI stub was entered with MMU and Dcache disabled, please fix your firmware!
efi: CPSR at EFI stub entry : 0x600001d3
efi: SCTLR at EFI stub entry : 0x00c51838
efi: CPSR after ExitBootServices() : 0x600001d3
efi: SCTLR after ExitBootServices(): 0x00c50838
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
2020-06-07 15:41:35 +02:00
static efi_guid_t cpu_state_guid = LINUX_EFI_ARM_CPU_STATE_TABLE_GUID ;
struct efi_arm_entry_state * efi_entry_state ;
static void get_cpu_state ( u32 * cpsr , u32 * sctlr )
{
asm ( " mrs %0, cpsr " : " =r " ( * cpsr ) ) ;
if ( ( * cpsr & MODE_MASK ) = = HYP_MODE )
asm ( " mrc p15, 4, %0, c1, c0, 0 " : " =r " ( * sctlr ) ) ;
else
asm ( " mrc p15, 0, %0, c1, c0, 0 " : " =r " ( * sctlr ) ) ;
}
2019-12-24 16:10:19 +01:00
efi_status_t check_platform_features ( void )
2016-02-17 12:36:01 +00:00
{
efi/libstub: arm: Print CPU boot mode and MMU state at boot
On 32-bit ARM, we may boot at HYP mode, or with the MMU and caches off
(or both), even though the EFI spec does not actually support this.
While booting at HYP mode is something we might tolerate, fiddling
with the caches is a more serious issue, as disabling the caches is
tricky to do safely from C code, and running without the Dcache makes
it impossible to support unaligned memory accesses, which is another
explicit requirement imposed by the EFI spec.
So take note of the CPU mode and MMU state in the EFI stub diagnostic
output so that we can easily diagnose any issues that may arise from
this. E.g.,
EFI stub: Entering in SVC mode with MMU enabled
Also, capture the CPSR and SCTLR system register values at EFI stub
entry, and after ExitBootServices() returns, and check whether the
MMU and Dcache were disabled at any point. If this is the case, a
diagnostic message like the following will be emitted:
efi: [Firmware Bug]: EFI stub was entered with MMU and Dcache disabled, please fix your firmware!
efi: CPSR at EFI stub entry : 0x600001d3
efi: SCTLR at EFI stub entry : 0x00c51838
efi: CPSR after ExitBootServices() : 0x600001d3
efi: SCTLR after ExitBootServices(): 0x00c50838
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
2020-06-07 15:41:35 +02:00
efi_status_t status ;
u32 cpsr , sctlr ;
2016-02-17 12:36:01 +00:00
int block ;
efi/libstub: arm: Print CPU boot mode and MMU state at boot
On 32-bit ARM, we may boot at HYP mode, or with the MMU and caches off
(or both), even though the EFI spec does not actually support this.
While booting at HYP mode is something we might tolerate, fiddling
with the caches is a more serious issue, as disabling the caches is
tricky to do safely from C code, and running without the Dcache makes
it impossible to support unaligned memory accesses, which is another
explicit requirement imposed by the EFI spec.
So take note of the CPU mode and MMU state in the EFI stub diagnostic
output so that we can easily diagnose any issues that may arise from
this. E.g.,
EFI stub: Entering in SVC mode with MMU enabled
Also, capture the CPSR and SCTLR system register values at EFI stub
entry, and after ExitBootServices() returns, and check whether the
MMU and Dcache were disabled at any point. If this is the case, a
diagnostic message like the following will be emitted:
efi: [Firmware Bug]: EFI stub was entered with MMU and Dcache disabled, please fix your firmware!
efi: CPSR at EFI stub entry : 0x600001d3
efi: SCTLR at EFI stub entry : 0x00c51838
efi: CPSR after ExitBootServices() : 0x600001d3
efi: SCTLR after ExitBootServices(): 0x00c50838
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
2020-06-07 15:41:35 +02:00
get_cpu_state ( & cpsr , & sctlr ) ;
efi_info ( " Entering in %s mode with MMU %sabled \n " ,
( ( cpsr & MODE_MASK ) = = HYP_MODE ) ? " HYP " : " SVC " ,
( sctlr & 1 ) ? " en " : " dis " ) ;
status = efi_bs_call ( allocate_pool , EFI_LOADER_DATA ,
sizeof ( * efi_entry_state ) ,
( void * * ) & efi_entry_state ) ;
if ( status ! = EFI_SUCCESS ) {
efi_err ( " allocate_pool() failed \n " ) ;
return status ;
}
efi_entry_state - > cpsr_before_ebs = cpsr ;
efi_entry_state - > sctlr_before_ebs = sctlr ;
status = efi_bs_call ( install_configuration_table , & cpu_state_guid ,
efi_entry_state ) ;
if ( status ! = EFI_SUCCESS ) {
efi_err ( " install_configuration_table() failed \n " ) ;
goto free_state ;
}
2016-02-17 12:36:01 +00:00
/* non-LPAE kernels can run anywhere */
if ( ! IS_ENABLED ( CONFIG_ARM_LPAE ) )
return EFI_SUCCESS ;
/* LPAE kernels need compatible hardware */
block = cpuid_feature_extract ( CPUID_EXT_MMFR0 , 0 ) ;
if ( block < 5 ) {
2020-04-30 14:28:35 -04:00
efi_err ( " This LPAE kernel is not supported by your CPU \n " ) ;
efi/libstub: arm: Print CPU boot mode and MMU state at boot
On 32-bit ARM, we may boot at HYP mode, or with the MMU and caches off
(or both), even though the EFI spec does not actually support this.
While booting at HYP mode is something we might tolerate, fiddling
with the caches is a more serious issue, as disabling the caches is
tricky to do safely from C code, and running without the Dcache makes
it impossible to support unaligned memory accesses, which is another
explicit requirement imposed by the EFI spec.
So take note of the CPU mode and MMU state in the EFI stub diagnostic
output so that we can easily diagnose any issues that may arise from
this. E.g.,
EFI stub: Entering in SVC mode with MMU enabled
Also, capture the CPSR and SCTLR system register values at EFI stub
entry, and after ExitBootServices() returns, and check whether the
MMU and Dcache were disabled at any point. If this is the case, a
diagnostic message like the following will be emitted:
efi: [Firmware Bug]: EFI stub was entered with MMU and Dcache disabled, please fix your firmware!
efi: CPSR at EFI stub entry : 0x600001d3
efi: SCTLR at EFI stub entry : 0x00c51838
efi: CPSR after ExitBootServices() : 0x600001d3
efi: SCTLR after ExitBootServices(): 0x00c50838
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
2020-06-07 15:41:35 +02:00
status = EFI_UNSUPPORTED ;
goto drop_table ;
2016-02-17 12:36:01 +00:00
}
return EFI_SUCCESS ;
efi/libstub: arm: Print CPU boot mode and MMU state at boot
On 32-bit ARM, we may boot at HYP mode, or with the MMU and caches off
(or both), even though the EFI spec does not actually support this.
While booting at HYP mode is something we might tolerate, fiddling
with the caches is a more serious issue, as disabling the caches is
tricky to do safely from C code, and running without the Dcache makes
it impossible to support unaligned memory accesses, which is another
explicit requirement imposed by the EFI spec.
So take note of the CPU mode and MMU state in the EFI stub diagnostic
output so that we can easily diagnose any issues that may arise from
this. E.g.,
EFI stub: Entering in SVC mode with MMU enabled
Also, capture the CPSR and SCTLR system register values at EFI stub
entry, and after ExitBootServices() returns, and check whether the
MMU and Dcache were disabled at any point. If this is the case, a
diagnostic message like the following will be emitted:
efi: [Firmware Bug]: EFI stub was entered with MMU and Dcache disabled, please fix your firmware!
efi: CPSR at EFI stub entry : 0x600001d3
efi: SCTLR at EFI stub entry : 0x00c51838
efi: CPSR after ExitBootServices() : 0x600001d3
efi: SCTLR after ExitBootServices(): 0x00c50838
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
2020-06-07 15:41:35 +02:00
drop_table :
efi_bs_call ( install_configuration_table , & cpu_state_guid , NULL ) ;
free_state :
efi_bs_call ( free_pool , efi_entry_state ) ;
return status ;
}
void efi_handle_post_ebs_state ( void )
{
get_cpu_state ( & efi_entry_state - > cpsr_after_ebs ,
& efi_entry_state - > sctlr_after_ebs ) ;
2016-02-17 12:36:01 +00:00
}
2019-12-24 16:10:19 +01:00
efi_status_t handle_kernel_image ( unsigned long * image_addr ,
2015-09-23 20:17:54 -07:00
unsigned long * image_size ,
unsigned long * reserve_addr ,
unsigned long * reserve_size ,
2022-03-19 18:35:53 +01:00
efi_loaded_image_t * image ,
efi_handle_t image_handle )
2015-09-23 20:17:54 -07:00
{
efi/libstub: arm32: Use low allocation for the uncompressed kernel
Before commit
d0f9ca9be11f25ef ("ARM: decompressor: run decompressor in place if loaded via UEFI")
we were rather limited in the choice of base address for the uncompressed
kernel, as we were relying on the logic in the decompressor that blindly
rounds down the decompressor execution address to the next multiple of 128
MiB, and decompresses the kernel there. For this reason, we have a lot of
complicated memory region handling code, to ensure that this memory window
is available, even though it could be occupied by reserved regions or
other allocations that may or may not collide with the uncompressed image.
Today, we simply pass the target address for the decompressed image to the
decompressor directly, and so we can choose a suitable window just by
finding a 16 MiB aligned region, while taking TEXT_OFFSET and the region
for the swapper page tables into account.
So let's get rid of the complicated logic, and instead, use the existing
bottom up allocation routine to allocate a suitable window as low as
possible, and carve out a memory region that has the right properties.
Note that this removes any dependencies on the 'dram_base' argument to
handle_kernel_image(), and so this is removed as well. Given that this
was the only remaining use of dram_base, the code that produces it is
removed entirely as well.
Reviewed-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Tested-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-09-09 17:11:50 +03:00
const int slack = TEXT_OFFSET - 5 * PAGE_SIZE ;
int alloc_size = MAX_UNCOMP_KERNEL_SIZE + EFI_PHYS_ALIGN ;
unsigned long alloc_base , kernel_base ;
2015-09-23 20:17:54 -07:00
efi_status_t status ;
2019-10-29 18:37:53 +01:00
/*
efi/libstub: arm32: Use low allocation for the uncompressed kernel
Before commit
d0f9ca9be11f25ef ("ARM: decompressor: run decompressor in place if loaded via UEFI")
we were rather limited in the choice of base address for the uncompressed
kernel, as we were relying on the logic in the decompressor that blindly
rounds down the decompressor execution address to the next multiple of 128
MiB, and decompresses the kernel there. For this reason, we have a lot of
complicated memory region handling code, to ensure that this memory window
is available, even though it could be occupied by reserved regions or
other allocations that may or may not collide with the uncompressed image.
Today, we simply pass the target address for the decompressed image to the
decompressor directly, and so we can choose a suitable window just by
finding a 16 MiB aligned region, while taking TEXT_OFFSET and the region
for the swapper page tables into account.
So let's get rid of the complicated logic, and instead, use the existing
bottom up allocation routine to allocate a suitable window as low as
possible, and carve out a memory region that has the right properties.
Note that this removes any dependencies on the 'dram_base' argument to
handle_kernel_image(), and so this is removed as well. Given that this
was the only remaining use of dram_base, the code that produces it is
removed entirely as well.
Reviewed-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Tested-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-09-09 17:11:50 +03:00
* Allocate space for the decompressed kernel as low as possible .
* The region should be 16 MiB aligned , but the first ' slack ' bytes
* are not used by Linux , so we allow those to be occupied by the
* firmware .
2019-10-29 18:37:53 +01:00
*/
efi/libstub: arm32: Use low allocation for the uncompressed kernel
Before commit
d0f9ca9be11f25ef ("ARM: decompressor: run decompressor in place if loaded via UEFI")
we were rather limited in the choice of base address for the uncompressed
kernel, as we were relying on the logic in the decompressor that blindly
rounds down the decompressor execution address to the next multiple of 128
MiB, and decompresses the kernel there. For this reason, we have a lot of
complicated memory region handling code, to ensure that this memory window
is available, even though it could be occupied by reserved regions or
other allocations that may or may not collide with the uncompressed image.
Today, we simply pass the target address for the decompressed image to the
decompressor directly, and so we can choose a suitable window just by
finding a 16 MiB aligned region, while taking TEXT_OFFSET and the region
for the swapper page tables into account.
So let's get rid of the complicated logic, and instead, use the existing
bottom up allocation routine to allocate a suitable window as low as
possible, and carve out a memory region that has the right properties.
Note that this removes any dependencies on the 'dram_base' argument to
handle_kernel_image(), and so this is removed as well. Given that this
was the only remaining use of dram_base, the code that produces it is
removed entirely as well.
Reviewed-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Tested-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-09-09 17:11:50 +03:00
status = efi_low_alloc_above ( alloc_size , EFI_PAGE_SIZE , & alloc_base , 0x0 ) ;
2015-09-23 20:17:54 -07:00
if ( status ! = EFI_SUCCESS ) {
2020-04-30 14:28:35 -04:00
efi_err ( " Unable to allocate memory for uncompressed kernel. \n " ) ;
2015-09-23 20:17:54 -07:00
return status ;
}
efi/libstub: arm32: Use low allocation for the uncompressed kernel
Before commit
d0f9ca9be11f25ef ("ARM: decompressor: run decompressor in place if loaded via UEFI")
we were rather limited in the choice of base address for the uncompressed
kernel, as we were relying on the logic in the decompressor that blindly
rounds down the decompressor execution address to the next multiple of 128
MiB, and decompresses the kernel there. For this reason, we have a lot of
complicated memory region handling code, to ensure that this memory window
is available, even though it could be occupied by reserved regions or
other allocations that may or may not collide with the uncompressed image.
Today, we simply pass the target address for the decompressed image to the
decompressor directly, and so we can choose a suitable window just by
finding a 16 MiB aligned region, while taking TEXT_OFFSET and the region
for the swapper page tables into account.
So let's get rid of the complicated logic, and instead, use the existing
bottom up allocation routine to allocate a suitable window as low as
possible, and carve out a memory region that has the right properties.
Note that this removes any dependencies on the 'dram_base' argument to
handle_kernel_image(), and so this is removed as well. Given that this
was the only remaining use of dram_base, the code that produces it is
removed entirely as well.
Reviewed-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Tested-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-09-09 17:11:50 +03:00
if ( ( alloc_base % EFI_PHYS_ALIGN ) > slack ) {
/*
* More than ' slack ' bytes are already occupied at the base of
* the allocation , so we need to advance to the next 16 MiB block .
*/
kernel_base = round_up ( alloc_base , EFI_PHYS_ALIGN ) ;
efi_info ( " Free memory starts at 0x%lx, setting kernel_base to 0x%lx \n " ,
alloc_base , kernel_base ) ;
} else {
kernel_base = round_down ( alloc_base , EFI_PHYS_ALIGN ) ;
}
* reserve_addr = kernel_base + slack ;
* reserve_size = MAX_UNCOMP_KERNEL_SIZE ;
/* now free the parts that we will not use */
if ( * reserve_addr > alloc_base ) {
efi_bs_call ( free_pages , alloc_base ,
( * reserve_addr - alloc_base ) / EFI_PAGE_SIZE ) ;
alloc_size - = * reserve_addr - alloc_base ;
}
efi_bs_call ( free_pages , * reserve_addr + MAX_UNCOMP_KERNEL_SIZE ,
( alloc_size - MAX_UNCOMP_KERNEL_SIZE ) / EFI_PAGE_SIZE ) ;
* image_addr = kernel_base + TEXT_OFFSET ;
2020-04-13 18:21:35 +02:00
* image_size = 0 ;
efi/libstub: arm32: Use low allocation for the uncompressed kernel
Before commit
d0f9ca9be11f25ef ("ARM: decompressor: run decompressor in place if loaded via UEFI")
we were rather limited in the choice of base address for the uncompressed
kernel, as we were relying on the logic in the decompressor that blindly
rounds down the decompressor execution address to the next multiple of 128
MiB, and decompresses the kernel there. For this reason, we have a lot of
complicated memory region handling code, to ensure that this memory window
is available, even though it could be occupied by reserved regions or
other allocations that may or may not collide with the uncompressed image.
Today, we simply pass the target address for the decompressed image to the
decompressor directly, and so we can choose a suitable window just by
finding a 16 MiB aligned region, while taking TEXT_OFFSET and the region
for the swapper page tables into account.
So let's get rid of the complicated logic, and instead, use the existing
bottom up allocation routine to allocate a suitable window as low as
possible, and carve out a memory region that has the right properties.
Note that this removes any dependencies on the 'dram_base' argument to
handle_kernel_image(), and so this is removed as well. Given that this
was the only remaining use of dram_base, the code that produces it is
removed entirely as well.
Reviewed-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Tested-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-09-09 17:11:50 +03:00
efi_debug ( " image addr == 0x%lx, reserve_addr == 0x%lx \n " ,
* image_addr , * reserve_addr ) ;
2015-09-23 20:17:54 -07:00
return EFI_SUCCESS ;
}