efi capsule loader fixes
Subsystems (3)
Ard Biesheuvel
maintainercover efi capsule loader fixes
A couple of fixes for the EFI capsule loader. Patch #1 switches from kmap() to kmap_atomic(). Patch #2 adds cache maintenance of the scatter gather list entries passed to UpdateCapsule.
Ard Biesheuvel (2):
efi: capsule: use atomic kmap for transient sglist mappings
efi: capsule: clean scatter-gather entries from the D-cache
arch/arm/include/asm/efi.h | 5 +++++ arch/arm64/include/asm/efi.h | 5 +++++ drivers/firmware/efi/capsule.c | 16 ++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-)
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 1/2 efi: capsule: use atomic kmap for transient sglist mappings
Don't use the heavy-weight kmap() API to create short-lived mappings of the scatter-gather list entries that are released as soon as the entries are written. Instead, use kmap_atomic(), which is more suited to this purpose.
--- drivers/firmware/efi/capsule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/efi/capsule.c +2 -2
@@ -244,7 +244,7 @@ int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)for (i =0 ; i < sg_count; i++) {efi_capsule_block_desc_t *sglist; - sglist =kmap (sg_pages[i]); + sglist =kmap_atomic (sg_pages[i]);for (j =0 ; j <SGLIST_PER_PAGE && count >0 ; j++) { u64 sz = min_t(u64, imagesize,
@@ -265,7 +265,7 @@ int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)else sglist[j].data =page_to_phys (sg_pages[i +1 ]); -kunmap (sg_pages[i]); +kunmap_atomic (sglist); }mutex_lock (&capsule_mutex);
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 2/2 efi: capsule: clean scatter-gather entries from the D-cache
In reply to Ard BiesheuvelThe UEFI spec 2.9 has recently been updated to include a requirement that scatter-gather lists passed to UpdateCapsule() should be cleaned from the D-cache to ensure that they are visible to the CPU after a warm reboot before it enables the MMU. On ARM and arm64 systems, this implies a D-cache clean by virtual address to the point of coherency.
--- arch/arm/include/asm/efi.h | 5 +++++ arch/arm64/include/asm/efi.h | 5 +++++ drivers/firmware/efi/capsule.c | 12 ++++++++++++ 3 files changed, 22 insertions(+)
arch/arm/include/asm/efi.h +5 -0
@@ -93,4 +93,9 @@ struct efi_arm_entry_state { u32 sctlr_after_ebs; }; +static inline void efi_capsule_flush_cache_range (void *addr,int size) +{ +__cpuc_flush_dcache_area (addr, size); +} +#endif /* _ASM_ARM_EFI_H */
arch/arm64/include/asm/efi.h +5 -0
@@ -141,4 +141,9 @@ static inline void efi_set_pgd(struct mm_struct *mm)void efi_virtmap_load (void );void efi_virtmap_unload (void ); +static inline void efi_capsule_flush_cache_range (void *addr,int size) +{ +__flush_dcache_area (addr, size); +} +#endif /* _ASM_EFI_H */
drivers/firmware/efi/capsule.c +12 -0
@@ -12,6 +12,7 @@#include <linux/highmem.h> #include <linux/efi.h> #include <linux/vmalloc.h> +#include <asm/efi.h> #include <asm/io.h> typedef struct {
@@ -265,6 +266,17 @@ int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)else sglist[j].data =page_to_phys (sg_pages[i +1 ]); +#if defined(CONFIG_ARM ) || defined(CONFIG_ARM64 ) +/* +* At runtime, the firmware has no way to find out where the +* sglist elements are mapped, if they are mapped in the first +* place. Therefore, on architectures that can only perform +* cache maintenance by virtual address, the firmware is unable +* to perform this maintenance, and so it is up to the OS to do +* it instead. +*/ +efi_capsule_flush_cache_range (sglist,PAGE_SIZE ); +#endif kunmap_atomic (sglist); }
Signature · 1 line
2.17.1