EFI changes for v4.7
Subsystems (8)
Folks, here's the queue of EFI material for v4.7. This is probably the biggest EFI pull ever sent, and there quite a few different topics covered.
On the plus side the majority of new features (EFI Memory Attribute tables, EFI capsules, GOP framebuffer) are basically architecture independent, and some of the existing architecture-specific code has been generalised and moved to drivers/firmware/efi.
The following changes since commit c3b46c73264b03000d1e18b22f5caf63332547c9:
Linux 4.6-rc4 (2016-04-17 19:13:32 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git tags/efi-next
for you to fetch changes up to 4716a27d61ca3e3201d3201a6ee073da24902613:
efi/runtime-wrappers: Remove ARCH_EFI_IRQ_FLAGS_MASK ifdef (2016-04-25 16:53:59 +0100)
----------------------------------------------------------------
* Drop the unused EFI_SYSTEM_TABLES efi.flags bit and ensure the ARM/arm64 EFI System Table mapping is read-only - Ard Biesheuvel
* Add a comment to explain that one of the code paths in the x86/pat code is only executed for EFI boot - Matt Fleming
* Improve Secure Boot status checks on arm64 and handle unexpected errors - Linn Crosetto
* Remove the global EFI memory map variable 'memmap' as the same information is already available in efi::memmap - Matt Fleming
* EFI Memory Attribute table support for ARM/arm64 - Ard Biesheuvel
* EFI GOP framebuffer support for ARM/arm64 - Ard Biesheuvel
* EFI Bootloader Control driver for storing reboot(2) data in EFI variables for consumption by bootloaders - Jeremy Compostella
* Core EFI capsule support - Matt Fleming
* EFI capsule char driver - Kweh, Hock Leong
* EFI memory map code unification for ARM and arm64 - Ard Biesheuvel
* Add generic EFI support for detecting when firmware corrupts cpu status register bits (like IRQ flags) when performing EFI runtime service calls - Mark Rutland
----------------------------------------------------------------
Ard Biesheuvel (19):
efi: Get rid of EFI_SYSTEM_TABLES status bit
efi/arm*: Drop writable mapping of the UEFI System table
efi: Check EFI_MEMORY_DESCRIPTOR version explicitly efi/arm*: Use memremap() to create the persistent memmap mapping
ARM: efi: Apply strict permissons for UEFI Runtime Services regions
arm64: efi: Apply strict permissons for UEFI Runtime Services regions
efi: Add support for the EFI_MEMORY_ATTRIBUTES_TABLE config table
efi: Implement generic support for the Memory Attributes table efi/arm*: Take the Memory Attributes table into account x86/efi: Prepare GOP handling code for reuse as generic code efi/libstub: Move Graphics Output Protocol handling to generic code x86/efi: efifb: Move DMI based quirks handling out of generic code
efifb: Use builtin_platform_driver and drop unused includes arm64/efi: libstub: Make screen_info accessible to the UEFI stub efi/arm: libstub: Make screen_info accessible to the UEFI stub efi/arm*: libstub: Wire up GOP protocol to struct screen_info efi/arm*: Wire up struct screen_info to efi-framebuffer platform device
efifb: Enable the efi-framebuffer platform driver for ARM and arm64 efi/arm-init: Reserve rather than unmap the memory map for ARM as well
Compostella, Jeremy (1):
efibc: EFI Bootloader Control
Kweh, Hock Leong (1):
efi: A misc char interface to update EFI firmware
Linn Crosetto (2):
efi/arm64: Report unexpected errors when determining Secure Boot status efi/arm64: Check SetupMode when determining Secure Boot status
Mark Rutland (10):
efi/runtime-wrappers: Add {__,}efi_call_virt templates arm64/efi: Move to generic {__,}efi_call_virt arm/efi: Move to generic {__,}efi_call_virt x86/efi: Move to generic {__,}efi_call_virt efi/runtime-wrappers: Remove redundant ifdefs efi/runtime-wrappers: Detect firmware irq flag corruption arm64/efi: Enable runtime call flag checking arm/efi: Enable runtime call flag checking x86/efi: Enable runtime call flag checking efi/runtime-wrappers: Remove ARCH_EFI_IRQ_FLAGS_MASK ifdef
Matt Fleming (7):
x86/mm/pat: Document the (currently) EFI-only code path
efi: Iterate over efi.memmap in for_each_efi_memory_desc
efi: Remove global 'memmap'
x86/efi: Remove the always true EFI_DEBUG symbol
efi: Move efi_status_to_err() to drivers/firmware/efi/
efi: Capsule update support
x86/efi: Force EFI reboot to process pending capsules
arch/arm/include/asm/efi.h | 37 +-- arch/arm/kernel/efi.c | 41 +++ arch/arm/kernel/setup.c | 3 +- arch/arm64/include/asm/efi.h | 37 +-- arch/arm64/kernel/efi.c | 57 +++- arch/arm64/kernel/image.h | 1 + arch/ia64/kernel/efi.c | 2 - arch/x86/boot/compressed/eboot.c | 308 +-------------------- arch/x86/boot/compressed/eboot.h | 74 ------ arch/x86/include/asm/efi.h | 52 ++-- arch/x86/kernel/reboot.c | 9 + arch/x86/kernel/sysfb_efi.c | 15 ++ arch/x86/mm/pageattr.c | 8 +- arch/x86/platform/efi/efi.c | 133 +++++----- arch/x86/platform/efi/efi_64.c | 10 +- arch/x86/platform/efi/quirks.c | 10 +- drivers/firmware/efi/Kconfig | 25 ++ drivers/firmware/efi/Makefile | 5 +- drivers/firmware/efi/arm-init.c | 96 +++++-- drivers/firmware/efi/arm-runtime.c | 45 ++-- drivers/firmware/efi/capsule-loader.c | 343 ++++++++++++++++++++++++ drivers/firmware/efi/capsule.c | 300 +++++++++++++++++++++ drivers/firmware/efi/efi.c | 48 +++- drivers/firmware/efi/efibc.c | 101 +++++++ drivers/firmware/efi/fake_mem.c | 43 ++- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/arm-stub.c | 77 +++++- drivers/firmware/efi/libstub/arm32-stub.c | 37 +++ drivers/firmware/efi/libstub/efi-stub-helper.c | 6 +- drivers/firmware/efi/libstub/gop.c | 354 +++++++++++++++++++++++++ drivers/firmware/efi/memattr.c | 182 +++++++++++++ drivers/firmware/efi/reboot.c | 12 +- drivers/firmware/efi/runtime-wrappers.c | 60 +++++ drivers/firmware/efi/vars.c | 33 --- drivers/video/fbdev/Kconfig | 2 +- drivers/video/fbdev/efifb.c | 21 +- include/linux/efi.h | 164 +++++++++++- 37 files changed, 2062 insertions(+), 691 deletions(-) create mode 100644 drivers/firmware/efi/capsule-loader.c create mode 100644 drivers/firmware/efi/capsule.c create mode 100644 drivers/firmware/efi/efibc.c create mode 100644 drivers/firmware/efi/libstub/gop.c create mode 100644 drivers/firmware/efi/memattr.c
PATCH 1/40 efi: Get rid of EFI_SYSTEM_TABLES status bit
From: Ard Biesheuvel <[email protected]>
The EFI_SYSTEM_TABLES status bit is set by all EFI supporting architectures upon discovery of the EFI system table, but the bit is never tested in any code we have in the tree. So remove it.
--- arch/ia64/kernel/efi.c | 2 -- arch/x86/platform/efi/efi.c | 2 -- drivers/firmware/efi/arm-runtime.c | 1 - include/linux/efi.h | 1 - 4 files changed, 6 deletions(-)
arch/ia64/kernel/efi.c +0 -2
@@ -531,8 +531,6 @@ efi_init (void) efi.systab->hdr.revision >>16 , efi.systab->hdr.revision & 0xffff, vendor); -set_bit (EFI_SYSTEM_TABLES , &efi.flags); - palo_phys =EFI_INVALID_TABLE_ADDR ;if (efi_config_init (arch_tables) !=0 )
arch/x86/platform/efi/efi.c +0 -2
@@ -352,8 +352,6 @@ static int __init efi_systab_init(void *phys) efi.systab->hdr.revision >>16 , efi.systab->hdr.revision & 0xffff); -set_bit (EFI_SYSTEM_TABLES , &efi.flags); -return 0 ; }
drivers/firmware/efi/arm-runtime.c +0 -1
@@ -105,7 +105,6 @@ static int __init arm_enable_runtime_services(void)pr_err ("Failed to remap EFI System Table\n" );return -ENOMEM ; } -set_bit (EFI_SYSTEM_TABLES , &efi.flags);if (!efi_virtmap_init ()) {pr_err ("No UEFI virtual mapping was installed -- runtime services will not be available\n" );
include/linux/efi.h +0 -1
@@ -1000,7 +1000,6 @@ extern int __init efi_setup_pcdp_console(char *);* possible, remove EFI-related code altogether. */ #define EFI_BOOT 0/* Were we booted from EFI? */ -#define EFI_SYSTEM_TABLES 1/* Can we use EFI system tables? */ #define EFI_CONFIG_TABLES 2/* Can we use EFI config tables? */ #define EFI_RUNTIME_SERVICES 3/* Can we use runtime services? */ #define EFI_MEMMAP 4/* Can we use EFI memory map? */
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi: Get rid of the EFI_SYSTEM_TABLES status bit
efi: Get rid of the EFI_SYSTEM_TABLES status bit
Commit-ID: c5b591e96db9d99d0126acf93f24e1fb8b368343 Gitweb: http://git.kernel.org/tip/c5b591e96db9d99d0126acf93f24e1fb8b368343 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:33 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:46 +0200
efi: Get rid of the EFI_SYSTEM_TABLES status bit
The EFI_SYSTEM_TABLES status bit is set by all EFI supporting architectures upon discovery of the EFI system table, but the bit is never tested in any code we have in the tree. So remove it.
--- arch/ia64/kernel/efi.c | 2 -- arch/x86/platform/efi/efi.c | 2 -- drivers/firmware/efi/arm-runtime.c | 1 - include/linux/efi.h | 1 - 4 files changed, 6 deletions(-)
arch/ia64/kernel/efi.c +0 -2
@@ -531,8 +531,6 @@ efi_init (void) efi.systab->hdr.revision >>16 , efi.systab->hdr.revision & 0xffff, vendor); -set_bit (EFI_SYSTEM_TABLES , &efi.flags); - palo_phys =EFI_INVALID_TABLE_ADDR ;if (efi_config_init (arch_tables) !=0 )
arch/x86/platform/efi/efi.c +0 -2
@@ -352,8 +352,6 @@ static int __init efi_systab_init(void *phys) efi.systab->hdr.revision >>16 , efi.systab->hdr.revision & 0xffff); -set_bit (EFI_SYSTEM_TABLES , &efi.flags); -return 0 ; }
drivers/firmware/efi/arm-runtime.c +0 -1
@@ -105,7 +105,6 @@ static int __init arm_enable_runtime_services(void)pr_err ("Failed to remap EFI System Table\n" );return -ENOMEM ; } -set_bit (EFI_SYSTEM_TABLES , &efi.flags);if (!efi_virtmap_init ()) {pr_err ("No UEFI virtual mapping was installed -- runtime services will not be available\n" );
include/linux/efi.h +0 -1
@@ -1000,7 +1000,6 @@ extern int __init efi_setup_pcdp_console(char *);* possible, remove EFI-related code altogether. */ #define EFI_BOOT 0/* Were we booted from EFI? */ -#define EFI_SYSTEM_TABLES 1/* Can we use EFI system tables? */ #define EFI_CONFIG_TABLES 2/* Can we use EFI config tables? */ #define EFI_RUNTIME_SERVICES 3/* Can we use runtime services? */ #define EFI_MEMMAP 4/* Can we use EFI memory map? */
PATCH 2/40 efi/arm*: Drop writable mapping of the UEFI System table
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Commit 2eec5dedf770 ("efi/arm-init: Use read-only early mappings") updated the early ARM UEFI init code to create the temporary, early mapping of the UEFI System table using read-only attributes, as a hardening measure against inadvertent modification.
However, this still leaves the permanent, writable mapping of the UEFI System table, which is only ever referenced during invocations of UEFI Runtime Services, at which time the UEFI virtual mapping is available, which also covers the system table. (This is guaranteed by the fact that SetVirtualAddressMap(), which is a runtime service itself, converts various entries in the table to their virtual equivalents, which implies that the table must be covered by a RuntimeServicesData region that has the EFI_MEMORY_RUNTIME attribute.)
So instead of creating this permanent mapping, record the virtual address of the system table inside the UEFI virtual mapping, and dereference that when accessing the table. This protects the contents of the system table from inadvertent (or deliberate) modification when no UEFI Runtime Services calls are in progress.
--- drivers/firmware/efi/arm-init.c | 2 ++ drivers/firmware/efi/arm-runtime.c | 27 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-)
drivers/firmware/efi/arm-init.c +2 -0
@@ -85,6 +85,8 @@ static int __init uefi_init(void) efi.systab->hdr.revision >>16 , efi.systab->hdr.revision & 0xffff); + efi.runtime_version = efi.systab->hdr.revision; +/* Show what we know for posterity */ c16 =early_memremap_ro (efi_to_phys (efi.systab->fw_vendor),sizeof (vendor) *sizeof (efi_char16_t));
drivers/firmware/efi/arm-runtime.c +16 -11
@@ -42,10 +42,12 @@ static struct mm_struct efi_mm = {static bool __init efi_virtmap_init (void ) {efi_memory_desc_t *md; +bool systab_found; efi_mm.pgd =pgd_alloc (&efi_mm);init_new_context (NULL , &efi_mm); + systab_found = false;for_each_efi_memory_desc (&memmap, md) {phys_addr_t phys = md->phys_addr;int ret;
@@ -64,8 +66,20 @@ static bool __init efi_virtmap_init(void) &phys, ret);return false; } +/* +* If this entry covers the address of the UEFI system table, +* calculate and record its virtual address. +*/ +if (efi_system_table >= phys && + efi_system_table < phys + (md->num_pages *EFI_PAGE_SIZE )) { + efi.systab = (void *)(unsigned long )(efi_system_table - + phys + md->virt_addr); + systab_found = true; + } } -return true; +if (!systab_found) +pr_err ("No virtual mapping found for the UEFI System Table\n" ); +return systab_found; }/*
@@ -99,15 +113,8 @@ static int __init arm_enable_runtime_services(void) memmap.map_end = memmap.map + mapsize; efi.memmap = &memmap; - efi.systab = (__force void *)ioremap_cache (efi_system_table, -sizeof (efi_system_table_t)); -if (!efi.systab) { -pr_err ("Failed to remap EFI System Table\n" ); -return -ENOMEM ; - } -if (!efi_virtmap_init ()) { -pr_err ("No UEFI virtual mapping was installed -- runtime services will not be available\n" ); +pr_err ("UEFI virtual mapping missing or invalid -- runtime services will not be available\n" );return -ENOMEM ; }
@@ -115,8 +122,6 @@ static int __init arm_enable_runtime_services(void)efi_native_runtime_setup ();set_bit (EFI_RUNTIME_SERVICES , &efi.flags); - efi.runtime_version = efi.systab->hdr.revision; -return 0 ; }early_initcall (arm_enable_runtime_services);
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/arm*: Drop writable mapping of the UEFI System table
efi/arm*: Drop writable mapping of the UEFI System table
Commit-ID: 14c43be60166981f0b1f034ad9c59252c6f99e0d Gitweb: http://git.kernel.org/tip/14c43be60166981f0b1f034ad9c59252c6f99e0d Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:34 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:47 +0200
efi/arm*: Drop writable mapping of the UEFI System table
Commit:
2eec5dedf770 ("efi/arm-init: Use read-only early mappings")
updated the early ARM UEFI init code to create the temporary, early mapping of the UEFI System table using read-only attributes, as a hardening measure against inadvertent modification.
However, this still leaves the permanent, writable mapping of the UEFI System table, which is only ever referenced during invocations of UEFI Runtime Services, at which time the UEFI virtual mapping is available, which also covers the system table. (This is guaranteed by the fact that SetVirtualAddressMap(), which is a runtime service itself, converts various entries in the table to their virtual equivalents, which implies that the table must be covered by a RuntimeServicesData region that has the EFI_MEMORY_RUNTIME attribute.)
So instead of creating this permanent mapping, record the virtual address of the system table inside the UEFI virtual mapping, and dereference that when accessing the table. This protects the contents of the system table from inadvertent (or deliberate) modification when no UEFI Runtime Services calls are in progress.
--- drivers/firmware/efi/arm-init.c | 2 ++ drivers/firmware/efi/arm-runtime.c | 27 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-)
drivers/firmware/efi/arm-init.c +2 -0
@@ -85,6 +85,8 @@ static int __init uefi_init(void) efi.systab->hdr.revision >>16 , efi.systab->hdr.revision & 0xffff); + efi.runtime_version = efi.systab->hdr.revision; +/* Show what we know for posterity */ c16 =early_memremap_ro (efi_to_phys (efi.systab->fw_vendor),sizeof (vendor) *sizeof (efi_char16_t));
drivers/firmware/efi/arm-runtime.c +16 -11
@@ -42,10 +42,12 @@ static struct mm_struct efi_mm = {static bool __init efi_virtmap_init (void ) {efi_memory_desc_t *md; +bool systab_found; efi_mm.pgd =pgd_alloc (&efi_mm);init_new_context (NULL , &efi_mm); + systab_found = false;for_each_efi_memory_desc (&memmap, md) {phys_addr_t phys = md->phys_addr;int ret;
@@ -64,8 +66,20 @@ static bool __init efi_virtmap_init(void) &phys, ret);return false; } +/* +* If this entry covers the address of the UEFI system table, +* calculate and record its virtual address. +*/ +if (efi_system_table >= phys && + efi_system_table < phys + (md->num_pages *EFI_PAGE_SIZE )) { + efi.systab = (void *)(unsigned long )(efi_system_table - + phys + md->virt_addr); + systab_found = true; + } } -return true; +if (!systab_found) +pr_err ("No virtual mapping found for the UEFI System Table\n" ); +return systab_found; }/*
@@ -99,15 +113,8 @@ static int __init arm_enable_runtime_services(void) memmap.map_end = memmap.map + mapsize; efi.memmap = &memmap; - efi.systab = (__force void *)ioremap_cache (efi_system_table, -sizeof (efi_system_table_t)); -if (!efi.systab) { -pr_err ("Failed to remap EFI System Table\n" ); -return -ENOMEM ; - } -if (!efi_virtmap_init ()) { -pr_err ("No UEFI virtual mapping was installed -- runtime services will not be available\n" ); +pr_err ("UEFI virtual mapping missing or invalid -- runtime services will not be available\n" );return -ENOMEM ; }
@@ -115,8 +122,6 @@ static int __init arm_enable_runtime_services(void)efi_native_runtime_setup ();set_bit (EFI_RUNTIME_SERVICES , &efi.flags); - efi.runtime_version = efi.systab->hdr.revision; -return 0 ; }early_initcall (arm_enable_runtime_services);
PATCH 3/40 x86/mm/pat: Document the (currently) EFI-only code path
In reply to Matt FlemingIt's not at all obvious that populate_pgd() and friends are only executed when mapping EFI virtual memory regions or that no other pageattr callers pass a ->pgd value.
--- arch/x86/mm/pageattr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
arch/x86/mm/pageattr.c +7 -1
@@ -1125,8 +1125,14 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)static int __cpa_process_fault (struct cpa_data *cpa,unsigned long vaddr,int primary) { -if (cpa->pgd) +if (cpa->pgd) { +/* +* Right now, we only execute this code path when mapping +* the EFI virtual memory map regions, no other users +* provide a ->pgd value. This may change in the future. +*/ return populate_pgd (cpa, vaddr); + }/* * Ignore all non primary paths.
Signature · 1 line
2.7.3
tip-bot for Matt Fleming
merge bot[tip:efi/core] x86/mm/pat: Document the (currently) EFI-only code path
x86/mm/pat: Document the (currently) EFI-only code path
Commit-ID: 7fc8442f2a8a77f40565b42c41e4f2d48b179a56 Gitweb: http://git.kernel.org/tip/7fc8442f2a8a77f40565b42c41e4f2d48b179a56 Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:35 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:48 +0200
x86/mm/pat: Document the (currently) EFI-only code path
It's not at all obvious that populate_pgd() and friends are only executed when mapping EFI virtual memory regions or that no other pageattr callers pass a ->pgd value.
--- arch/x86/mm/pageattr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
arch/x86/mm/pageattr.c +7 -1
@@ -1125,8 +1125,14 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)static int __cpa_process_fault (struct cpa_data *cpa,unsigned long vaddr,int primary) { -if (cpa->pgd) +if (cpa->pgd) { +/* +* Right now, we only execute this code path when mapping +* the EFI virtual memory map regions, no other users +* provide a ->pgd value. This may change in the future. +*/ return populate_pgd (cpa, vaddr); + }/* * Ignore all non primary paths.
PATCH 4/40 efi/arm64: Report unexpected errors when determining Secure Boot status
In reply to Matt FlemingFrom: Linn Crosetto <[email protected]>
Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters.
If an unexpected error is returned from GetVariable() when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned.
--- drivers/firmware/efi/libstub/arm-stub.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
drivers/firmware/efi/libstub/arm-stub.c +18 -4
@@ -20,7 +20,7 @@bool __nokaslr; -static int efi_secureboot_enabled (efi_system_table_t *sys_table_arg) +static int efi_get_secureboot (efi_system_table_t *sys_table_arg) {static efi_guid_t const var_guid =EFI_GLOBAL_VARIABLE_GUID ;static efi_char16_t const var_name[] = {
@@ -39,8 +39,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg)return val;case EFI_NOT_FOUND :return 0 ; +case EFI_DEVICE_ERROR : +return -EIO ; +case EFI_SECURITY_VIOLATION : +return -EACCES ;default : -return 1 ; +return -EINVAL ; } }
@@ -185,6 +189,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,efi_guid_t loaded_image_proto =LOADED_IMAGE_PROTOCOL_GUID ;unsigned long reserve_addr =0 ;unsigned long reserve_size =0 ; +int secure_boot =0 ;/* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature !=EFI_SYSTEM_TABLE_SIGNATURE )
@@ -250,12 +255,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,if (status !=EFI_SUCCESS )pr_efi_err (sys_table,"Failed to parse EFI cmdline options\n" ); + secure_boot =efi_get_secureboot (sys_table); +if (secure_boot >0 ) +pr_efi (sys_table,"UEFI Secure Boot is enabled.\n" ); + +if (secure_boot <0 ) { +pr_efi_err (sys_table, +"could not determine UEFI Secure Boot status.\n" ); + } +/* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ -if (efi_secureboot_enabled (sys_table)) { -pr_efi (sys_table,"UEFI Secure Boot is enabled.\n" ); +if (secure_boot !=0 &&strstr (cmdline_ptr,"dtb=" )) { +pr_efi (sys_table,"Ignoring DTB from command line.\n" ); }else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=",
Signature · 1 line
2.7.3
tip-bot for Linn Crosetto
merge bot[tip:efi/core] efi/arm64: Report unexpected errors when determining Secure Boot status
efi/arm64: Report unexpected errors when determining Secure Boot status
Commit-ID: 73a6492589c87cd56707c8ac19eec78236c2d576 Gitweb: http://git.kernel.org/tip/73a6492589c87cd56707c8ac19eec78236c2d576 Author: Linn Crosetto <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:36 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:48 +0200
efi/arm64: Report unexpected errors when determining Secure Boot status
Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters.
If an unexpected error is returned from GetVariable() when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned.
--- drivers/firmware/efi/libstub/arm-stub.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
drivers/firmware/efi/libstub/arm-stub.c +18 -4
@@ -20,7 +20,7 @@bool __nokaslr; -static int efi_secureboot_enabled (efi_system_table_t *sys_table_arg) +static int efi_get_secureboot (efi_system_table_t *sys_table_arg) {static efi_guid_t const var_guid =EFI_GLOBAL_VARIABLE_GUID ;static efi_char16_t const var_name[] = {
@@ -39,8 +39,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg)return val;case EFI_NOT_FOUND :return 0 ; +case EFI_DEVICE_ERROR : +return -EIO ; +case EFI_SECURITY_VIOLATION : +return -EACCES ;default : -return 1 ; +return -EINVAL ; } }
@@ -185,6 +189,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,efi_guid_t loaded_image_proto =LOADED_IMAGE_PROTOCOL_GUID ;unsigned long reserve_addr =0 ;unsigned long reserve_size =0 ; +int secure_boot =0 ;/* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature !=EFI_SYSTEM_TABLE_SIGNATURE )
@@ -250,12 +255,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,if (status !=EFI_SUCCESS )pr_efi_err (sys_table,"Failed to parse EFI cmdline options\n" ); + secure_boot =efi_get_secureboot (sys_table); +if (secure_boot >0 ) +pr_efi (sys_table,"UEFI Secure Boot is enabled.\n" ); + +if (secure_boot <0 ) { +pr_efi_err (sys_table, +"could not determine UEFI Secure Boot status.\n" ); + } +/* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ -if (efi_secureboot_enabled (sys_table)) { -pr_efi (sys_table,"UEFI Secure Boot is enabled.\n" ); +if (secure_boot !=0 &&strstr (cmdline_ptr,"dtb=" )) { +pr_efi (sys_table,"Ignoring DTB from command line.\n" ); }else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=",
PATCH 5/40 efi/arm64: Check SetupMode when determining Secure Boot status
In reply to Matt FlemingFrom: Linn Crosetto <[email protected]>
According to the UEFI specification (version 2.5 Errata A, page 87):
The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1.
Check the value of the SetupMode variable when determining the state of Secure Boot. Minor cleanup, change sizeof to match kernel style guidelines.
--- drivers/firmware/efi/libstub/arm-stub.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-)
drivers/firmware/efi/libstub/arm-stub.c +25 -7
@@ -22,21 +22,39 @@ bool __nokaslr;static int efi_get_secureboot (efi_system_table_t *sys_table_arg) { -static efi_guid_t const var_guid =EFI_GLOBAL_VARIABLE_GUID ; -static efi_char16_t const var_name[] = { +static efi_char16_t const sb_var_name[] = {'S' ,'e' ,'c' ,'u' ,'r' ,'e' ,'B' ,'o' ,'o' ,'t' ,0 }; +static efi_char16_t const sm_var_name[] = { +'S' ,'e' ,'t' ,'u' ,'p' ,'M' ,'o' ,'d' ,'e' ,0 }; +efi_guid_t var_guid =EFI_GLOBAL_VARIABLE_GUID ;efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; -unsigned long size =sizeof (u8); -efi_status_t status;u8 val; +unsigned long size =sizeof (val); +efi_status_t status; - status =f_getvar ((efi_char16_t *)var_name, (efi_guid_t *)&var_guid, + status =f_getvar ((efi_char16_t *)sb_var_name, (efi_guid_t *)&var_guid,NULL , &size, &val); +if (status !=EFI_SUCCESS ) + goto out_efi_err; + +if (val ==0 ) +return 0 ; + + status =f_getvar ((efi_char16_t *)sm_var_name, (efi_guid_t *)&var_guid, +NULL , &size, &val); + +if (status !=EFI_SUCCESS ) + goto out_efi_err; + +if (val ==1 ) +return 0 ; + +return 1 ; + +out_efi_err:switch (status) { -case EFI_SUCCESS : -return val;case EFI_NOT_FOUND :return 0 ;case EFI_DEVICE_ERROR :
Signature · 1 line
2.7.3
tip-bot for Linn Crosetto
merge bot[tip:efi/core] efi/arm64: Check SetupMode when determining Secure Boot status
efi/arm64: Check SetupMode when determining Secure Boot status
Commit-ID: 30d7bf034c034995f34dae265d96247f7f12044e Gitweb: http://git.kernel.org/tip/30d7bf034c034995f34dae265d96247f7f12044e Author: Linn Crosetto <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:37 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:49 +0200
efi/arm64: Check SetupMode when determining Secure Boot status
According to the UEFI specification (version 2.5 Errata A, page 87):
The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1.
Check the value of the SetupMode variable when determining the state of Secure Boot.
Plus also do minor cleanup, change sizeof() use to match kernel style guidelines.
--- drivers/firmware/efi/libstub/arm-stub.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-)
drivers/firmware/efi/libstub/arm-stub.c +25 -7
@@ -22,21 +22,39 @@ bool __nokaslr;static int efi_get_secureboot (efi_system_table_t *sys_table_arg) { -static efi_guid_t const var_guid =EFI_GLOBAL_VARIABLE_GUID ; -static efi_char16_t const var_name[] = { +static efi_char16_t const sb_var_name[] = {'S' ,'e' ,'c' ,'u' ,'r' ,'e' ,'B' ,'o' ,'o' ,'t' ,0 }; +static efi_char16_t const sm_var_name[] = { +'S' ,'e' ,'t' ,'u' ,'p' ,'M' ,'o' ,'d' ,'e' ,0 }; +efi_guid_t var_guid =EFI_GLOBAL_VARIABLE_GUID ;efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; -unsigned long size =sizeof (u8); -efi_status_t status;u8 val; +unsigned long size =sizeof (val); +efi_status_t status; - status =f_getvar ((efi_char16_t *)var_name, (efi_guid_t *)&var_guid, + status =f_getvar ((efi_char16_t *)sb_var_name, (efi_guid_t *)&var_guid,NULL , &size, &val); +if (status !=EFI_SUCCESS ) + goto out_efi_err; + +if (val ==0 ) +return 0 ; + + status =f_getvar ((efi_char16_t *)sm_var_name, (efi_guid_t *)&var_guid, +NULL , &size, &val); + +if (status !=EFI_SUCCESS ) + goto out_efi_err; + +if (val ==1 ) +return 0 ; + +return 1 ; + +out_efi_err:switch (status) { -case EFI_SUCCESS : -return val;case EFI_NOT_FOUND :return 0 ;case EFI_DEVICE_ERROR :
PATCH 6/40 efi: Iterate over efi.memmap in for_each_efi_memory_desc
In reply to Matt FlemingMost of the users of for_each_efi_memory_desc() are equally happy iterating over the EFI memory map in efi.memmap instead of 'memmap', since the former is usually a pointer to the latter.
For those users that want to specify an EFI memory map other than efi.memmap, that can be done using for_each_efi_memory_desc_in_map(). One such example is in the libstub code where the firmware is queried directly for the memory map, it gets iterated over, and then freed.
This change goes part of the way toward deleting the global 'memmap' variable, which is not universally available on all architectures (notably ia64) and is rather poorly named.
--- arch/x86/platform/efi/efi.c | 43 ++++++++------------------ arch/x86/platform/efi/efi_64.c | 10 ++---- arch/x86/platform/efi/quirks.c | 10 +++--- drivers/firmware/efi/arm-init.c | 4 +-- drivers/firmware/efi/arm-runtime.c | 2 +- drivers/firmware/efi/efi.c | 6 +--- drivers/firmware/efi/fake_mem.c | 3 +- drivers/firmware/efi/libstub/efi-stub-helper.c | 6 ++-- include/linux/efi.h | 11 ++++++- 9 files changed, 39 insertions(+), 56 deletions(-)
arch/x86/platform/efi/efi.c +13 -30
@@ -119,11 +119,10 @@ void efi_get_time(struct timespec *now)void __init efi_find_mirror (void ) { -void *p; +efi_memory_desc_t *md;u64 mirror_size =0 , total_size =0 ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;
@@ -146,10 +145,9 @@ void __init efi_find_mirror(void)static void __init do_add_efi_memmap (void ) { -void *p; +efi_memory_desc_t *md; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;int e820_type;
@@ -226,17 +224,13 @@ void __init efi_print_memmap(void) {#ifdef EFI_DEBUG efi_memory_desc_t *md; -void *p; -int i; +int i =0 ; -for (p = memmap.map, i =0 ; - p < memmap.map_end; - p += memmap.desc_size, i++) { +for_each_efi_memory_desc (md) {char buf[64 ]; - md = p;pr_info ("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n" , - i,efi_md_typeattr_format (buf,sizeof (buf), md), + i++,efi_md_typeattr_format (buf,sizeof (buf), md), md->phys_addr, md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ) -1 , (md->num_pages >> (20 -EFI_PAGE_SHIFT )));
@@ -550,12 +544,9 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable)void __init runtime_code_page_mkexec (void ) {efi_memory_desc_t *md; -void *p;/* Make EFI runtime service code area executable */ -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; - +for_each_efi_memory_desc (md) {if (md->type !=EFI_RUNTIME_SERVICES_CODE )continue ;
@@ -602,12 +593,10 @@ void __init old_map_region(efi_memory_desc_t *md)/* Merge contiguous regions of the same type and attribute */ static void __init efi_merge_regions (void ) { -void *p;efi_memory_desc_t *md, *prev_md =NULL ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { +for_each_efi_memory_desc (md) {u64 prev_size; - md = p;if (!prev_md) { prev_md = md;
@@ -650,15 +639,13 @@ static void __init save_runtime_map(void) {#ifdef CONFIG_KEXEC_CORE efi_memory_desc_t *md; -void *tmp, *p, *q =NULL ; +void *tmp, *q =NULL ;int count =0 ;if (efi_enabled (EFI_OLD_MEMMAP ))return ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; - +for_each_efi_memory_desc (md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ) || (md->type ==EFI_BOOT_SERVICES_CODE ) || (md->type ==EFI_BOOT_SERVICES_DATA ))
@@ -814,7 +801,6 @@ static void __init kexec_enter_virtual_mode(void)#ifdef CONFIG_KEXEC_CORE efi_memory_desc_t *md;unsigned int num_pages; -void *p; efi.systab =NULL ;
@@ -838,8 +824,7 @@ static void __init kexec_enter_virtual_mode(void)* Map efi regions which were passed via setup_data. The virt_addr is a * fixed addr which was used in first kernel of a kexec boot. */ -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; +for_each_efi_memory_desc (md) {efi_map_region_fixed (md);/* FIXME: add error handling */ get_systab_virt_addr (md); }
@@ -1009,13 +994,11 @@ void __init efi_enter_virtual_mode(void)u32 efi_mem_type (unsigned long phys_addr) {efi_memory_desc_t *md; -void *p;if (!efi_enabled (EFI_MEMMAP ))return 0 ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; +for_each_efi_memory_desc (md) {if ((md->phys_addr <= phys_addr) && (phys_addr < (md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ))))
arch/x86/platform/efi/efi_64.c +3 -7
@@ -55,14 +55,12 @@ struct efi_scratch efi_scratch;static void __init early_code_mapping_set_exec (int executable) {efi_memory_desc_t *md; -void *p;if (!(__supported_pte_mask & _PAGE_NX))return ;/* Make EFI service code area executable */ -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; +for_each_efi_memory_desc (md) {if (md->type ==EFI_RUNTIME_SERVICES_CODE || md->type ==EFI_BOOT_SERVICES_CODE )efi_set_executable (md, executable);
@@ -253,7 +251,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)* Map all of RAM so that we can access arguments in the 1:1 * mapping when making EFI runtime calls. */ -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc (md) {if (md->type !=EFI_CONVENTIONAL_MEMORY && md->type !=EFI_LOADER_DATA && md->type !=EFI_LOADER_CODE )
@@ -398,7 +396,6 @@ void __init efi_runtime_update_mappings(void)unsigned long pfn;pgd_t *pgd = efi_pgd;efi_memory_desc_t *md; -void *p;if (efi_enabled (EFI_OLD_MEMMAP )) {if (__supported_pte_mask & _PAGE_NX)
@@ -409,9 +406,8 @@ void __init efi_runtime_update_mappings(void)if (!efi_enabled (EFI_NX_PE_DATA ))return ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { +for_each_efi_memory_desc (md) {unsigned long pf =0 ; - md = p;if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ;
arch/x86/platform/efi/quirks.c +4 -6
@@ -195,10 +195,9 @@ static bool can_free_region(u64 start, u64 size)*/ void __init efi_reserve_boot_services (void ) { -void *p; +efi_memory_desc_t *md; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {u64 start = md->phys_addr;u64 size = md->num_pages <<EFI_PAGE_SHIFT ;bool already_reserved;
@@ -250,10 +249,9 @@ void __init efi_reserve_boot_services(void)void __init efi_free_boot_services (void ) { -void *p; +efi_memory_desc_t *md; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;
drivers/firmware/efi/arm-init.c +2 -2
@@ -40,7 +40,7 @@ static phys_addr_t efi_to_phys(unsigned long addr) {efi_memory_desc_t *md; -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc_in_map (&memmap, md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ;if (md->virt_addr ==0 )
@@ -145,7 +145,7 @@ static __init void reserve_regions(void)if (efi_enabled (EFI_DBG ))pr_info ("Processing EFI memory map:\n" ); -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc_in_map (&memmap, md) { paddr = md->phys_addr; npages = md->num_pages;
drivers/firmware/efi/arm-runtime.c +1 -1
@@ -48,7 +48,7 @@ static bool __init efi_virtmap_init(void)init_new_context (NULL , &efi_mm); systab_found = false; -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc (md) {phys_addr_t phys = md->phys_addr;int ret;
drivers/firmware/efi/efi.c +1 -5
@@ -620,16 +620,12 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,*/ u64 __weak efi_mem_attributes (unsigned long phys_addr) { -struct efi_memory_map *map;efi_memory_desc_t *md; -void *p;if (!efi_enabled (EFI_MEMMAP ))return 0 ; - map = efi.memmap; -for (p = map->map; p < map->map_end; p += map->desc_size) { - md = p; +for_each_efi_memory_desc (md) {if ((md->phys_addr <= phys_addr) && (phys_addr < (md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ))))
drivers/firmware/efi/fake_mem.c +1 -2
@@ -68,8 +68,7 @@ void __init efi_fake_memmap(void)return ;/* count up the number of EFI memory descriptor */ -for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) { - md = old; +for_each_efi_memory_desc (md) { start = md->phys_addr; end = start + (md->num_pages <<EFI_PAGE_SHIFT ) -1 ;
drivers/firmware/efi/libstub/efi-stub-helper.c +4 -2
@@ -125,10 +125,12 @@ unsigned long get_dram_base(efi_system_table_t *sys_table_arg) map.map_end = map.map + map_size; -for_each_efi_memory_desc (&map, md) -if (md->attribute &EFI_MEMORY_WB ) +for_each_efi_memory_desc_in_map (&map, md) { +if (md->attribute &EFI_MEMORY_WB ) {if (membase > md->phys_addr) membase = md->phys_addr; + } + }efi_call_early (free_pool, map.map);
include/linux/efi.h +10 -1
@@ -958,11 +958,20 @@ static inline void efi_fake_memmap(void) { }#endif /* Iterate through an efi_memory_map */ -#define for_each_efi_memory_desc (m, md) \ +#define for_each_efi_memory_desc_in_map (m, md) \ for ((md) = (m)->map; \ (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \ (md) = (void *)(md) + (m)->desc_size) +/** +* for_each_efi_memory_desc - iterate over descriptors in efi.memmap +* @md: the efi_memory_desc_t * iterator +* +* Once the loop finishes @md must not be accessed. +*/ +#define for_each_efi_memory_desc (md) \ + for_each_efi_memory_desc_in_map(efi.memmap, md) +/* * Format an EFI memory descriptor's type and attributes to a user-provided * character buffer, as per snprintf(), and return the buffer.
Signature · 1 line
2.7.3
tip-bot for Matt Fleming
merge bot[tip:efi/core] efi: Iterate over efi.memmap in for_each_efi_memory_desc()
efi: Iterate over efi.memmap in for_each_efi_memory_desc()
Commit-ID: 78ce248faa3c46e24e9bd42db3ab3650659f16dd Gitweb: http://git.kernel.org/tip/78ce248faa3c46e24e9bd42db3ab3650659f16dd Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:38 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:50 +0200
efi: Iterate over efi.memmap in for_each_efi_memory_desc()
Most of the users of for_each_efi_memory_desc() are equally happy iterating over the EFI memory map in efi.memmap instead of 'memmap', since the former is usually a pointer to the latter.
For those users that want to specify an EFI memory map other than efi.memmap, that can be done using for_each_efi_memory_desc_in_map(). One such example is in the libstub code where the firmware is queried directly for the memory map, it gets iterated over, and then freed.
This change goes part of the way toward deleting the global 'memmap' variable, which is not universally available on all architectures (notably IA64) and is rather poorly named.
--- arch/x86/platform/efi/efi.c | 43 ++++++++------------------ arch/x86/platform/efi/efi_64.c | 10 ++---- arch/x86/platform/efi/quirks.c | 10 +++--- drivers/firmware/efi/arm-init.c | 4 +-- drivers/firmware/efi/arm-runtime.c | 2 +- drivers/firmware/efi/efi.c | 6 +--- drivers/firmware/efi/fake_mem.c | 3 +- drivers/firmware/efi/libstub/efi-stub-helper.c | 6 ++-- include/linux/efi.h | 11 ++++++- 9 files changed, 39 insertions(+), 56 deletions(-)
arch/x86/platform/efi/efi.c +13 -30
@@ -119,11 +119,10 @@ void efi_get_time(struct timespec *now)void __init efi_find_mirror (void ) { -void *p; +efi_memory_desc_t *md;u64 mirror_size =0 , total_size =0 ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;
@@ -146,10 +145,9 @@ void __init efi_find_mirror(void)static void __init do_add_efi_memmap (void ) { -void *p; +efi_memory_desc_t *md; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;int e820_type;
@@ -226,17 +224,13 @@ void __init efi_print_memmap(void) {#ifdef EFI_DEBUG efi_memory_desc_t *md; -void *p; -int i; +int i =0 ; -for (p = memmap.map, i =0 ; - p < memmap.map_end; - p += memmap.desc_size, i++) { +for_each_efi_memory_desc (md) {char buf[64 ]; - md = p;pr_info ("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n" , - i,efi_md_typeattr_format (buf,sizeof (buf), md), + i++,efi_md_typeattr_format (buf,sizeof (buf), md), md->phys_addr, md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ) -1 , (md->num_pages >> (20 -EFI_PAGE_SHIFT )));
@@ -550,12 +544,9 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable)void __init runtime_code_page_mkexec (void ) {efi_memory_desc_t *md; -void *p;/* Make EFI runtime service code area executable */ -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; - +for_each_efi_memory_desc (md) {if (md->type !=EFI_RUNTIME_SERVICES_CODE )continue ;
@@ -602,12 +593,10 @@ void __init old_map_region(efi_memory_desc_t *md)/* Merge contiguous regions of the same type and attribute */ static void __init efi_merge_regions (void ) { -void *p;efi_memory_desc_t *md, *prev_md =NULL ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { +for_each_efi_memory_desc (md) {u64 prev_size; - md = p;if (!prev_md) { prev_md = md;
@@ -650,15 +639,13 @@ static void __init save_runtime_map(void) {#ifdef CONFIG_KEXEC_CORE efi_memory_desc_t *md; -void *tmp, *p, *q =NULL ; +void *tmp, *q =NULL ;int count =0 ;if (efi_enabled (EFI_OLD_MEMMAP ))return ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; - +for_each_efi_memory_desc (md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ) || (md->type ==EFI_BOOT_SERVICES_CODE ) || (md->type ==EFI_BOOT_SERVICES_DATA ))
@@ -814,7 +801,6 @@ static void __init kexec_enter_virtual_mode(void)#ifdef CONFIG_KEXEC_CORE efi_memory_desc_t *md;unsigned int num_pages; -void *p; efi.systab =NULL ;
@@ -838,8 +824,7 @@ static void __init kexec_enter_virtual_mode(void)* Map efi regions which were passed via setup_data. The virt_addr is a * fixed addr which was used in first kernel of a kexec boot. */ -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; +for_each_efi_memory_desc (md) {efi_map_region_fixed (md);/* FIXME: add error handling */ get_systab_virt_addr (md); }
@@ -1009,13 +994,11 @@ void __init efi_enter_virtual_mode(void)u32 efi_mem_type (unsigned long phys_addr) {efi_memory_desc_t *md; -void *p;if (!efi_enabled (EFI_MEMMAP ))return 0 ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; +for_each_efi_memory_desc (md) {if ((md->phys_addr <= phys_addr) && (phys_addr < (md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ))))
arch/x86/platform/efi/efi_64.c +3 -7
@@ -55,14 +55,12 @@ struct efi_scratch efi_scratch;static void __init early_code_mapping_set_exec (int executable) {efi_memory_desc_t *md; -void *p;if (!(__supported_pte_mask & _PAGE_NX))return ;/* Make EFI service code area executable */ -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; +for_each_efi_memory_desc (md) {if (md->type ==EFI_RUNTIME_SERVICES_CODE || md->type ==EFI_BOOT_SERVICES_CODE )efi_set_executable (md, executable);
@@ -253,7 +251,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)* Map all of RAM so that we can access arguments in the 1:1 * mapping when making EFI runtime calls. */ -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc (md) {if (md->type !=EFI_CONVENTIONAL_MEMORY && md->type !=EFI_LOADER_DATA && md->type !=EFI_LOADER_CODE )
@@ -398,7 +396,6 @@ void __init efi_runtime_update_mappings(void)unsigned long pfn;pgd_t *pgd = efi_pgd;efi_memory_desc_t *md; -void *p;if (efi_enabled (EFI_OLD_MEMMAP )) {if (__supported_pte_mask & _PAGE_NX)
@@ -409,9 +406,8 @@ void __init efi_runtime_update_mappings(void)if (!efi_enabled (EFI_NX_PE_DATA ))return ; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { +for_each_efi_memory_desc (md) {unsigned long pf =0 ; - md = p;if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ;
arch/x86/platform/efi/quirks.c +4 -6
@@ -195,10 +195,9 @@ static bool can_free_region(u64 start, u64 size)*/ void __init efi_reserve_boot_services (void ) { -void *p; +efi_memory_desc_t *md; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {u64 start = md->phys_addr;u64 size = md->num_pages <<EFI_PAGE_SHIFT ;bool already_reserved;
@@ -250,10 +249,9 @@ void __init efi_reserve_boot_services(void)void __init efi_free_boot_services (void ) { -void *p; +efi_memory_desc_t *md; -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -efi_memory_desc_t *md = p; +for_each_efi_memory_desc (md) {unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages <<EFI_PAGE_SHIFT ;
drivers/firmware/efi/arm-init.c +2 -2
@@ -40,7 +40,7 @@ static phys_addr_t efi_to_phys(unsigned long addr) {efi_memory_desc_t *md; -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc_in_map (&memmap, md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ;if (md->virt_addr ==0 )
@@ -145,7 +145,7 @@ static __init void reserve_regions(void)if (efi_enabled (EFI_DBG ))pr_info ("Processing EFI memory map:\n" ); -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc_in_map (&memmap, md) { paddr = md->phys_addr; npages = md->num_pages;
drivers/firmware/efi/arm-runtime.c +1 -1
@@ -48,7 +48,7 @@ static bool __init efi_virtmap_init(void)init_new_context (NULL , &efi_mm); systab_found = false; -for_each_efi_memory_desc (&memmap, md) { +for_each_efi_memory_desc (md) {phys_addr_t phys = md->phys_addr;int ret;
drivers/firmware/efi/efi.c +1 -5
@@ -620,16 +620,12 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,*/ u64 __weak efi_mem_attributes (unsigned long phys_addr) { -struct efi_memory_map *map;efi_memory_desc_t *md; -void *p;if (!efi_enabled (EFI_MEMMAP ))return 0 ; - map = efi.memmap; -for (p = map->map; p < map->map_end; p += map->desc_size) { - md = p; +for_each_efi_memory_desc (md) {if ((md->phys_addr <= phys_addr) && (phys_addr < (md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ))))
drivers/firmware/efi/fake_mem.c +1 -2
@@ -68,8 +68,7 @@ void __init efi_fake_memmap(void)return ;/* count up the number of EFI memory descriptor */ -for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) { - md = old; +for_each_efi_memory_desc (md) { start = md->phys_addr; end = start + (md->num_pages <<EFI_PAGE_SHIFT ) -1 ;
drivers/firmware/efi/libstub/efi-stub-helper.c +4 -2
@@ -125,10 +125,12 @@ unsigned long get_dram_base(efi_system_table_t *sys_table_arg) map.map_end = map.map + map_size; -for_each_efi_memory_desc (&map, md) -if (md->attribute &EFI_MEMORY_WB ) +for_each_efi_memory_desc_in_map (&map, md) { +if (md->attribute &EFI_MEMORY_WB ) {if (membase > md->phys_addr) membase = md->phys_addr; + } + }efi_call_early (free_pool, map.map);
include/linux/efi.h +10 -1
@@ -958,11 +958,20 @@ static inline void efi_fake_memmap(void) { }#endif /* Iterate through an efi_memory_map */ -#define for_each_efi_memory_desc (m, md) \ +#define for_each_efi_memory_desc_in_map (m, md) \ for ((md) = (m)->map; \ (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \ (md) = (void *)(md) + (m)->desc_size) +/** +* for_each_efi_memory_desc - iterate over descriptors in efi.memmap +* @md: the efi_memory_desc_t * iterator +* +* Once the loop finishes @md must not be accessed. +*/ +#define for_each_efi_memory_desc (md) \ + for_each_efi_memory_desc_in_map(efi.memmap, md) +/* * Format an EFI memory descriptor's type and attributes to a user-provided * character buffer, as per snprintf(), and return the buffer.
PATCH 7/40 efi: Remove global 'memmap'
In reply to Matt FlemingAbolish the poorly named EFI memory map, 'memmap'. It is shadowed by a bunch of local definitions in various files and having two ways to access the EFI memory map ('efi.memmap' vs 'memmap') is rather confusing.
Furthermore, ia64 doesn't even provide this global object, which has caused issues when trying to write generic EFI memmap code.
Replace all occurrences with efi.memmap, and convert the remaining iterator code to use for_each_efi_mem_desc().
--- arch/x86/platform/efi/efi.c | 84 +++++++++++++++++++++----------------- drivers/firmware/efi/arm-init.c | 20 ++++----- drivers/firmware/efi/arm-runtime.c | 12 +++--- drivers/firmware/efi/efi.c | 2 +- drivers/firmware/efi/fake_mem.c | 40 +++++++++--------- include/linux/efi.h | 5 +-- 6 files changed, 85 insertions(+), 78 deletions(-)
arch/x86/platform/efi/efi.c +47 -37
@@ -56,8 +56,6 @@#define EFI_DEBUG -struct efi_memory_map memmap; -static struct efi efi_phys__initdata ;static efi_system_table_t efi_systab__initdata ;
@@ -207,15 +205,13 @@ int __init efi_memblock_x86_reserve_range(void)#else pmap = (e->efi_memmap | ((__u64 )e->efi_memmap_hi <<32 ));#endif - memmap.phys_map = pmap; - memmap.nr_map = e->efi_memmap_size / + efi.memmap.phys_map = pmap; + efi.memmap.nr_map = e->efi_memmap_size / e->efi_memdesc_size; - memmap.desc_size = e->efi_memdesc_size; - memmap.desc_version = e->efi_memdesc_version; - -memblock_reserve (pmap, memmap.nr_map * memmap.desc_size); + efi.memmap.desc_size = e->efi_memdesc_size; + efi.memmap.desc_version = e->efi_memdesc_version; - efi.memmap = &memmap; +memblock_reserve (pmap, efi.memmap.nr_map * efi.memmap.desc_size);return 0 ; }
@@ -240,10 +236,14 @@ void __init efi_print_memmap(void)void __init efi_unmap_memmap (void ) { +unsigned long size; +clear_bit (EFI_MEMMAP , &efi.flags); -if (memmap.map) { -early_memunmap (memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map =NULL ; + + size = efi.memmap.nr_map * efi.memmap.desc_size; +if (efi.memmap.map) { +early_memunmap (efi.memmap.map, size); + efi.memmap.map =NULL ; } }
@@ -432,17 +432,22 @@ static int __init efi_runtime_init(void)static int __init efi_memmap_init (void ) { +unsigned long addr, size; +if (efi_enabled (EFI_PARAVIRT ))return 0 ;/* Map the EFI memory map */ - memmap.map =early_memremap ((unsigned long )memmap.phys_map, - memmap.nr_map * memmap.desc_size); -if (memmap.map ==NULL ) { + size = efi.memmap.nr_map * efi.memmap.desc_size; + addr = (unsigned long )efi.memmap.phys_map; + + efi.memmap.map =early_memremap (addr, size); +if (efi.memmap.map ==NULL ) {pr_err ("Could not map the memory map!\n" );return -ENOMEM ; } - memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); + + efi.memmap.map_end = efi.memmap.map + size;if (add_efi_memmap)do_add_efi_memmap ();
@@ -638,6 +643,7 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md)static void __init save_runtime_map (void ) {#ifdef CONFIG_KEXEC_CORE +unsigned long desc_size;efi_memory_desc_t *md;void *tmp, *q =NULL ;int count =0 ;
@@ -645,21 +651,23 @@ static void __init save_runtime_map(void)if (efi_enabled (EFI_OLD_MEMMAP ))return ; + desc_size = efi.memmap.desc_size; +for_each_efi_memory_desc (md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ) || (md->type ==EFI_BOOT_SERVICES_CODE ) || (md->type ==EFI_BOOT_SERVICES_DATA ))continue ; - tmp =krealloc (q, (count +1 ) * memmap.desc_size,GFP_KERNEL ); + tmp =krealloc (q, (count +1 ) * desc_size,GFP_KERNEL );if (!tmp) goto out; q = tmp; -memcpy (q + count * memmap.desc_size, md, memmap.desc_size); +memcpy (q + count * desc_size, md, desc_size); count++; } -efi_runtime_map_setup (q, count, memmap.desc_size); +efi_runtime_map_setup (q, count, desc_size);return ; out:
@@ -699,10 +707,10 @@ static inline void *efi_map_next_entry_reverse(void *entry) {/* Initial call */ if (!entry) -return memmap.map_end - memmap.desc_size; +return efi.memmap.map_end - efi.memmap.desc_size; - entry -= memmap.desc_size; -if (entry < memmap.map) + entry -= efi.memmap.desc_size; +if (entry < efi.memmap.map)return NULL ;return entry;
@@ -744,10 +752,10 @@ static void *efi_map_next_entry(void *entry)/* Initial call */ if (!entry) -return memmap.map; +return efi.memmap.map; - entry += memmap.desc_size; -if (entry >= memmap.map_end) + entry += efi.memmap.desc_size; +if (entry >= efi.memmap.map_end)return NULL ;return entry;
@@ -761,8 +769,11 @@ static void * __init efi_map_regions(int *count, int *pg_shift) {void *p, *new_memmap =NULL ;unsigned long left =0 ; +unsigned long desc_size;efi_memory_desc_t *md; + desc_size = efi.memmap.desc_size; + p =NULL ;while ((p =efi_map_next_entry (p))) { md = p;
@@ -777,7 +788,7 @@ static void * __init efi_map_regions(int *count, int *pg_shift)efi_map_region (md);get_systab_virt_addr (md); -if (left < memmap.desc_size) { +if (left < desc_size) { new_memmap =realloc_pages (new_memmap, *pg_shift);if (!new_memmap)return NULL ;
@@ -786,10 +797,9 @@ static void * __init efi_map_regions(int *count, int *pg_shift) (*pg_shift)++; } -memcpy (new_memmap + (*count * memmap.desc_size), md, - memmap.desc_size); +memcpy (new_memmap + (*count * desc_size), md, desc_size); - left -= memmap.desc_size; + left -= desc_size; (*count)++; }
@@ -833,10 +843,10 @@ static void __init kexec_enter_virtual_mode(void)BUG_ON (!efi.systab); - num_pages =ALIGN (memmap.nr_map * memmap.desc_size,PAGE_SIZE ); + num_pages =ALIGN (efi.memmap.nr_map * efi.memmap.desc_size,PAGE_SIZE ); num_pages >>=PAGE_SHIFT ; -if (efi_setup_page_tables (memmap.phys_map, num_pages)) { +if (efi_setup_page_tables (efi.memmap.phys_map, num_pages)) {clear_bit (EFI_RUNTIME_SERVICES , &efi.flags);return ; }
@@ -920,16 +930,16 @@ static void __init __efi_enter_virtual_mode(void)if (efi_is_native ()) { status =phys_efi_set_virtual_address_map ( - memmap.desc_size * count, - memmap.desc_size, - memmap.desc_version, + efi.memmap.desc_size * count, + efi.memmap.desc_size, + efi.memmap.desc_version, (efi_memory_desc_t *)__pa (new_memmap)); }else { status =efi_thunk_set_virtual_address_map ( efi_phys.set_virtual_address_map, - memmap.desc_size * count, - memmap.desc_size, - memmap.desc_version, + efi.memmap.desc_size * count, + efi.memmap.desc_size, + efi.memmap.desc_version, (efi_memory_desc_t *)__pa (new_memmap)); }
drivers/firmware/efi/arm-init.c +9 -11
@@ -20,8 +20,6 @@#include <asm/efi.h> -struct efi_memory_map memmap; -u64 efi_system_table;static int __init is_normal_ram (efi_memory_desc_t *md)
@@ -40,7 +38,7 @@ static phys_addr_t efi_to_phys(unsigned long addr) {efi_memory_desc_t *md; -for_each_efi_memory_desc_in_map (&memmap, md) { +for_each_efi_memory_desc (md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ;if (md->virt_addr ==0 )
@@ -145,7 +143,7 @@ static __init void reserve_regions(void)if (efi_enabled (EFI_DBG ))pr_info ("Processing EFI memory map:\n" ); -for_each_efi_memory_desc_in_map (&memmap, md) { +for_each_efi_memory_desc (md) { paddr = md->phys_addr; npages = md->num_pages;
@@ -186,9 +184,9 @@ void __init efi_init(void) efi_system_table = params.system_table; - memmap.phys_map = params.mmap; - memmap.map =early_memremap_ro (params.mmap, params.mmap_size); -if (memmap.map ==NULL ) { + efi.memmap.phys_map = params.mmap; + efi.memmap.map =early_memremap_ro (params.mmap, params.mmap_size); +if (efi.memmap.map ==NULL ) {/* * If we are booting via UEFI, the UEFI memory map is the only * description of memory we have, so there is little point in
@@ -196,15 +194,15 @@ void __init efi_init(void)*/ panic ("Unable to map EFI memory map.\n" ); } - memmap.map_end = memmap.map + params.mmap_size; - memmap.desc_size = params.desc_size; - memmap.desc_version = params.desc_ver; + efi.memmap.map_end = efi.memmap.map + params.mmap_size; + efi.memmap.desc_size = params.desc_size; + efi.memmap.desc_version = params.desc_ver;if (uefi_init () <0 )return ;reserve_regions (); -early_memunmap (memmap.map, params.mmap_size); +early_memunmap (efi.memmap.map, params.mmap_size);if (IS_ENABLED (CONFIG_ARM )) {/*
drivers/firmware/efi/arm-runtime.c +6 -6
@@ -103,15 +103,15 @@ static int __init arm_enable_runtime_services(void)pr_info ("Remapping and enabling EFI services.\n" ); - mapsize = memmap.map_end - memmap.map; - memmap.map = (__force void *)ioremap_cache (memmap.phys_map, - mapsize); -if (!memmap.map) { + mapsize = efi.memmap.map_end - efi.memmap.map; + + efi.memmap.map = (__force void *)ioremap_cache (efi.memmap.phys_map, + mapsize); +if (!efi.memmap.map) {pr_err ("Failed to remap EFI memory map\n" );return -ENOMEM ; } - memmap.map_end = memmap.map + mapsize; - efi.memmap = &memmap; + efi.memmap.map_end = efi.memmap.map + mapsize;if (!efi_virtmap_init ()) {pr_err ("UEFI virtual mapping missing or invalid -- runtime services will not be available\n" );
drivers/firmware/efi/efi.c +1 -1
@@ -256,7 +256,7 @@ subsys_initcall(efisubsys_init);*/ int __init efi_mem_desc_lookup (u64 phys_addr,efi_memory_desc_t *out_md) { -struct efi_memory_map *map = efi.memmap; +struct efi_memory_map *map = &efi.memmap;phys_addr_t p, e;if (!efi_enabled (EFI_MEMMAP )) {
drivers/firmware/efi/fake_mem.c +20 -20
@@ -57,7 +57,7 @@ static int __init cmp_fake_mem(const void *x1, const void *x2)void __init efi_fake_memmap (void ) {u64 start, end, m_start, m_end, m_attr; -int new_nr_map = memmap.nr_map; +int new_nr_map = efi.memmap.nr_map;efi_memory_desc_t *md;phys_addr_t new_memmap_phy;void *new_memmap;
@@ -94,25 +94,25 @@ void __init efi_fake_memmap(void) }/* allocate memory for new EFI memmap */ - new_memmap_phy =memblock_alloc (memmap.desc_size * new_nr_map, + new_memmap_phy =memblock_alloc (efi.memmap.desc_size * new_nr_map,PAGE_SIZE );if (!new_memmap_phy)return ;/* create new EFI memmap */ new_memmap =early_memremap (new_memmap_phy, - memmap.desc_size * new_nr_map); + efi.memmap.desc_size * new_nr_map);if (!new_memmap) { -memblock_free (new_memmap_phy, memmap.desc_size * new_nr_map); +memblock_free (new_memmap_phy, efi.memmap.desc_size * new_nr_map);return ; } -for (old = memmap.map, new = new_memmap; - old < memmap.map_end; - old += memmap.desc_size, new += memmap.desc_size) { +for (old = efi.memmap.map, new = new_memmap; + old < efi.memmap.map_end; + old += efi.memmap.desc_size, new += efi.memmap.desc_size) {/* copy original EFI memory descriptor */ -memcpy (new, old, memmap.desc_size); +memcpy (new, old, efi.memmap.desc_size); md = new; start = md->phys_addr; end = md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ) -1 ;
@@ -133,8 +133,8 @@ void __init efi_fake_memmap(void) md->num_pages = (m_end - md->phys_addr +1 ) >>EFI_PAGE_SHIFT ;/* latter part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_end +1 ; md->num_pages = (end - md->phys_addr + 1) >>
@@ -146,16 +146,16 @@ void __init efi_fake_memmap(void) md->num_pages = (m_start - md->phys_addr) >>EFI_PAGE_SHIFT ;/* middle part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->attribute |= m_attr; md->phys_addr = m_start; md->num_pages = (m_end - m_start +1 ) >>EFI_PAGE_SHIFT ;/* last part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_end +1 ; md->num_pages = (end - m_end) >>
@@ -168,8 +168,8 @@ void __init efi_fake_memmap(void) md->num_pages = (m_start - md->phys_addr) >>EFI_PAGE_SHIFT ;/* latter part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_start; md->num_pages = (end - md->phys_addr + 1) >>
@@ -181,10 +181,10 @@ void __init efi_fake_memmap(void)/* swap into new EFI memmap */ efi_unmap_memmap (); - memmap.map = new_memmap; - memmap.phys_map = new_memmap_phy; - memmap.nr_map = new_nr_map; - memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size; + efi.memmap.map = new_memmap; + efi.memmap.phys_map = new_memmap_phy; + efi.memmap.nr_map = new_nr_map; + efi.memmap.map_end = efi.memmap.map + efi.memmap.nr_map * efi.memmap.desc_size;set_bit (EFI_MEMMAP , &efi.flags);/* print new EFI memmap */
include/linux/efi.h +2 -3
@@ -883,7 +883,7 @@ extern struct efi {efi_get_next_high_mono_count_t *get_next_high_mono_count;efi_reset_system_t *reset_system;efi_set_virtual_address_map_t *set_virtual_address_map; -struct efi_memory_map *memmap; +struct efi_memory_map memmap;unsigned long flags; } efi;
@@ -945,7 +945,6 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,extern void efi_get_time (struct timespec *now);extern void efi_reserve_boot_services (void );extern int efi_get_fdt_params (struct efi_fdt_params *params); -extern struct efi_memory_map memmap;extern struct kobject *efi_kobj;extern int efi_reboot_quirk_mode;
@@ -970,7 +969,7 @@ static inline void efi_fake_memmap(void) { }* Once the loop finishes @md must not be accessed. */ #define for_each_efi_memory_desc (md) \ - for_each_efi_memory_desc_in_map(efi.memmap, md) + for_each_efi_memory_desc_in_map(&efi.memmap, md)/* * Format an EFI memory descriptor's type and attributes to a user-provided
Signature · 1 line
2.7.3
tip-bot for Matt Fleming
merge bot[tip:efi/core] efi: Remove global 'memmap' EFI memory map
efi: Remove global 'memmap' EFI memory map
Commit-ID: 884f4f66ffd6ffe632f3a8be4e6d10a858afdc37 Gitweb: http://git.kernel.org/tip/884f4f66ffd6ffe632f3a8be4e6d10a858afdc37 Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:39 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:51 +0200
efi: Remove global 'memmap' EFI memory map
Abolish the poorly named EFI memory map, 'memmap'. It is shadowed by a bunch of local definitions in various files and having two ways to access the EFI memory map ('efi.memmap' vs. 'memmap') is rather confusing.
Furthermore, IA64 doesn't even provide this global object, which has caused issues when trying to write generic EFI memmap code.
Replace all occurrences with efi.memmap, and convert the remaining iterator code to use for_each_efi_mem_desc().
--- arch/x86/platform/efi/efi.c | 84 +++++++++++++++++++++----------------- drivers/firmware/efi/arm-init.c | 20 ++++----- drivers/firmware/efi/arm-runtime.c | 12 +++--- drivers/firmware/efi/efi.c | 2 +- drivers/firmware/efi/fake_mem.c | 40 +++++++++--------- include/linux/efi.h | 5 +-- 6 files changed, 85 insertions(+), 78 deletions(-)
arch/x86/platform/efi/efi.c +47 -37
@@ -56,8 +56,6 @@#define EFI_DEBUG -struct efi_memory_map memmap; -static struct efi efi_phys__initdata ;static efi_system_table_t efi_systab__initdata ;
@@ -207,15 +205,13 @@ int __init efi_memblock_x86_reserve_range(void)#else pmap = (e->efi_memmap | ((__u64 )e->efi_memmap_hi <<32 ));#endif - memmap.phys_map = pmap; - memmap.nr_map = e->efi_memmap_size / + efi.memmap.phys_map = pmap; + efi.memmap.nr_map = e->efi_memmap_size / e->efi_memdesc_size; - memmap.desc_size = e->efi_memdesc_size; - memmap.desc_version = e->efi_memdesc_version; - -memblock_reserve (pmap, memmap.nr_map * memmap.desc_size); + efi.memmap.desc_size = e->efi_memdesc_size; + efi.memmap.desc_version = e->efi_memdesc_version; - efi.memmap = &memmap; +memblock_reserve (pmap, efi.memmap.nr_map * efi.memmap.desc_size);return 0 ; }
@@ -240,10 +236,14 @@ void __init efi_print_memmap(void)void __init efi_unmap_memmap (void ) { +unsigned long size; +clear_bit (EFI_MEMMAP , &efi.flags); -if (memmap.map) { -early_memunmap (memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map =NULL ; + + size = efi.memmap.nr_map * efi.memmap.desc_size; +if (efi.memmap.map) { +early_memunmap (efi.memmap.map, size); + efi.memmap.map =NULL ; } }
@@ -432,17 +432,22 @@ static int __init efi_runtime_init(void)static int __init efi_memmap_init (void ) { +unsigned long addr, size; +if (efi_enabled (EFI_PARAVIRT ))return 0 ;/* Map the EFI memory map */ - memmap.map =early_memremap ((unsigned long )memmap.phys_map, - memmap.nr_map * memmap.desc_size); -if (memmap.map ==NULL ) { + size = efi.memmap.nr_map * efi.memmap.desc_size; + addr = (unsigned long )efi.memmap.phys_map; + + efi.memmap.map =early_memremap (addr, size); +if (efi.memmap.map ==NULL ) {pr_err ("Could not map the memory map!\n" );return -ENOMEM ; } - memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); + + efi.memmap.map_end = efi.memmap.map + size;if (add_efi_memmap)do_add_efi_memmap ();
@@ -638,6 +643,7 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md)static void __init save_runtime_map (void ) {#ifdef CONFIG_KEXEC_CORE +unsigned long desc_size;efi_memory_desc_t *md;void *tmp, *q =NULL ;int count =0 ;
@@ -645,21 +651,23 @@ static void __init save_runtime_map(void)if (efi_enabled (EFI_OLD_MEMMAP ))return ; + desc_size = efi.memmap.desc_size; +for_each_efi_memory_desc (md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ) || (md->type ==EFI_BOOT_SERVICES_CODE ) || (md->type ==EFI_BOOT_SERVICES_DATA ))continue ; - tmp =krealloc (q, (count +1 ) * memmap.desc_size,GFP_KERNEL ); + tmp =krealloc (q, (count +1 ) * desc_size,GFP_KERNEL );if (!tmp) goto out; q = tmp; -memcpy (q + count * memmap.desc_size, md, memmap.desc_size); +memcpy (q + count * desc_size, md, desc_size); count++; } -efi_runtime_map_setup (q, count, memmap.desc_size); +efi_runtime_map_setup (q, count, desc_size);return ; out:
@@ -699,10 +707,10 @@ static inline void *efi_map_next_entry_reverse(void *entry) {/* Initial call */ if (!entry) -return memmap.map_end - memmap.desc_size; +return efi.memmap.map_end - efi.memmap.desc_size; - entry -= memmap.desc_size; -if (entry < memmap.map) + entry -= efi.memmap.desc_size; +if (entry < efi.memmap.map)return NULL ;return entry;
@@ -744,10 +752,10 @@ static void *efi_map_next_entry(void *entry)/* Initial call */ if (!entry) -return memmap.map; +return efi.memmap.map; - entry += memmap.desc_size; -if (entry >= memmap.map_end) + entry += efi.memmap.desc_size; +if (entry >= efi.memmap.map_end)return NULL ;return entry;
@@ -761,8 +769,11 @@ static void * __init efi_map_regions(int *count, int *pg_shift) {void *p, *new_memmap =NULL ;unsigned long left =0 ; +unsigned long desc_size;efi_memory_desc_t *md; + desc_size = efi.memmap.desc_size; + p =NULL ;while ((p =efi_map_next_entry (p))) { md = p;
@@ -777,7 +788,7 @@ static void * __init efi_map_regions(int *count, int *pg_shift)efi_map_region (md);get_systab_virt_addr (md); -if (left < memmap.desc_size) { +if (left < desc_size) { new_memmap =realloc_pages (new_memmap, *pg_shift);if (!new_memmap)return NULL ;
@@ -786,10 +797,9 @@ static void * __init efi_map_regions(int *count, int *pg_shift) (*pg_shift)++; } -memcpy (new_memmap + (*count * memmap.desc_size), md, - memmap.desc_size); +memcpy (new_memmap + (*count * desc_size), md, desc_size); - left -= memmap.desc_size; + left -= desc_size; (*count)++; }
@@ -833,10 +843,10 @@ static void __init kexec_enter_virtual_mode(void)BUG_ON (!efi.systab); - num_pages =ALIGN (memmap.nr_map * memmap.desc_size,PAGE_SIZE ); + num_pages =ALIGN (efi.memmap.nr_map * efi.memmap.desc_size,PAGE_SIZE ); num_pages >>=PAGE_SHIFT ; -if (efi_setup_page_tables (memmap.phys_map, num_pages)) { +if (efi_setup_page_tables (efi.memmap.phys_map, num_pages)) {clear_bit (EFI_RUNTIME_SERVICES , &efi.flags);return ; }
@@ -920,16 +930,16 @@ static void __init __efi_enter_virtual_mode(void)if (efi_is_native ()) { status =phys_efi_set_virtual_address_map ( - memmap.desc_size * count, - memmap.desc_size, - memmap.desc_version, + efi.memmap.desc_size * count, + efi.memmap.desc_size, + efi.memmap.desc_version, (efi_memory_desc_t *)__pa (new_memmap)); }else { status =efi_thunk_set_virtual_address_map ( efi_phys.set_virtual_address_map, - memmap.desc_size * count, - memmap.desc_size, - memmap.desc_version, + efi.memmap.desc_size * count, + efi.memmap.desc_size, + efi.memmap.desc_version, (efi_memory_desc_t *)__pa (new_memmap)); }
drivers/firmware/efi/arm-init.c +9 -11
@@ -20,8 +20,6 @@#include <asm/efi.h> -struct efi_memory_map memmap; -u64 efi_system_table;static int __init is_normal_ram (efi_memory_desc_t *md)
@@ -40,7 +38,7 @@ static phys_addr_t efi_to_phys(unsigned long addr) {efi_memory_desc_t *md; -for_each_efi_memory_desc_in_map (&memmap, md) { +for_each_efi_memory_desc (md) {if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ;if (md->virt_addr ==0 )
@@ -145,7 +143,7 @@ static __init void reserve_regions(void)if (efi_enabled (EFI_DBG ))pr_info ("Processing EFI memory map:\n" ); -for_each_efi_memory_desc_in_map (&memmap, md) { +for_each_efi_memory_desc (md) { paddr = md->phys_addr; npages = md->num_pages;
@@ -186,9 +184,9 @@ void __init efi_init(void) efi_system_table = params.system_table; - memmap.phys_map = params.mmap; - memmap.map =early_memremap_ro (params.mmap, params.mmap_size); -if (memmap.map ==NULL ) { + efi.memmap.phys_map = params.mmap; + efi.memmap.map =early_memremap_ro (params.mmap, params.mmap_size); +if (efi.memmap.map ==NULL ) {/* * If we are booting via UEFI, the UEFI memory map is the only * description of memory we have, so there is little point in
@@ -196,15 +194,15 @@ void __init efi_init(void)*/ panic ("Unable to map EFI memory map.\n" ); } - memmap.map_end = memmap.map + params.mmap_size; - memmap.desc_size = params.desc_size; - memmap.desc_version = params.desc_ver; + efi.memmap.map_end = efi.memmap.map + params.mmap_size; + efi.memmap.desc_size = params.desc_size; + efi.memmap.desc_version = params.desc_ver;if (uefi_init () <0 )return ;reserve_regions (); -early_memunmap (memmap.map, params.mmap_size); +early_memunmap (efi.memmap.map, params.mmap_size);if (IS_ENABLED (CONFIG_ARM )) {/*
drivers/firmware/efi/arm-runtime.c +6 -6
@@ -103,15 +103,15 @@ static int __init arm_enable_runtime_services(void)pr_info ("Remapping and enabling EFI services.\n" ); - mapsize = memmap.map_end - memmap.map; - memmap.map = (__force void *)ioremap_cache (memmap.phys_map, - mapsize); -if (!memmap.map) { + mapsize = efi.memmap.map_end - efi.memmap.map; + + efi.memmap.map = (__force void *)ioremap_cache (efi.memmap.phys_map, + mapsize); +if (!efi.memmap.map) {pr_err ("Failed to remap EFI memory map\n" );return -ENOMEM ; } - memmap.map_end = memmap.map + mapsize; - efi.memmap = &memmap; + efi.memmap.map_end = efi.memmap.map + mapsize;if (!efi_virtmap_init ()) {pr_err ("UEFI virtual mapping missing or invalid -- runtime services will not be available\n" );
drivers/firmware/efi/efi.c +1 -1
@@ -256,7 +256,7 @@ subsys_initcall(efisubsys_init);*/ int __init efi_mem_desc_lookup (u64 phys_addr,efi_memory_desc_t *out_md) { -struct efi_memory_map *map = efi.memmap; +struct efi_memory_map *map = &efi.memmap;phys_addr_t p, e;if (!efi_enabled (EFI_MEMMAP )) {
drivers/firmware/efi/fake_mem.c +20 -20
@@ -57,7 +57,7 @@ static int __init cmp_fake_mem(const void *x1, const void *x2)void __init efi_fake_memmap (void ) {u64 start, end, m_start, m_end, m_attr; -int new_nr_map = memmap.nr_map; +int new_nr_map = efi.memmap.nr_map;efi_memory_desc_t *md;phys_addr_t new_memmap_phy;void *new_memmap;
@@ -94,25 +94,25 @@ void __init efi_fake_memmap(void) }/* allocate memory for new EFI memmap */ - new_memmap_phy =memblock_alloc (memmap.desc_size * new_nr_map, + new_memmap_phy =memblock_alloc (efi.memmap.desc_size * new_nr_map,PAGE_SIZE );if (!new_memmap_phy)return ;/* create new EFI memmap */ new_memmap =early_memremap (new_memmap_phy, - memmap.desc_size * new_nr_map); + efi.memmap.desc_size * new_nr_map);if (!new_memmap) { -memblock_free (new_memmap_phy, memmap.desc_size * new_nr_map); +memblock_free (new_memmap_phy, efi.memmap.desc_size * new_nr_map);return ; } -for (old = memmap.map, new = new_memmap; - old < memmap.map_end; - old += memmap.desc_size, new += memmap.desc_size) { +for (old = efi.memmap.map, new = new_memmap; + old < efi.memmap.map_end; + old += efi.memmap.desc_size, new += efi.memmap.desc_size) {/* copy original EFI memory descriptor */ -memcpy (new, old, memmap.desc_size); +memcpy (new, old, efi.memmap.desc_size); md = new; start = md->phys_addr; end = md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ) -1 ;
@@ -133,8 +133,8 @@ void __init efi_fake_memmap(void) md->num_pages = (m_end - md->phys_addr +1 ) >>EFI_PAGE_SHIFT ;/* latter part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_end +1 ; md->num_pages = (end - md->phys_addr + 1) >>
@@ -146,16 +146,16 @@ void __init efi_fake_memmap(void) md->num_pages = (m_start - md->phys_addr) >>EFI_PAGE_SHIFT ;/* middle part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->attribute |= m_attr; md->phys_addr = m_start; md->num_pages = (m_end - m_start +1 ) >>EFI_PAGE_SHIFT ;/* last part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_end +1 ; md->num_pages = (end - m_end) >>
@@ -168,8 +168,8 @@ void __init efi_fake_memmap(void) md->num_pages = (m_start - md->phys_addr) >>EFI_PAGE_SHIFT ;/* latter part */ - new += memmap.desc_size; -memcpy (new, old, memmap.desc_size); + new += efi.memmap.desc_size; +memcpy (new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_start; md->num_pages = (end - md->phys_addr + 1) >>
@@ -181,10 +181,10 @@ void __init efi_fake_memmap(void)/* swap into new EFI memmap */ efi_unmap_memmap (); - memmap.map = new_memmap; - memmap.phys_map = new_memmap_phy; - memmap.nr_map = new_nr_map; - memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size; + efi.memmap.map = new_memmap; + efi.memmap.phys_map = new_memmap_phy; + efi.memmap.nr_map = new_nr_map; + efi.memmap.map_end = efi.memmap.map + efi.memmap.nr_map * efi.memmap.desc_size;set_bit (EFI_MEMMAP , &efi.flags);/* print new EFI memmap */
include/linux/efi.h +2 -3
@@ -883,7 +883,7 @@ extern struct efi {efi_get_next_high_mono_count_t *get_next_high_mono_count;efi_reset_system_t *reset_system;efi_set_virtual_address_map_t *set_virtual_address_map; -struct efi_memory_map *memmap; +struct efi_memory_map memmap;unsigned long flags; } efi;
@@ -945,7 +945,6 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,extern void efi_get_time (struct timespec *now);extern void efi_reserve_boot_services (void );extern int efi_get_fdt_params (struct efi_fdt_params *params); -extern struct efi_memory_map memmap;extern struct kobject *efi_kobj;extern int efi_reboot_quirk_mode;
@@ -970,7 +969,7 @@ static inline void efi_fake_memmap(void) { }* Once the loop finishes @md must not be accessed. */ #define for_each_efi_memory_desc (md) \ - for_each_efi_memory_desc_in_map(efi.memmap, md) + for_each_efi_memory_desc_in_map(&efi.memmap, md)/* * Format an EFI memory descriptor's type and attributes to a user-provided
PATCH 1/1 efi: Remove unnecessary (and buggy) .memmap initialization from the Xen EFI driver
Quoted 29 lines · tip-bot for Matt Fleming
Commit-ID: 884f4f66ffd6ffe632f3a8be4e6d10a858afdc37 Gitweb: http://git.kernel.org/tip/884f4f66ffd6ffe632f3a8be4e6d10a858afdc37 Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:39 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:51 +0200efi: Remove global 'memmap' EFI memory map
Abolish the poorly named EFI memory map, 'memmap'. It is shadowed by a bunch of local definitions in various files and having two ways to access the EFI memory map ('efi.memmap' vs. 'memmap') is rather confusing.
Furthermore, IA64 doesn't even provide this global object, which has caused issues when trying to write generic EFI memmap code.
Replace all occurrences with efi.memmap, and convert the remaining iterator code to use
for_each_efi_mem_desc().Signed-off-by Matt Fleming <[email protected]>Reviewed-by Ard Biesheuvel <[email protected]>Cc Borislav Petkov <[email protected]>Cc Luck, Tony <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Thomas Gleixner <[email protected]>Signed-off-by Ingo Molnar <[email protected]>
Quoted 8 lines
--- arch/x86/platform/efi/efi.c | 84 +++++++++++++++++++++----------------- drivers/firmware/efi/arm-init.c | 20 ++++----- drivers/firmware/efi/arm-runtime.c | 12 +++--- drivers/firmware/efi/efi.c | 2 +- drivers/firmware/efi/fake_mem.c | 40 +++++++++--------- include/linux/efi.h | 5 +-- 6 files changed, 85 insertions(+), 78 deletions(-)
So this commit triggered the follwing build warning on x86 64-bit allyesconfig:
In file included from ./include/uapi/linux/posix_types.h:4:0,
from include/uapi/linux/types.h:13,
from include/linux/compiler.h:203,
from include/asm-generic/bug.h:4,
from ./arch/x86/include/asm/bug.h:35,
from include/linux/bug.h:4,
from drivers/xen/efi.c:21:
include/linux/stddef.h:7:14: warning: initialization makes integer from pointer without a cast [-Wint-conversion]
#define NULL ((void *)0)
^
drivers/xen/efi.c:319:30: note: in expansion of macro ‘NULL’
.memmap = NULL, /* Not used under Xen. */
^
CC drivers/gpu/drm/i915/intel_acpi.o
include/linux/stddef.h:7:14: note: (near initialization for ‘efi_xen.memmap.phys_map’)
#define NULL ((void *)0)
^
drivers/xen/efi.c:319:30: note: in expansion of macro ‘NULL’
.memmap = NULL, /* Not used under Xen. */
^
drivers/xen/efi.c:290:47: warning: missing braces around initializer [-Wmissing-braces]
static const struct efi efi_xen __initconst = {
^drivers/xen/efi.c:290:47: note: (near initialization for ‘efi_xen’)
It's this initialization in drivers/xen/efi.c:
static const struct efi efi_xen __initconst = {
...
.memmap = NULL, /* Not used under Xen. */
...which was forgotten about, as .memmap now is an embedded struct:
struct efi_memory_map memmap;
We can remove this initialization - it's an EFI core internal data structure plus it's not used in the Xen driver anyway.
--- drivers/xen/efi.c | 1 - 1 file changed, 1 deletion(-)
drivers/xen/efi.c +0 -1
@@ -316,7 +316,6 @@ static const struct efi efi_xen __initconst = { .get_next_high_mono_count = xen_efi_get_next_high_mono_count, .reset_system = NULL, /* Functionality provided by Xen. */ .set_virtual_address_map = NULL, /* Not used under Xen. */ - .memmap = NULL, /* Not used under Xen. */ .flags = 0 /* Initialized later. */ };
Re: [PATCH] efi: Remove unnecessary (and buggy) .memmap initialization from the Xen EFI driver
Quoted 2 lines · Ingo Molnar
So this commit triggered the follwing build warning on x86 64-bit allyesconfig:
Doh! I wonder why the 0day bot didn't tell me about this?
Quoted 11 lines
It's this initialization in
drivers/xen/efi.c:static const struct efi efi_xen __initconst = { ... .memmap = NULL, /* Not used under Xen. */ ...which was forgotten about, as .memmap now is an embedded struct:
struct efi_memory_map memmap;
Quoted 7 lines
We can remove this initialization - it's an EFI core internal data structure plus it's not used in the Xen driver anyway.
Signed-off-by Ingo Molnar <[email protected]>--- drivers/xen/efi.c | 1 - 1 file changed, 1 deletion(-)
Yep, looks good. Thanks Ingo!
tip-bot for Ingo Molnar
merge bot[tip:efi/core] efi: Remove unnecessary (and buggy) .memmap initialization from the Xen EFI driver
In reply to Ingo Molnarefi: Remove unnecessary (and buggy) .memmap initialization from the Xen EFI driver
Commit-ID: 0ec7ae928a9c19c2b7b8054507d5694a2597065e Gitweb: http://git.kernel.org/tip/0ec7ae928a9c19c2b7b8054507d5694a2597065e Author: Ingo Molnar <[email protected]> AuthorDate: Fri, 29 Apr 2016 10:31:28 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 29 Apr 2016 11:06:15 +0200
efi: Remove unnecessary (and buggy) .memmap initialization from the Xen EFI driver
So the following commit:
884f4f66ffd6 ("efi: Remove global 'memmap' EFI memory map")
... triggered the following build warning on x86 64-bit allyesconfig:
drivers/xen/efi.c:290:47: warning: missing braces around initializer [-Wmissing-braces]
It's this initialization in drivers/xen/efi.c:
static const struct efi efi_xen __initconst = {
...
.memmap = NULL, /* Not used under Xen. */
...which was forgotten about, as .memmap now is an embedded struct:
struct efi_memory_map memmap;
We can remove this initialization - it's an EFI core internal data structure plus it's not used in the Xen driver anyway.
--- drivers/xen/efi.c | 1 - 1 file changed, 1 deletion(-)
drivers/xen/efi.c +0 -1
@@ -316,7 +316,6 @@ static const struct efi efi_xen __initconst = { .get_next_high_mono_count = xen_efi_get_next_high_mono_count, .reset_system = NULL, /* Functionality provided by Xen. */ .set_virtual_address_map = NULL, /* Not used under Xen. */ - .memmap = NULL, /* Not used under Xen. */ .flags = 0 /* Initialized later. */ };
PATCH 8/40 efi: Check EFI_MEMORY_DESCRIPTOR version explicitly
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Our efi_memory_desc_t type is based on EFI_MEMORY_DESCRIPTOR version 1 in the UEFI spec. No version updates are expected, but since we are about to introduce support for new firmware tables that use the same descriptor type, it makes sense to at least warn if we encounter other versions.
--- arch/x86/platform/efi/efi.c | 4 ++++ drivers/firmware/efi/arm-init.c | 4 ++++ 2 files changed, 8 insertions(+)
arch/x86/platform/efi/efi.c +4 -0
@@ -211,6 +211,10 @@ int __init efi_memblock_x86_reserve_range(void) efi.memmap.desc_size = e->efi_memdesc_size; efi.memmap.desc_version = e->efi_memdesc_version; +WARN (efi.memmap.desc_version !=1 , +"Unexpected EFI_MEMORY_DESCRIPTOR version %ld" , + efi.memmap.desc_version); +memblock_reserve (pmap, efi.memmap.nr_map * efi.memmap.desc_size);return 0 ;
drivers/firmware/efi/arm-init.c +4 -0
@@ -198,6 +198,10 @@ void __init efi_init(void) efi.memmap.desc_size = params.desc_size; efi.memmap.desc_version = params.desc_ver; +WARN (efi.memmap.desc_version !=1 , +"Unexpected EFI_MEMORY_DESCRIPTOR version %ld" , + efi.memmap.desc_version); +if (uefi_init () <0 )return ;
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi: Check EFI_MEMORY_DESCRIPTOR version explicitly
efi: Check EFI_MEMORY_DESCRIPTOR version explicitly
Commit-ID: 0d054ad96e97dcd8966e9333eabcc7a466672f70 Gitweb: http://git.kernel.org/tip/0d054ad96e97dcd8966e9333eabcc7a466672f70 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:40 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:51 +0200
efi: Check EFI_MEMORY_DESCRIPTOR version explicitly
Our efi_memory_desc_t type is based on EFI_MEMORY_DESCRIPTOR version 1 in the UEFI spec. No version updates are expected, but since we are about to introduce support for new firmware tables that use the same descriptor type, it makes sense to at least warn if we encounter other versions.
--- arch/x86/platform/efi/efi.c | 4 ++++ drivers/firmware/efi/arm-init.c | 4 ++++ 2 files changed, 8 insertions(+)
arch/x86/platform/efi/efi.c +4 -0
@@ -211,6 +211,10 @@ int __init efi_memblock_x86_reserve_range(void) efi.memmap.desc_size = e->efi_memdesc_size; efi.memmap.desc_version = e->efi_memdesc_version; +WARN (efi.memmap.desc_version !=1 , +"Unexpected EFI_MEMORY_DESCRIPTOR version %ld" , + efi.memmap.desc_version); +memblock_reserve (pmap, efi.memmap.nr_map * efi.memmap.desc_size);return 0 ;
drivers/firmware/efi/arm-init.c +4 -0
@@ -198,6 +198,10 @@ void __init efi_init(void) efi.memmap.desc_size = params.desc_size; efi.memmap.desc_version = params.desc_ver; +WARN (efi.memmap.desc_version !=1 , +"Unexpected EFI_MEMORY_DESCRIPTOR version %ld" , + efi.memmap.desc_version); +if (uefi_init () <0 )return ;
PATCH 9/40 efi/arm*: Use memremap() to create the persistent memmap mapping
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Instead of using ioremap_cache(), which is slightly inappropriate for mapping firmware tables, and is not even allowed on ARM for mapping regions that are covered by a struct page, use memremap(), which was invented for this purpose, and will also reuse the existing kernel direct mapping if the requested region is covered by it.
--- drivers/firmware/efi/arm-runtime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/firmware/efi/arm-runtime.c +1 -2
@@ -105,8 +105,7 @@ static int __init arm_enable_runtime_services(void) mapsize = efi.memmap.map_end - efi.memmap.map; - efi.memmap.map = (__force void *)ioremap_cache (efi.memmap.phys_map, - mapsize); + efi.memmap.map =memremap (efi.memmap.phys_map, mapsize,MEMREMAP_WB );if (!efi.memmap.map) {pr_err ("Failed to remap EFI memory map\n" );return -ENOMEM ;
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/arm*: Use memremap() to create the persistent memmap mapping
efi/arm*: Use memremap() to create the persistent memmap mapping
Commit-ID: 24d45d1dc275b818093fe1d0055a230ce5e8c4c7 Gitweb: http://git.kernel.org/tip/24d45d1dc275b818093fe1d0055a230ce5e8c4c7 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:41 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:52 +0200
efi/arm*: Use memremap() to create the persistent memmap mapping
Instead of using ioremap_cache(), which is slightly inappropriate for mapping firmware tables, and is not even allowed on ARM for mapping regions that are covered by a struct page, use memremap(), which was invented for this purpose, and will also reuse the existing kernel direct mapping if the requested region is covered by it.
--- drivers/firmware/efi/arm-runtime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/firmware/efi/arm-runtime.c +1 -2
@@ -105,8 +105,7 @@ static int __init arm_enable_runtime_services(void) mapsize = efi.memmap.map_end - efi.memmap.map; - efi.memmap.map = (__force void *)ioremap_cache (efi.memmap.phys_map, - mapsize); + efi.memmap.map =memremap (efi.memmap.phys_map, mapsize,MEMREMAP_WB );if (!efi.memmap.map) {pr_err ("Failed to remap EFI memory map\n" );return -ENOMEM ;
PATCH 10/40 ARM: efi: Apply strict permissons for UEFI Runtime Services regions
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Recent UEFI versions expose permission attributes for runtime services memory regions, either in the UEFI memory map or in the separate memory attributes table. This allows the kernel to map these regions with stricter permissions, rather than the RWX permissions that are used by default. So wire this up in our mapping routine.
--- arch/arm/include/asm/efi.h | 1 + arch/arm/kernel/efi.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+)
arch/arm/include/asm/efi.h +1 -0
@@ -22,6 +22,7 @@void efi_init (void );int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md); +int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md);#define efi_call_virt (f, ...) \ ({ \
arch/arm/kernel/efi.c +41 -0
52 lines not on this page · raw message
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] ARM/efi: Apply strict permissions for UEFI Runtime Services regions
ARM/efi: Apply strict permissions for UEFI Runtime Services regions
Commit-ID: 9fc68b717c24a215a32c1b4e05b30433cafb2599 Gitweb: http://git.kernel.org/tip/9fc68b717c24a215a32c1b4e05b30433cafb2599 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:42 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:53 +0200
ARM/efi: Apply strict permissions for UEFI Runtime Services regions
Recent UEFI versions expose permission attributes for runtime services memory regions, either in the UEFI memory map or in the separate memory attributes table. This allows the kernel to map these regions with stricter permissions, rather than the RWX permissions that are used by default. So wire this up in our mapping routine.
--- arch/arm/include/asm/efi.h | 1 + arch/arm/kernel/efi.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+)
arch/arm/include/asm/efi.h +1 -0
@@ -22,6 +22,7 @@void efi_init (void );int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md); +int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md);#define efi_call_virt (f, ...) \ ({ \
arch/arm/kernel/efi.c +41 -0
52 lines not on this page · raw message
PATCH 11/40 arm64: efi: Apply strict permissons for UEFI Runtime Services regions
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Recent UEFI versions expose permission attributes for runtime services memory regions, either in the UEFI memory map or in the separate memory attributes table. This allows the kernel to map these regions with stricter permissions, rather than the RWX permissions that are used by default. So wire this up in our mapping routine.
Note that in the absence of permission attributes, we still only map regions of type EFI_RUNTIME_SERVICE_CODE with the executable bit set. Also, we base the mapping attributes of EFI_MEMORY_MAPPED_IO on the type directly rather than on the absence of the EFI_MEMORY_WB attribute. This is more correct, but is also required for compatibility with the upcoming support for the Memory Attributes Table, which only carries permission attributes, not memory type attributes.
--- arch/arm64/kernel/efi.c | 54 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 14 deletions(-)
arch/arm64/kernel/efi.c +40 -14
@@ -17,22 +17,48 @@#include <asm/efi.h> -int __init efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md) +/* +* Only regions of type EFI_RUNTIME_SERVICES_CODE need to be +* executable, everything else can be mapped with the XN bits +* set. Also take the new (optional) RO/XP bits into account. +*/ +static __init pteval_t create_mapping_protection (efi_memory_desc_t *md) { -pteval_t prot_val; +u64 attr = md->attribute; +u32 type = md->type; -/* -* Only regions of type EFI_RUNTIME_SERVICES_CODE need to be -* executable, everything else can be mapped with the XN bits -* set. -*/ -if ((md->attribute &EFI_MEMORY_WB ) ==0 ) - prot_val = PROT_DEVICE_nGnRE; -else if (md->type ==EFI_RUNTIME_SERVICES_CODE || - !PAGE_ALIGNED (md->phys_addr)) - prot_val =pgprot_val (PAGE_KERNEL_EXEC ); -else - prot_val =pgprot_val (PAGE_KERNEL ); +if (type ==EFI_MEMORY_MAPPED_IO ) +return PROT_DEVICE_nGnRE; + +if (WARN_ONCE (!PAGE_ALIGNED (md->phys_addr), +"UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?" )) +/* +* If the region is not aligned to the page size of the OS, we +* can not use strict permissions, since that would also affect +* the mapping attributes of the adjacent regions. +*/ +return pgprot_val (PAGE_KERNEL_EXEC ); + +/* R-- */ +if ((attr & (EFI_MEMORY_XP |EFI_MEMORY_RO )) == + (EFI_MEMORY_XP |EFI_MEMORY_RO )) +return pgprot_val (PAGE_KERNEL_RO ); + +/* R-X */ +if (attr &EFI_MEMORY_RO ) +return pgprot_val (PAGE_KERNEL_ROX ); + +/* RW- */ +if (attr &EFI_MEMORY_XP || type !=EFI_RUNTIME_SERVICES_CODE ) +return pgprot_val (PAGE_KERNEL ); + +/* RWX */ +return pgprot_val (PAGE_KERNEL_EXEC ); +} + +int __init efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md) +{ +pteval_t prot_val =create_mapping_protection (md); create_pgd_mapping(mm, md->phys_addr, md->virt_addr, md->num_pages << EFI_PAGE_SHIFT,
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] arm64/efi: Apply strict permissions to UEFI Runtime Services regions
arm64/efi: Apply strict permissions to UEFI Runtime Services regions
Commit-ID: 1fd55a9a09b0293af95ab4299b108f030fef4464 Gitweb: http://git.kernel.org/tip/1fd55a9a09b0293af95ab4299b108f030fef4464 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:43 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:53 +0200
arm64/efi: Apply strict permissions to UEFI Runtime Services regions
Recent UEFI versions expose permission attributes for runtime services memory regions, either in the UEFI memory map or in the separate memory attributes table. This allows the kernel to map these regions with stricter permissions, rather than the RWX permissions that are used by default. So wire this up in our mapping routine.
Note that in the absence of permission attributes, we still only map regions of type EFI_RUNTIME_SERVICE_CODE with the executable bit set. Also, we base the mapping attributes of EFI_MEMORY_MAPPED_IO on the type directly rather than on the absence of the EFI_MEMORY_WB attribute. This is more correct, but is also required for compatibility with the upcoming support for the Memory Attributes Table, which only carries permission attributes, not memory type attributes.
--- arch/arm64/kernel/efi.c | 54 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 14 deletions(-)
arch/arm64/kernel/efi.c +40 -14
@@ -17,22 +17,48 @@#include <asm/efi.h> -int __init efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md) +/* +* Only regions of type EFI_RUNTIME_SERVICES_CODE need to be +* executable, everything else can be mapped with the XN bits +* set. Also take the new (optional) RO/XP bits into account. +*/ +static __init pteval_t create_mapping_protection (efi_memory_desc_t *md) { -pteval_t prot_val; +u64 attr = md->attribute; +u32 type = md->type; -/* -* Only regions of type EFI_RUNTIME_SERVICES_CODE need to be -* executable, everything else can be mapped with the XN bits -* set. -*/ -if ((md->attribute &EFI_MEMORY_WB ) ==0 ) - prot_val = PROT_DEVICE_nGnRE; -else if (md->type ==EFI_RUNTIME_SERVICES_CODE || - !PAGE_ALIGNED (md->phys_addr)) - prot_val =pgprot_val (PAGE_KERNEL_EXEC ); -else - prot_val =pgprot_val (PAGE_KERNEL ); +if (type ==EFI_MEMORY_MAPPED_IO ) +return PROT_DEVICE_nGnRE; + +if (WARN_ONCE (!PAGE_ALIGNED (md->phys_addr), +"UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?" )) +/* +* If the region is not aligned to the page size of the OS, we +* can not use strict permissions, since that would also affect +* the mapping attributes of the adjacent regions. +*/ +return pgprot_val (PAGE_KERNEL_EXEC ); + +/* R-- */ +if ((attr & (EFI_MEMORY_XP |EFI_MEMORY_RO )) == + (EFI_MEMORY_XP |EFI_MEMORY_RO )) +return pgprot_val (PAGE_KERNEL_RO ); + +/* R-X */ +if (attr &EFI_MEMORY_RO ) +return pgprot_val (PAGE_KERNEL_ROX ); + +/* RW- */ +if (attr &EFI_MEMORY_XP || type !=EFI_RUNTIME_SERVICES_CODE ) +return pgprot_val (PAGE_KERNEL ); + +/* RWX */ +return pgprot_val (PAGE_KERNEL_EXEC ); +} + +int __init efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md) +{ +pteval_t prot_val =create_mapping_protection (md); create_pgd_mapping(mm, md->phys_addr, md->virt_addr, md->num_pages << EFI_PAGE_SHIFT,
PATCH 12/40 efi: Add support for the EFI_MEMORY_ATTRIBUTES_TABLE config table
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
This declares the GUID and struct typedef for the new memory attributes table which contains the permissions that can be used to apply stricter permissions to UEFI Runtime Services memory regions.
--- drivers/firmware/efi/efi.c | 2 ++ include/linux/efi.h | 13 +++++++++++++ 2 files changed, 15 insertions(+)
drivers/firmware/efi/efi.c +2 -0
@@ -43,6 +43,7 @@ struct efi __read_mostly efi = { .config_table = EFI_INVALID_TABLE_ADDR, .esrt = EFI_INVALID_TABLE_ADDR, .properties_table = EFI_INVALID_TABLE_ADDR, + .mem_attr_table = EFI_INVALID_TABLE_ADDR, };EXPORT_SYMBOL (efi);
@@ -338,6 +339,7 @@ static __initdata efi_config_table_type_t common_tables[] = { {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, + {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, {NULL_GUID, NULL, NULL}, };
include/linux/efi.h +13 -0
@@ -623,6 +623,10 @@ void efi_native_runtime_setup(void);EFI_GUID (0x3152bca5 ,0xeade ,0x433d , \ 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) +#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID \ + EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, \ + 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) + typedef struct { efi_guid_t guid; u64 table;
@@ -847,6 +851,14 @@ typedef struct {#define EFI_INVALID_TABLE_ADDR (~0UL) +typedef struct { +u32 version; +u32 num_entries; +u32 desc_size; +u32 reserved; +efi_memory_desc_t entry[0 ]; +}efi_memory_attributes_table_t ; +/* * All runtime access to EFI goes through this structure: */
@@ -868,6 +880,7 @@ extern struct efi {unsigned long config_table;/* config tables */ unsigned long esrt;/* ESRT table */ unsigned long properties_table;/* properties table */ +unsigned long mem_attr_table;/* memory attributes table */ efi_get_time_t *get_time;efi_set_time_t *set_time;efi_get_wakeup_time_t *get_wakeup_time;
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi: Add support for the EFI_MEMORY_ATTRIBUTES_TABLE config table
efi: Add support for the EFI_MEMORY_ATTRIBUTES_TABLE config table
Commit-ID: a604af075a3226adaff84b7026876f0c6dfe9f52 Gitweb: http://git.kernel.org/tip/a604af075a3226adaff84b7026876f0c6dfe9f52 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:44 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:54 +0200
efi: Add support for the EFI_MEMORY_ATTRIBUTES_TABLE config table
This declares the GUID and struct typedef for the new memory attributes table which contains the permissions that can be used to apply stricter permissions to UEFI Runtime Services memory regions.
--- drivers/firmware/efi/efi.c | 2 ++ include/linux/efi.h | 13 +++++++++++++ 2 files changed, 15 insertions(+)
drivers/firmware/efi/efi.c +2 -0
@@ -43,6 +43,7 @@ struct efi __read_mostly efi = { .config_table = EFI_INVALID_TABLE_ADDR, .esrt = EFI_INVALID_TABLE_ADDR, .properties_table = EFI_INVALID_TABLE_ADDR, + .mem_attr_table = EFI_INVALID_TABLE_ADDR, };EXPORT_SYMBOL (efi);
@@ -338,6 +339,7 @@ static __initdata efi_config_table_type_t common_tables[] = { {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, + {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, {NULL_GUID, NULL, NULL}, };
include/linux/efi.h +13 -0
@@ -623,6 +623,10 @@ void efi_native_runtime_setup(void);EFI_GUID (0x3152bca5 ,0xeade ,0x433d , \ 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) +#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID \ + EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, \ + 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) + typedef struct { efi_guid_t guid; u64 table;
@@ -847,6 +851,14 @@ typedef struct {#define EFI_INVALID_TABLE_ADDR (~0UL) +typedef struct { +u32 version; +u32 num_entries; +u32 desc_size; +u32 reserved; +efi_memory_desc_t entry[0 ]; +}efi_memory_attributes_table_t ; +/* * All runtime access to EFI goes through this structure: */
@@ -868,6 +880,7 @@ extern struct efi {unsigned long config_table;/* config tables */ unsigned long esrt;/* ESRT table */ unsigned long properties_table;/* properties table */ +unsigned long mem_attr_table;/* memory attributes table */ efi_get_time_t *get_time;efi_set_time_t *set_time;efi_get_wakeup_time_t *get_wakeup_time;
PATCH 13/40 efi: Implement generic support for the Memory Attributes table
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
This implements shared support for discovering the presence of the Memory Attributes table, and for parsing and validating its contents.
The table is validated against the construction rules in the UEFI spec. Since this is a new table, it makes sense to complain if we encounter a table that does not follow those rules.
The parsing and validation routine takes a callback that can be specified per architecture, that gets passed each unique validated region, with the virtual address retrieved from the ordinary memory map.
--- drivers/firmware/efi/Makefile | 2 +- drivers/firmware/efi/memattr.c | 182 +++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 13 +++ 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/efi/memattr.c
drivers/firmware/efi/Makefile +1 -1
@@ -9,7 +9,7 @@ # KASAN_SANITIZE_runtime-wrappers.o := n -obj-$(CONFIG_EFI) += efi.o vars.o reboot.o +obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_ESRT) += esrt.o obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
drivers/firmware/efi/memattr.c new file +182 -0
182 lines not on this page · raw message
include/linux/efi.h +13 -0
@@ -969,6 +969,19 @@ extern void __init efi_fake_memmap(void);static inline void efi_fake_memmap (void ) { }#endif +/* +* efi_memattr_perm_setter - arch specific callback function passed into +* efi_memattr_apply_permissions() that updates the +* mapping permissions described by the second +* argument in the page tables referred to by the +* first argument. +*/ +typedef int (*efi_memattr_perm_setter )(struct mm_struct *,efi_memory_desc_t *); + +extern int efi_memattr_init (void ); +extern int efi_memattr_apply_permissions (struct mm_struct *mm, +efi_memattr_perm_setter fn); +/* Iterate through an efi_memory_map */ #define for_each_efi_memory_desc_in_map (m, md) \ for ((md) = (m)->map; \
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi: Implement generic support for the Memory Attributes table
efi: Implement generic support for the Memory Attributes table
Commit-ID: 10f0d2f57705350bbbe5f28e9292ae3905823c3c Gitweb: http://git.kernel.org/tip/10f0d2f57705350bbbe5f28e9292ae3905823c3c Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:45 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:54 +0200
efi: Implement generic support for the Memory Attributes table
This implements shared support for discovering the presence of the Memory Attributes table, and for parsing and validating its contents.
The table is validated against the construction rules in the UEFI spec. Since this is a new table, it makes sense to complain if we encounter a table that does not follow those rules.
The parsing and validation routine takes a callback that can be specified per architecture, that gets passed each unique validated region, with the virtual address retrieved from the ordinary memory map.
--- drivers/firmware/efi/Makefile | 2 +- drivers/firmware/efi/memattr.c | 182 +++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 13 +++ 3 files changed, 196 insertions(+), 1 deletion(-)
drivers/firmware/efi/Makefile +1 -1
@@ -9,7 +9,7 @@ # KASAN_SANITIZE_runtime-wrappers.o := n -obj-$(CONFIG_EFI) += efi.o vars.o reboot.o +obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_ESRT) += esrt.o obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
drivers/firmware/efi/memattr.c new file +182 -0
182 lines not on this page · raw message
include/linux/efi.h +13 -0
@@ -969,6 +969,19 @@ extern void __init efi_fake_memmap(void);static inline void efi_fake_memmap (void ) { }#endif +/* +* efi_memattr_perm_setter - arch specific callback function passed into +* efi_memattr_apply_permissions() that updates the +* mapping permissions described by the second +* argument in the page tables referred to by the +* first argument. +*/ +typedef int (*efi_memattr_perm_setter )(struct mm_struct *,efi_memory_desc_t *); + +extern int efi_memattr_init (void ); +extern int efi_memattr_apply_permissions (struct mm_struct *mm, +efi_memattr_perm_setter fn); +/* Iterate through an efi_memory_map */ #define for_each_efi_memory_desc_in_map (m, md) \ for ((md) = (m)->map; \
PATCH 14/40 efi/arm*: Take the Memory Attributes table into account
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Call into the generic memory attributes table support code at the appropriate times during the init sequence so that the UEFI Runtime Services region are mapped according to the strict permissions it specifies.
--- arch/arm64/include/asm/efi.h | 2 ++ drivers/firmware/efi/arm-init.c | 1 + drivers/firmware/efi/arm-runtime.c | 10 ++++++++-- 3 files changed, 11 insertions(+), 2 deletions(-)
arch/arm64/include/asm/efi.h +2 -0
@@ -14,6 +14,8 @@ extern void efi_init(void);int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md); +#define efi_set_mapping_permissions efi_create_mapping +#define efi_call_virt (f, ...) \ ({ \ efi_##f##_t *__f; \
drivers/firmware/efi/arm-init.c +1 -0
@@ -206,6 +206,7 @@ void __init efi_init(void)return ;reserve_regions (); +efi_memattr_init ();early_memunmap (efi.memmap.map, params.mmap_size);if (IS_ENABLED (CONFIG_ARM )) {
drivers/firmware/efi/arm-runtime.c +8 -2
@@ -77,9 +77,15 @@ static bool __init efi_virtmap_init(void) systab_found = true; } } -if (!systab_found) +if (!systab_found) {pr_err ("No virtual mapping found for the UEFI System Table\n" ); -return systab_found; +return false; + } + +if (efi_memattr_apply_permissions (&efi_mm, efi_set_mapping_permissions)) +return false; + +return true; }/*
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/arm*: Take the Memory Attributes table into account
efi/arm*: Take the Memory Attributes table into account
Commit-ID: 789957ef72f976cb325e9057225fc4e9c4513060 Gitweb: http://git.kernel.org/tip/789957ef72f976cb325e9057225fc4e9c4513060 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:46 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:55 +0200
efi/arm*: Take the Memory Attributes table into account
Call into the generic memory attributes table support code at the appropriate times during the init sequence so that the UEFI Runtime Services region are mapped according to the strict permissions it specifies.
--- arch/arm64/include/asm/efi.h | 2 ++ drivers/firmware/efi/arm-init.c | 1 + drivers/firmware/efi/arm-runtime.c | 10 ++++++++-- 3 files changed, 11 insertions(+), 2 deletions(-)
arch/arm64/include/asm/efi.h +2 -0
@@ -14,6 +14,8 @@ extern void efi_init(void);int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md); +#define efi_set_mapping_permissions efi_create_mapping +#define efi_call_virt (f, ...) \ ({ \ efi_##f##_t *__f; \
drivers/firmware/efi/arm-init.c +1 -0
@@ -206,6 +206,7 @@ void __init efi_init(void)return ;reserve_regions (); +efi_memattr_init ();early_memunmap (efi.memmap.map, params.mmap_size);if (IS_ENABLED (CONFIG_ARM )) {
drivers/firmware/efi/arm-runtime.c +8 -2
@@ -77,9 +77,15 @@ static bool __init efi_virtmap_init(void) systab_found = true; } } -if (!systab_found) +if (!systab_found) {pr_err ("No virtual mapping found for the UEFI System Table\n" ); -return systab_found; +return false; + } + +if (efi_memattr_apply_permissions (&efi_mm, efi_set_mapping_permissions)) +return false; + +return true; }/*
PATCH 15/40 x86/efi: Remove the always true EFI_DEBUG symbol
In reply to Matt FlemingThis symbol is always set which makes it useless. Additionally we have a kernel command-line switch, efi=debug, which actually controls the printing of the memory map.
--- arch/x86/platform/efi/efi.c | 4 ---- 1 file changed, 4 deletions(-)
arch/x86/platform/efi/efi.c +0 -4
@@ -54,8 +54,6 @@#include <asm/rtc.h> #include <asm/uv/uv.h> -#define EFI_DEBUG -static struct efi efi_phys__initdata ;static efi_system_table_t efi_systab__initdata ;
@@ -222,7 +220,6 @@ int __init efi_memblock_x86_reserve_range(void)void __init efi_print_memmap (void ) { -#ifdef EFI_DEBUG efi_memory_desc_t *md;int i =0 ;
@@ -235,7 +232,6 @@ void __init efi_print_memmap(void) md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ) -1 , (md->num_pages >> (20 - EFI_PAGE_SHIFT))); } -#endif /* EFI_DEBUG */ }void __init efi_unmap_memmap (void )
Signature · 1 line
2.7.3
tip-bot for Matt Fleming
merge bot[tip:efi/core] x86/efi: Remove the always true EFI_DEBUG symbol
x86/efi: Remove the always true EFI_DEBUG symbol
Commit-ID: c3c1c47f15b37a8492e630d1e9ab8ad576ee10e5 Gitweb: http://git.kernel.org/tip/c3c1c47f15b37a8492e630d1e9ab8ad576ee10e5 Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:47 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:56 +0200
x86/efi: Remove the always true EFI_DEBUG symbol
This symbol is always set which makes it useless. Additionally we have a kernel command-line switch, efi=debug, which actually controls the printing of the memory map.
--- arch/x86/platform/efi/efi.c | 4 ---- 1 file changed, 4 deletions(-)
arch/x86/platform/efi/efi.c +0 -4
@@ -54,8 +54,6 @@#include <asm/rtc.h> #include <asm/uv/uv.h> -#define EFI_DEBUG -static struct efi efi_phys__initdata ;static efi_system_table_t efi_systab__initdata ;
@@ -222,7 +220,6 @@ int __init efi_memblock_x86_reserve_range(void)void __init efi_print_memmap (void ) { -#ifdef EFI_DEBUG efi_memory_desc_t *md;int i =0 ;
@@ -235,7 +232,6 @@ void __init efi_print_memmap(void) md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ) -1 , (md->num_pages >> (20 - EFI_PAGE_SHIFT))); } -#endif /* EFI_DEBUG */ }void __init efi_unmap_memmap (void )
PATCH 16/40 x86/efi: Prepare GOP handling code for reuse as generic code
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
In preparation of moving this code to drivers/firmware/efi and reusing it on ARM and arm64, apply any changes that will be required to make this code build for other architectures. This should make it easier to track down problems that this move may cause to its operation on x86.
Note that the generic version uses slightly different ways of casting the protocol methods and some other variables to the correct types, since such method calls are not loosely typed on ARM and arm64 as they are on x86.
--- arch/x86/boot/compressed/eboot.c | 58 ++++++++++++++++++++++++---------------- arch/x86/boot/compressed/eboot.h | 4 +++ arch/x86/include/asm/efi.h | 5 ++++ include/linux/efi.h | 5 ++++ 4 files changed, 49 insertions(+), 23 deletions(-)
arch/x86/boot/compressed/eboot.c +35 -23
@@ -622,19 +622,22 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, }static efi_status_t -__gop_query32 (struct efi_graphics_output_protocol_32 *gop32, +__gop_query32 (efi_system_table_t *sys_table_arg, +struct efi_graphics_output_protocol_32 *gop32,struct efi_graphics_output_mode_info **info,unsigned long *size,u64 *fb_base) {struct efi_graphics_output_protocol_mode_32 *mode; +efi_graphics_output_protocol_query_mode query_mode;efi_status_t status;unsigned long m; m = gop32->mode; mode = (struct efi_graphics_output_protocol_mode_32 *)m; + query_mode = (void *)(unsigned long )gop32->query_mode; - status = efi_early->call (gop32->query_mode, gop32, - mode->mode, size, info); + status =__efi_call_early (query_mode, (void *)gop32, mode->mode, size, + info);if (status !=EFI_SUCCESS )return status;
@@ -643,8 +646,8 @@ __gop_query32(struct efi_graphics_output_protocol_32 *gop32, }static efi_status_t -setup_gop32 (struct screen_info *si,efi_guid_t *proto, -unsigned long size,void **gop_handle) +setup_gop32 (efi_system_table_t *sys_table_arg,struct screen_info *si, +efi_guid_t *proto,unsigned long size,void **gop_handle) {struct efi_graphics_output_protocol_32 *gop32, *first_gop;unsigned long nr_gops;
@@ -654,7 +657,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,u64 fb_base;struct efi_pixel_bitmask pixel_info;int pixel_format; -efi_status_t status; +efi_status_t status =EFI_NOT_FOUND ;u32 *handles = (u32 *)(unsigned long )gop_handle;int i;
@@ -667,7 +670,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,efi_guid_t conout_proto =EFI_CONSOLE_OUT_DEVICE_GUID ;bool conout_found = false;void *dummy =NULL ; -u32 h = handles[i]; +efi_handle_t h = (efi_handle_t )(unsigned long )handles[i];u64 current_fb_base; status = efi_call_early(handle_protocol, h,
@@ -680,7 +683,8 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,if (status ==EFI_SUCCESS ) conout_found = true; - status =__gop_query32 (gop32, &info, &size, ¤t_fb_base); + status =__gop_query32 (sys_table_arg, gop32, &info, &size, + ¤t_fb_base);if (status ==EFI_SUCCESS && (!first_gop || conout_found)) {/* * Systems that use the UEFI Console Splitter may
@@ -735,19 +739,22 @@ out: }static efi_status_t -__gop_query64 (struct efi_graphics_output_protocol_64 *gop64, +__gop_query64 (efi_system_table_t *sys_table_arg, +struct efi_graphics_output_protocol_64 *gop64,struct efi_graphics_output_mode_info **info,unsigned long *size,u64 *fb_base) {struct efi_graphics_output_protocol_mode_64 *mode; +efi_graphics_output_protocol_query_mode query_mode;efi_status_t status;unsigned long m; m = gop64->mode; mode = (struct efi_graphics_output_protocol_mode_64 *)m; + query_mode = (void *)(unsigned long )gop64->query_mode; - status = efi_early->call (gop64->query_mode, gop64, - mode->mode, size, info); + status =__efi_call_early (query_mode, (void *)gop64, mode->mode, size, + info);if (status !=EFI_SUCCESS )return status;
@@ -756,8 +763,8 @@ __gop_query64(struct efi_graphics_output_protocol_64 *gop64, }static efi_status_t -setup_gop64 (struct screen_info *si,efi_guid_t *proto, -unsigned long size,void **gop_handle) +setup_gop64 (efi_system_table_t *sys_table_arg,struct screen_info *si, +efi_guid_t *proto,unsigned long size,void **gop_handle) {struct efi_graphics_output_protocol_64 *gop64, *first_gop;unsigned long nr_gops;
@@ -767,7 +774,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,u64 fb_base;struct efi_pixel_bitmask pixel_info;int pixel_format; -efi_status_t status; +efi_status_t status =EFI_NOT_FOUND ;u64 *handles = (u64 *)(unsigned long )gop_handle;int i;
@@ -780,7 +787,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,efi_guid_t conout_proto =EFI_CONSOLE_OUT_DEVICE_GUID ;bool conout_found = false;void *dummy =NULL ; -u64 h = handles[i]; +efi_handle_t h = (efi_handle_t )(unsigned long )handles[i];u64 current_fb_base; status = efi_call_early(handle_protocol, h,
@@ -793,7 +800,8 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,if (status ==EFI_SUCCESS ) conout_found = true; - status =__gop_query64 (gop64, &info, &size, ¤t_fb_base); + status =__gop_query64 (sys_table_arg, gop64, &info, &size, + ¤t_fb_base);if (status ==EFI_SUCCESS && (!first_gop || conout_found)) {/* * Systems that use the UEFI Console Splitter may
@@ -850,8 +858,9 @@ out:/* * See if we have Graphics Output Protocol */ -static efi_status_t setup_gop (struct screen_info *si,efi_guid_t *proto, -unsigned long size) +efi_status_t efi_setup_gop (efi_system_table_t *sys_table_arg, +struct screen_info *si,efi_guid_t *proto, +unsigned long size) {efi_status_t status;void **gop_handle =NULL ;
@@ -867,10 +876,13 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,if (status !=EFI_SUCCESS ) goto free_handle; -if (efi_early->is64) - status =setup_gop64 (si, proto, size, gop_handle); -else - status =setup_gop32 (si, proto, size, gop_handle); +if (efi_is_64bit ()) { + status =setup_gop64 (sys_table_arg, si, proto, size, + gop_handle); + }else { + status =setup_gop32 (sys_table_arg, si, proto, size, + gop_handle); + } free_handle:efi_call_early (free_pool, gop_handle);
@@ -1038,7 +1050,7 @@ void setup_graphics(struct boot_params *boot_params)EFI_LOCATE_BY_PROTOCOL , &graphics_proto, NULL, &size, gop_handle);if (status ==EFI_BUFFER_TOO_SMALL ) - status =setup_gop (si, &graphics_proto, size); + status =efi_setup_gop (NULL , si, &graphics_proto, size);if (status !=EFI_SUCCESS ) { size =0 ;
arch/x86/boot/compressed/eboot.h +4 -0
@@ -85,6 +85,10 @@ struct efi_graphics_output_protocol {struct efi_graphics_output_protocol_mode *mode; }; +typedef efi_status_t (*efi_graphics_output_protocol_query_mode )( +struct efi_graphics_output_protocol *,u32 ,unsigned long *, +struct efi_graphics_output_mode_info **); +struct efi_uga_draw_protocol_32 {u32 get_mode;u32 set_mode;
arch/x86/include/asm/efi.h +5 -0
@@ -225,6 +225,11 @@ __pure const struct efi_config *__efi_early(void);#define efi_call_early (f, ...) \ __efi_early()->call(__efi_early()->f, __VA_ARGS__); +#define __efi_call_early (f, ...) \ + __efi_early()->call((unsigned long)f, __VA_ARGS__); + +#define efi_is_64bit () __efi_early()->is64 +extern bool efi_reboot_required (void );#else
include/linux/efi.h +5 -0
@@ -21,6 +21,7 @@#include <linux/pfn.h> #include <linux/pstore.h> #include <linux/reboot.h> +#include <linux/screen_info.h> #include <asm/page.h>
@@ -1352,5 +1353,9 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,efi_status_t efi_parse_options (char *cmdline); +efi_status_t efi_setup_gop (efi_system_table_t *sys_table_arg, +struct screen_info *si,efi_guid_t *proto, +unsigned long size); +bool efi_runtime_disabled (void );#endif /* _LINUX_EFI_H */
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] x86/efi: Prepare GOP handling code for reuse as generic code
x86/efi: Prepare GOP handling code for reuse as generic code
Commit-ID: 2c23b73c2d0249c499c4784b6db08dcfc6b7b3b0 Gitweb: http://git.kernel.org/tip/2c23b73c2d0249c499c4784b6db08dcfc6b7b3b0 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:48 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:56 +0200
x86/efi: Prepare GOP handling code for reuse as generic code
In preparation of moving this code to drivers/firmware/efi and reusing it on ARM and arm64, apply any changes that will be required to make this code build for other architectures. This should make it easier to track down problems that this move may cause to its operation on x86.
Note that the generic version uses slightly different ways of casting the protocol methods and some other variables to the correct types, since such method calls are not loosely typed on ARM and arm64 as they are on x86.
--- arch/x86/boot/compressed/eboot.c | 58 ++++++++++++++++++++++++---------------- arch/x86/boot/compressed/eboot.h | 4 +++ arch/x86/include/asm/efi.h | 5 ++++ include/linux/efi.h | 5 ++++ 4 files changed, 49 insertions(+), 23 deletions(-)
arch/x86/boot/compressed/eboot.c +35 -23
@@ -622,19 +622,22 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, }static efi_status_t -__gop_query32 (struct efi_graphics_output_protocol_32 *gop32, +__gop_query32 (efi_system_table_t *sys_table_arg, +struct efi_graphics_output_protocol_32 *gop32,struct efi_graphics_output_mode_info **info,unsigned long *size,u64 *fb_base) {struct efi_graphics_output_protocol_mode_32 *mode; +efi_graphics_output_protocol_query_mode query_mode;efi_status_t status;unsigned long m; m = gop32->mode; mode = (struct efi_graphics_output_protocol_mode_32 *)m; + query_mode = (void *)(unsigned long )gop32->query_mode; - status = efi_early->call (gop32->query_mode, gop32, - mode->mode, size, info); + status =__efi_call_early (query_mode, (void *)gop32, mode->mode, size, + info);if (status !=EFI_SUCCESS )return status;
@@ -643,8 +646,8 @@ __gop_query32(struct efi_graphics_output_protocol_32 *gop32, }static efi_status_t -setup_gop32 (struct screen_info *si,efi_guid_t *proto, -unsigned long size,void **gop_handle) +setup_gop32 (efi_system_table_t *sys_table_arg,struct screen_info *si, +efi_guid_t *proto,unsigned long size,void **gop_handle) {struct efi_graphics_output_protocol_32 *gop32, *first_gop;unsigned long nr_gops;
@@ -654,7 +657,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,u64 fb_base;struct efi_pixel_bitmask pixel_info;int pixel_format; -efi_status_t status; +efi_status_t status =EFI_NOT_FOUND ;u32 *handles = (u32 *)(unsigned long )gop_handle;int i;
@@ -667,7 +670,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,efi_guid_t conout_proto =EFI_CONSOLE_OUT_DEVICE_GUID ;bool conout_found = false;void *dummy =NULL ; -u32 h = handles[i]; +efi_handle_t h = (efi_handle_t )(unsigned long )handles[i];u64 current_fb_base; status = efi_call_early(handle_protocol, h,
@@ -680,7 +683,8 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,if (status ==EFI_SUCCESS ) conout_found = true; - status =__gop_query32 (gop32, &info, &size, ¤t_fb_base); + status =__gop_query32 (sys_table_arg, gop32, &info, &size, + ¤t_fb_base);if (status ==EFI_SUCCESS && (!first_gop || conout_found)) {/* * Systems that use the UEFI Console Splitter may
@@ -735,19 +739,22 @@ out: }static efi_status_t -__gop_query64 (struct efi_graphics_output_protocol_64 *gop64, +__gop_query64 (efi_system_table_t *sys_table_arg, +struct efi_graphics_output_protocol_64 *gop64,struct efi_graphics_output_mode_info **info,unsigned long *size,u64 *fb_base) {struct efi_graphics_output_protocol_mode_64 *mode; +efi_graphics_output_protocol_query_mode query_mode;efi_status_t status;unsigned long m; m = gop64->mode; mode = (struct efi_graphics_output_protocol_mode_64 *)m; + query_mode = (void *)(unsigned long )gop64->query_mode; - status = efi_early->call (gop64->query_mode, gop64, - mode->mode, size, info); + status =__efi_call_early (query_mode, (void *)gop64, mode->mode, size, + info);if (status !=EFI_SUCCESS )return status;
@@ -756,8 +763,8 @@ __gop_query64(struct efi_graphics_output_protocol_64 *gop64, }static efi_status_t -setup_gop64 (struct screen_info *si,efi_guid_t *proto, -unsigned long size,void **gop_handle) +setup_gop64 (efi_system_table_t *sys_table_arg,struct screen_info *si, +efi_guid_t *proto,unsigned long size,void **gop_handle) {struct efi_graphics_output_protocol_64 *gop64, *first_gop;unsigned long nr_gops;
@@ -767,7 +774,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,u64 fb_base;struct efi_pixel_bitmask pixel_info;int pixel_format; -efi_status_t status; +efi_status_t status =EFI_NOT_FOUND ;u64 *handles = (u64 *)(unsigned long )gop_handle;int i;
@@ -780,7 +787,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,efi_guid_t conout_proto =EFI_CONSOLE_OUT_DEVICE_GUID ;bool conout_found = false;void *dummy =NULL ; -u64 h = handles[i]; +efi_handle_t h = (efi_handle_t )(unsigned long )handles[i];u64 current_fb_base; status = efi_call_early(handle_protocol, h,
@@ -793,7 +800,8 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,if (status ==EFI_SUCCESS ) conout_found = true; - status =__gop_query64 (gop64, &info, &size, ¤t_fb_base); + status =__gop_query64 (sys_table_arg, gop64, &info, &size, + ¤t_fb_base);if (status ==EFI_SUCCESS && (!first_gop || conout_found)) {/* * Systems that use the UEFI Console Splitter may
@@ -850,8 +858,9 @@ out:/* * See if we have Graphics Output Protocol */ -static efi_status_t setup_gop (struct screen_info *si,efi_guid_t *proto, -unsigned long size) +efi_status_t efi_setup_gop (efi_system_table_t *sys_table_arg, +struct screen_info *si,efi_guid_t *proto, +unsigned long size) {efi_status_t status;void **gop_handle =NULL ;
@@ -867,10 +876,13 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,if (status !=EFI_SUCCESS ) goto free_handle; -if (efi_early->is64) - status =setup_gop64 (si, proto, size, gop_handle); -else - status =setup_gop32 (si, proto, size, gop_handle); +if (efi_is_64bit ()) { + status =setup_gop64 (sys_table_arg, si, proto, size, + gop_handle); + }else { + status =setup_gop32 (sys_table_arg, si, proto, size, + gop_handle); + } free_handle:efi_call_early (free_pool, gop_handle);
@@ -1038,7 +1050,7 @@ void setup_graphics(struct boot_params *boot_params)EFI_LOCATE_BY_PROTOCOL , &graphics_proto, NULL, &size, gop_handle);if (status ==EFI_BUFFER_TOO_SMALL ) - status =setup_gop (si, &graphics_proto, size); + status =efi_setup_gop (NULL , si, &graphics_proto, size);if (status !=EFI_SUCCESS ) { size =0 ;
arch/x86/boot/compressed/eboot.h +4 -0
@@ -85,6 +85,10 @@ struct efi_graphics_output_protocol {struct efi_graphics_output_protocol_mode *mode; }; +typedef efi_status_t (*efi_graphics_output_protocol_query_mode )( +struct efi_graphics_output_protocol *,u32 ,unsigned long *, +struct efi_graphics_output_mode_info **); +struct efi_uga_draw_protocol_32 {u32 get_mode;u32 set_mode;
arch/x86/include/asm/efi.h +5 -0
@@ -225,6 +225,11 @@ __pure const struct efi_config *__efi_early(void);#define efi_call_early (f, ...) \ __efi_early()->call(__efi_early()->f, __VA_ARGS__); +#define __efi_call_early (f, ...) \ + __efi_early()->call((unsigned long)f, __VA_ARGS__); + +#define efi_is_64bit () __efi_early()->is64 +extern bool efi_reboot_required (void );#else
include/linux/efi.h +5 -0
@@ -21,6 +21,7 @@#include <linux/pfn.h> #include <linux/pstore.h> #include <linux/reboot.h> +#include <linux/screen_info.h> #include <asm/page.h>
@@ -1352,5 +1353,9 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,efi_status_t efi_parse_options (char *cmdline); +efi_status_t efi_setup_gop (efi_system_table_t *sys_table_arg, +struct screen_info *si,efi_guid_t *proto, +unsigned long size); +bool efi_runtime_disabled (void );#endif /* _LINUX_EFI_H */
PATCH 17/40 efi/libstub: Move Graphics Output Protocol handling to generic code
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
The Graphics Output Protocol code executes in the stub, so create a generic version based on the x86 version in libstub so that we can move other archs to it in subsequent patches. The new source file gop.c is added to the libstub build for all architectures, but only wired up for x86.
--- arch/arm/include/asm/efi.h | 4 +- arch/arm64/include/asm/efi.h | 4 +- arch/x86/boot/compressed/eboot.c | 318 ------------------------------ arch/x86/boot/compressed/eboot.h | 78 -------- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/gop.c | 354 ++++++++++++++++++++++++++++++++++ include/linux/efi.h | 81 +++++++- 7 files changed, 441 insertions(+), 400 deletions(-) create mode 100644 drivers/firmware/efi/libstub/gop.c
arch/arm/include/asm/efi.h +3 -1
@@ -60,7 +60,9 @@ void efi_virtmap_unload(void);/* arch specific definitions used by the stub code */ -#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define __efi_call_early (f, ...) f(__VA_ARGS__) +#define efi_is_64bit () (false)/* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
arch/arm64/include/asm/efi.h +3 -1
@@ -52,7 +52,9 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);#define EFI_FDT_ALIGN SZ_2M/* used by allocate_new_fdt_and_exit_boot() */ #define MAX_FDT_OFFSET SZ_512M -#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define __efi_call_early (f, ...) f(__VA_ARGS__) +#define efi_is_64bit () (true)#define EFI_ALLOC_ALIGN SZ_64K
arch/x86/boot/compressed/eboot.c +0 -318
324 lines not on this page · raw message
arch/x86/boot/compressed/eboot.h +0 -78
84 lines not on this page · raw message
drivers/firmware/efi/libstub/Makefile +1 -1
@@ -28,7 +28,7 @@ OBJECT_FILES_NON_STANDARD := y # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. KCOV_INSTRUMENT := n -lib-y := efi-stub-helper.o +lib-y := efi-stub-helper.o gop.o # include the stub's generic dependencies from lib/ when building for ARM/arm64 arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
drivers/firmware/efi/libstub/gop.c new file +354 -0
354 lines not on this page · raw message
include/linux/efi.h +80 -1
99 lines not on this page · raw message
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/libstub: Move Graphics Output Protocol handling to generic code
efi/libstub: Move Graphics Output Protocol handling to generic code
Commit-ID: fc37206427ce38eafbeff48099d873235e878450 Gitweb: http://git.kernel.org/tip/fc37206427ce38eafbeff48099d873235e878450 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:49 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:57 +0200
efi/libstub: Move Graphics Output Protocol handling to generic code
The Graphics Output Protocol code executes in the stub, so create a generic version based on the x86 version in libstub so that we can move other archs to it in subsequent patches. The new source file gop.c is added to the libstub build for all architectures, but only wired up for x86.
--- arch/arm/include/asm/efi.h | 4 +- arch/arm64/include/asm/efi.h | 4 +- arch/x86/boot/compressed/eboot.c | 318 ------------------------------ arch/x86/boot/compressed/eboot.h | 78 -------- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/gop.c | 354 ++++++++++++++++++++++++++++++++++ include/linux/efi.h | 81 +++++++- 7 files changed, 441 insertions(+), 400 deletions(-)
arch/arm/include/asm/efi.h +3 -1
@@ -60,7 +60,9 @@ void efi_virtmap_unload(void);/* arch specific definitions used by the stub code */ -#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define __efi_call_early (f, ...) f(__VA_ARGS__) +#define efi_is_64bit () (false)/* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
arch/arm64/include/asm/efi.h +3 -1
@@ -52,7 +52,9 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);#define EFI_FDT_ALIGN SZ_2M/* used by allocate_new_fdt_and_exit_boot() */ #define MAX_FDT_OFFSET SZ_512M -#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define __efi_call_early (f, ...) f(__VA_ARGS__) +#define efi_is_64bit () (true)#define EFI_ALLOC_ALIGN SZ_64K
arch/x86/boot/compressed/eboot.c +0 -318
324 lines not on this page · raw message
arch/x86/boot/compressed/eboot.h +0 -78
84 lines not on this page · raw message
drivers/firmware/efi/libstub/Makefile +1 -1
@@ -28,7 +28,7 @@ OBJECT_FILES_NON_STANDARD := y # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. KCOV_INSTRUMENT := n -lib-y := efi-stub-helper.o +lib-y := efi-stub-helper.o gop.o # include the stub's generic dependencies from lib/ when building for ARM/arm64 arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
drivers/firmware/efi/libstub/gop.c new file +354 -0
354 lines not on this page · raw message
include/linux/efi.h +80 -1
99 lines not on this page · raw message
PATCH 18/40 x86/efi: efifb: Move DMI based quirks handling out of generic code
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
The efifb quirks handling based on DMI identification of the platform is specific to x86, so move it to x86 arch code.
--- arch/x86/include/asm/efi.h | 2 ++ arch/x86/kernel/sysfb_efi.c | 15 +++++++++++++++ drivers/video/fbdev/efifb.c | 15 ++++----------- 3 files changed, 21 insertions(+), 11 deletions(-)
arch/x86/include/asm/efi.h +2 -0
@@ -180,6 +180,8 @@ static inline bool efi_runtime_supported(void)extern struct console early_efi_console;extern void parse_efi_setup (u64 phys_addr,u32 data_len); +extern void efifb_setup_from_dmi (struct screen_info *si,const char *opt); +#ifdef CONFIG_EFI_MIXED extern void efi_thunk_runtime_setup (void ); extern efi_status_t efi_thunk_set_virtual_address_map(
arch/x86/kernel/sysfb_efi.c +15 -0
@@ -68,6 +68,21 @@ struct efifb_dmi_info efifb_dmi_list[] = { [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } }; +void efifb_setup_from_dmi (struct screen_info *si,const char *opt) +{ +int i; + +for (i =0 ; i <M_UNKNOWN ; i++) { +if (efifb_dmi_list[i].base !=0 && + !strcmp (opt, efifb_dmi_list[i].optname)) { + si->lfb_base = efifb_dmi_list[i].base; + si->lfb_linelength = efifb_dmi_list[i].stride; + si->lfb_width = efifb_dmi_list[i].width; + si->lfb_height = efifb_dmi_list[i].height; + } + } +} +#define choose_value (dmivalue, fwvalue, field, flags) ({ \ typeof(fwvalue) _ret_ = fwvalue; \ if ((flags) & (field)) \
drivers/video/fbdev/efifb.c +4 -11
@@ -8,6 +8,7 @@#include <linux/module.h> #include <linux/kernel.h> +#include <linux/efi.h> #include <linux/errno.h> #include <linux/fb.h> #include <linux/platform_device.h>
@@ -15,7 +16,7 @@#include <linux/dmi.h> #include <linux/pci.h> #include <video/vga.h> -#include <asm/sysfb.h> +#include <asm/efi.h> static bool request_mem_succeeded = false;
@@ -85,21 +86,13 @@ static struct fb_ops efifb_ops = {static int efifb_setup (char *options) {char *this_opt; -int i;if (options && *options) {while ((this_opt =strsep (&options,"," )) !=NULL ) {if (!*this_opt)continue ; -for (i =0 ; i <M_UNKNOWN ; i++) { -if (efifb_dmi_list[i].base !=0 && - !strcmp (this_opt, efifb_dmi_list[i].optname)) { - screen_info.lfb_base = efifb_dmi_list[i].base; - screen_info.lfb_linelength = efifb_dmi_list[i].stride; - screen_info.lfb_width = efifb_dmi_list[i].width; - screen_info.lfb_height = efifb_dmi_list[i].height; - } - } +efifb_setup_from_dmi (&screen_info, this_opt); +if (!strncmp (this_opt,"base:" ,5 )) screen_info.lfb_base =simple_strtoul (this_opt+5 ,NULL ,0 );else if (!strncmp (this_opt,"stride:" ,7 ))
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] x86/efi/efifb: Move DMI based quirks handling out of generic code
x86/efi/efifb: Move DMI based quirks handling out of generic code
Commit-ID: 21289ec02b41c4b928a0b3de1778b325d714eea3 Gitweb: http://git.kernel.org/tip/21289ec02b41c4b928a0b3de1778b325d714eea3 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:50 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:57 +0200
x86/efi/efifb: Move DMI based quirks handling out of generic code
The efifb quirks handling based on DMI identification of the platform is specific to x86, so move it to x86 arch code.
--- arch/x86/include/asm/efi.h | 2 ++ arch/x86/kernel/sysfb_efi.c | 15 +++++++++++++++ drivers/video/fbdev/efifb.c | 15 ++++----------- 3 files changed, 21 insertions(+), 11 deletions(-)
arch/x86/include/asm/efi.h +2 -0
@@ -180,6 +180,8 @@ static inline bool efi_runtime_supported(void)extern struct console early_efi_console;extern void parse_efi_setup (u64 phys_addr,u32 data_len); +extern void efifb_setup_from_dmi (struct screen_info *si,const char *opt); +#ifdef CONFIG_EFI_MIXED extern void efi_thunk_runtime_setup (void ); extern efi_status_t efi_thunk_set_virtual_address_map(
arch/x86/kernel/sysfb_efi.c +15 -0
@@ -68,6 +68,21 @@ struct efifb_dmi_info efifb_dmi_list[] = { [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } }; +void efifb_setup_from_dmi (struct screen_info *si,const char *opt) +{ +int i; + +for (i =0 ; i <M_UNKNOWN ; i++) { +if (efifb_dmi_list[i].base !=0 && + !strcmp (opt, efifb_dmi_list[i].optname)) { + si->lfb_base = efifb_dmi_list[i].base; + si->lfb_linelength = efifb_dmi_list[i].stride; + si->lfb_width = efifb_dmi_list[i].width; + si->lfb_height = efifb_dmi_list[i].height; + } + } +} +#define choose_value (dmivalue, fwvalue, field, flags) ({ \ typeof(fwvalue) _ret_ = fwvalue; \ if ((flags) & (field)) \
drivers/video/fbdev/efifb.c +4 -11
@@ -8,6 +8,7 @@#include <linux/module.h> #include <linux/kernel.h> +#include <linux/efi.h> #include <linux/errno.h> #include <linux/fb.h> #include <linux/platform_device.h>
@@ -15,7 +16,7 @@#include <linux/dmi.h> #include <linux/pci.h> #include <video/vga.h> -#include <asm/sysfb.h> +#include <asm/efi.h> static bool request_mem_succeeded = false;
@@ -85,21 +86,13 @@ static struct fb_ops efifb_ops = {static int efifb_setup (char *options) {char *this_opt; -int i;if (options && *options) {while ((this_opt =strsep (&options,"," )) !=NULL ) {if (!*this_opt)continue ; -for (i =0 ; i <M_UNKNOWN ; i++) { -if (efifb_dmi_list[i].base !=0 && - !strcmp (this_opt, efifb_dmi_list[i].optname)) { - screen_info.lfb_base = efifb_dmi_list[i].base; - screen_info.lfb_linelength = efifb_dmi_list[i].stride; - screen_info.lfb_width = efifb_dmi_list[i].width; - screen_info.lfb_height = efifb_dmi_list[i].height; - } - } +efifb_setup_from_dmi (&screen_info, this_opt); +if (!strncmp (this_opt,"base:" ,5 )) screen_info.lfb_base =simple_strtoul (this_opt+5 ,NULL ,0 );else if (!strncmp (this_opt,"stride:" ,7 ))
PATCH 19/40 efifb: Use builtin_platform_driver and drop unused includes
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Since efifb can only be built directly into the kernel, drop the module specific includes and definitions. Drop some other includes we don't need as well.
--- drivers/video/fbdev/efifb.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/video/fbdev/efifb.c +1 -5
@@ -6,15 +6,12 @@* */ -#include <linux/module.h> #include <linux/kernel.h> #include <linux/efi.h> #include <linux/errno.h> #include <linux/fb.h> #include <linux/platform_device.h> #include <linux/screen_info.h> -#include <linux/dmi.h> -#include <linux/pci.h> #include <video/vga.h> #include <asm/efi.h>
@@ -331,5 +328,4 @@ static struct platform_driver efifb_driver = { .remove = efifb_remove, }; -module_platform_driver (efifb_driver); -MODULE_LICENSE ("GPL" ); +builtin_platform_driver (efifb_driver);
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efifb: Use builtin_platform_driver and drop unused includes
efifb: Use builtin_platform_driver and drop unused includes
Commit-ID: 07ea7ec5df3ee4a9fedb3d81dc69c2f8d07d44c0 Gitweb: http://git.kernel.org/tip/07ea7ec5df3ee4a9fedb3d81dc69c2f8d07d44c0 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:51 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:58 +0200
efifb: Use builtin_platform_driver and drop unused includes
Since efifb can only be built directly into the kernel, drop the module specific includes and definitions. Drop some other includes we don't need as well.
--- drivers/video/fbdev/efifb.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/video/fbdev/efifb.c +1 -5
@@ -6,15 +6,12 @@* */ -#include <linux/module.h> #include <linux/kernel.h> #include <linux/efi.h> #include <linux/errno.h> #include <linux/fb.h> #include <linux/platform_device.h> #include <linux/screen_info.h> -#include <linux/dmi.h> -#include <linux/pci.h> #include <video/vga.h> #include <asm/efi.h>
@@ -331,5 +328,4 @@ static struct platform_driver efifb_driver = { .remove = efifb_remove, }; -module_platform_driver (efifb_driver); -MODULE_LICENSE ("GPL" ); +builtin_platform_driver (efifb_driver);
PATCH 20/40 arm64/efi: libstub: Make screen_info accessible to the UEFI stub
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Unlike on 32-bit ARM, where we need to pass the stub's version of struct screen_info to the kernel proper via a configuration table, on 64-bit ARM it simply involves making the core kernel's copy of struct screen_info visible to the stub by exposing an __efistub_ alias for it.
--- arch/arm64/include/asm/efi.h | 3 +++ arch/arm64/kernel/efi.c | 3 +++ arch/arm64/kernel/image.h | 1 + 3 files changed, 7 insertions(+)
arch/arm64/include/asm/efi.h +3 -0
@@ -56,6 +56,9 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);#define __efi_call_early (f, ...) f(__VA_ARGS__)#define efi_is_64bit () (true) +#define alloc_screen_info(x...) &screen_info +#define free_screen_info(x...) +#define EFI_ALLOC_ALIGN SZ_64K/*
arch/arm64/kernel/efi.c +3 -0
@@ -56,6 +56,9 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)return pgprot_val (PAGE_KERNEL_EXEC ); } +/* we will fill this structure from the stub, so don't put it in .bss */ +struct screen_info screen_info __section(.data); +int __init efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md) {pteval_t prot_val =create_mapping_protection (md);
arch/arm64/kernel/image.h +1 -0
@@ -112,6 +112,7 @@ __efistub___memset = KALLSYMS_HIDE(__pi_memset); __efistub__text =KALLSYMS_HIDE (_text); __efistub__end =KALLSYMS_HIDE (_end); __efistub__edata =KALLSYMS_HIDE (_edata); +__efistub_screen_info =KALLSYMS_HIDE (screen_info);#endif
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] arm64/efi/libstub: Make screen_info accessible to the UEFI stub
arm64/efi/libstub: Make screen_info accessible to the UEFI stub
Commit-ID: 57fdb89aeb7b0e3aab19847ab7399e5d76f11e6f Gitweb: http://git.kernel.org/tip/57fdb89aeb7b0e3aab19847ab7399e5d76f11e6f Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:52 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:59 +0200
arm64/efi/libstub: Make screen_info accessible to the UEFI stub
Unlike on 32-bit ARM, where we need to pass the stub's version of struct screen_info to the kernel proper via a configuration table, on 64-bit ARM it simply involves making the core kernel's copy of struct screen_info visible to the stub by exposing an __efistub_ alias for it.
--- arch/arm64/include/asm/efi.h | 3 +++ arch/arm64/kernel/efi.c | 3 +++ arch/arm64/kernel/image.h | 1 + 3 files changed, 7 insertions(+)
arch/arm64/include/asm/efi.h +3 -0
@@ -56,6 +56,9 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);#define __efi_call_early (f, ...) f(__VA_ARGS__)#define efi_is_64bit () (true) +#define alloc_screen_info(x...) &screen_info +#define free_screen_info(x...) +#define EFI_ALLOC_ALIGN SZ_64K/*
arch/arm64/kernel/efi.c +3 -0
@@ -56,6 +56,9 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)return pgprot_val (PAGE_KERNEL_EXEC ); } +/* we will fill this structure from the stub, so don't put it in .bss */ +struct screen_info screen_info __section(.data); +int __init efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md) {pteval_t prot_val =create_mapping_protection (md);
arch/arm64/kernel/image.h +1 -0
@@ -112,6 +112,7 @@ __efistub___memset = KALLSYMS_HIDE(__pi_memset); __efistub__text =KALLSYMS_HIDE (_text); __efistub__end =KALLSYMS_HIDE (_end); __efistub__edata =KALLSYMS_HIDE (_edata); +__efistub_screen_info =KALLSYMS_HIDE (screen_info);#endif
PATCH 21/40 efi/arm: libstub: Make screen_info accessible to the UEFI stub
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
In order to hand over the framebuffer described by the GOP protocol and discovered by the UEFI stub, make struct screen_info accessible by the stub. This involves allocating a loader data buffer and passing it to the kernel proper via a UEFI Configuration Table, since the UEFI stub executes in the context of the decompressor, and cannot access the kernel's copy of struct screen_info directly.
--- arch/arm/include/asm/efi.h | 3 +++ arch/arm/kernel/setup.c | 3 ++- drivers/firmware/efi/arm-init.c | 34 +++++++++++++++++++++++++++- drivers/firmware/efi/efi.c | 5 +++-- drivers/firmware/efi/libstub/arm32-stub.c | 37 +++++++++++++++++++++++++++++++ include/linux/efi.h | 11 ++++++++- 6 files changed, 88 insertions(+), 5 deletions(-)
arch/arm/include/asm/efi.h +3 -0
@@ -64,6 +64,9 @@ void efi_virtmap_unload(void);#define __efi_call_early (f, ...) f(__VA_ARGS__)#define efi_is_64bit () (false) +struct screen_info *alloc_screen_info (efi_system_table_t *sys_table_arg); +void free_screen_info (efi_system_table_t *sys_table,struct screen_info *si); +/* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, * so we will reserve that amount of memory. We have no easy way to tell what
arch/arm/kernel/setup.c +2 -1
@@ -883,7 +883,8 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)request_resource (&ioport_resource, &lp2); } -#if defined(CONFIG_VGA_CONSOLE ) || defined(CONFIG_DUMMY_CONSOLE ) +#if defined(CONFIG_VGA_CONSOLE ) || defined(CONFIG_DUMMY_CONSOLE ) || \ + defined(CONFIG_EFI )struct screen_info screen_info = { .orig_video_lines =30 , .orig_video_cols = 80,
drivers/firmware/efi/arm-init.c +33 -1
@@ -11,12 +11,15 @@* */ +#define pr_fmt (fmt) "efi: " fmt +#include <linux/efi.h> #include <linux/init.h> #include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/of.h> #include <linux/of_fdt.h> +#include <linux/screen_info.h> #include <asm/efi.h>
@@ -51,6 +54,32 @@ static phys_addr_t efi_to_phys(unsigned long addr)return addr; } +static __initdata unsigned long screen_info_table =EFI_INVALID_TABLE_ADDR ; + +static __initdata efi_config_table_type_t arch_tables[] = { + {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID ,NULL , &screen_info_table}, + {NULL_GUID ,NULL ,NULL } +}; + +static void __init init_screen_info (void ) +{ +struct screen_info *si; + +if (screen_info_table !=EFI_INVALID_TABLE_ADDR ) { + si =early_memremap_ro (screen_info_table,sizeof (*si)); +if (!si) { +pr_err ("Could not map screen_info config table\n" ); +return ; + } + screen_info = *si; +early_memunmap (si,sizeof (*si)); + +/* dummycon on ARM needs non-zero values for columns/lines */ + screen_info.orig_video_cols =80 ; + screen_info.orig_video_lines =25 ; + } +} +static int __init uefi_init (void ) {efi_char16_t *c16;
@@ -108,7 +137,8 @@ static int __init uefi_init(void) goto out; } retval =efi_config_parse_tables (config_tables, efi.systab->nr_tables, -sizeof (efi_config_table_t),NULL ); +sizeof (efi_config_table_t), + arch_tables);early_memunmap (config_tables, table_size); out:
@@ -223,4 +253,6 @@ void __init efi_init(void)PAGE_ALIGN (params.mmap_size + (params.mmap & ~PAGE_MASK))); } + +init_screen_info (); }
drivers/firmware/efi/efi.c +3 -2
@@ -353,8 +353,9 @@ static __init int match_config_table(efi_guid_t *guid,for (i =0 ;efi_guidcmp (table_types[i].guid,NULL_GUID ); i++) {if (!efi_guidcmp (*guid, table_types[i].guid)) { *(table_types[i].ptr) = table; -pr_cont (" %s=0x%lx " , - table_types[i].name, table); +if (table_types[i].name) +pr_cont (" %s=0x%lx " , + table_types[i].name, table);return 1 ; } }
drivers/firmware/efi/libstub/arm32-stub.c +37 -0
@@ -26,6 +26,43 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)return EFI_SUCCESS ; } +static efi_guid_t screen_info_guid =LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID ; + +struct screen_info *alloc_screen_info (efi_system_table_t *sys_table_arg) +{ +struct screen_info *si; +efi_status_t status; + +/* +* Unlike on arm64, where we can directly fill out the screen_info +* structure from the stub, we need to allocate a buffer to hold +* its contents while we hand over to the kernel proper from the +* decompressor. +*/ + status =efi_call_early (allocate_pool,EFI_RUNTIME_SERVICES_DATA , +sizeof (*si), (void **)&si); + +if (status !=EFI_SUCCESS ) +return NULL ; + + status =efi_call_early (install_configuration_table, + &screen_info_guid, si); +if (status ==EFI_SUCCESS ) +return si; + +efi_call_early (free_pool, si); +return NULL ; +} + +void free_screen_info (efi_system_table_t *sys_table_arg,struct screen_info *si) +{ +if (!si) +return ; + +efi_call_early (install_configuration_table, &screen_info_guid,NULL ); +efi_call_early (free_pool, si); +} + efi_status_t handle_kernel_image(efi_system_table_t *sys_table, unsigned long *image_addr, unsigned long *image_size,
include/linux/efi.h +10 -1
@@ -286,7 +286,7 @@ typedef struct {efi_status_t (*locate_handle)(int ,efi_guid_t *,void *,unsigned long *,efi_handle_t *);void *locate_device_path; -void *install_configuration_table; +efi_status_t (*install_configuration_table)(efi_guid_t *,void *);void *load_image;void *start_image;void *exit;
@@ -633,6 +633,15 @@ void efi_native_runtime_setup(void);EFI_GUID (0xd3b36f2c ,0xd551 ,0x11d4 , \0x9a ,0x46 ,0x00 ,0x90 ,0x27 ,0x3f ,0xc1 ,0x4d ) +/* +* This GUID is used to pass to the kernel proper the struct screen_info +* structure that was populated by the stub based on the GOP protocol instance +* associated with ConOut + */ +#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID \ + EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, \ + 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) + typedef struct { efi_guid_t guid; u64 table;
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/arm/libstub: Make screen_info accessible to the UEFI stub
efi/arm/libstub: Make screen_info accessible to the UEFI stub
Commit-ID: 801820bee9bccb7c156af2b95c7208f428a06ae7 Gitweb: http://git.kernel.org/tip/801820bee9bccb7c156af2b95c7208f428a06ae7 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:53 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:33:59 +0200
efi/arm/libstub: Make screen_info accessible to the UEFI stub
In order to hand over the framebuffer described by the GOP protocol and discovered by the UEFI stub, make struct screen_info accessible by the stub. This involves allocating a loader data buffer and passing it to the kernel proper via a UEFI Configuration Table, since the UEFI stub executes in the context of the decompressor, and cannot access the kernel's copy of struct screen_info directly.
--- arch/arm/include/asm/efi.h | 3 +++ arch/arm/kernel/setup.c | 3 ++- drivers/firmware/efi/arm-init.c | 34 +++++++++++++++++++++++++++- drivers/firmware/efi/efi.c | 5 +++-- drivers/firmware/efi/libstub/arm32-stub.c | 37 +++++++++++++++++++++++++++++++ include/linux/efi.h | 11 ++++++++- 6 files changed, 88 insertions(+), 5 deletions(-)
arch/arm/include/asm/efi.h +3 -0
@@ -64,6 +64,9 @@ void efi_virtmap_unload(void);#define __efi_call_early (f, ...) f(__VA_ARGS__)#define efi_is_64bit () (false) +struct screen_info *alloc_screen_info (efi_system_table_t *sys_table_arg); +void free_screen_info (efi_system_table_t *sys_table,struct screen_info *si); +/* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, * so we will reserve that amount of memory. We have no easy way to tell what
arch/arm/kernel/setup.c +2 -1
@@ -883,7 +883,8 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)request_resource (&ioport_resource, &lp2); } -#if defined(CONFIG_VGA_CONSOLE ) || defined(CONFIG_DUMMY_CONSOLE ) +#if defined(CONFIG_VGA_CONSOLE ) || defined(CONFIG_DUMMY_CONSOLE ) || \ + defined(CONFIG_EFI )struct screen_info screen_info = { .orig_video_lines =30 , .orig_video_cols = 80,
drivers/firmware/efi/arm-init.c +33 -1
@@ -11,12 +11,15 @@* */ +#define pr_fmt (fmt) "efi: " fmt +#include <linux/efi.h> #include <linux/init.h> #include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/of.h> #include <linux/of_fdt.h> +#include <linux/screen_info.h> #include <asm/efi.h>
@@ -51,6 +54,32 @@ static phys_addr_t efi_to_phys(unsigned long addr)return addr; } +static __initdata unsigned long screen_info_table =EFI_INVALID_TABLE_ADDR ; + +static __initdata efi_config_table_type_t arch_tables[] = { + {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID ,NULL , &screen_info_table}, + {NULL_GUID ,NULL ,NULL } +}; + +static void __init init_screen_info (void ) +{ +struct screen_info *si; + +if (screen_info_table !=EFI_INVALID_TABLE_ADDR ) { + si =early_memremap_ro (screen_info_table,sizeof (*si)); +if (!si) { +pr_err ("Could not map screen_info config table\n" ); +return ; + } + screen_info = *si; +early_memunmap (si,sizeof (*si)); + +/* dummycon on ARM needs non-zero values for columns/lines */ + screen_info.orig_video_cols =80 ; + screen_info.orig_video_lines =25 ; + } +} +static int __init uefi_init (void ) {efi_char16_t *c16;
@@ -108,7 +137,8 @@ static int __init uefi_init(void) goto out; } retval =efi_config_parse_tables (config_tables, efi.systab->nr_tables, -sizeof (efi_config_table_t),NULL ); +sizeof (efi_config_table_t), + arch_tables);early_memunmap (config_tables, table_size); out:
@@ -223,4 +253,6 @@ void __init efi_init(void)PAGE_ALIGN (params.mmap_size + (params.mmap & ~PAGE_MASK))); } + +init_screen_info (); }
drivers/firmware/efi/efi.c +3 -2
@@ -353,8 +353,9 @@ static __init int match_config_table(efi_guid_t *guid,for (i =0 ;efi_guidcmp (table_types[i].guid,NULL_GUID ); i++) {if (!efi_guidcmp (*guid, table_types[i].guid)) { *(table_types[i].ptr) = table; -pr_cont (" %s=0x%lx " , - table_types[i].name, table); +if (table_types[i].name) +pr_cont (" %s=0x%lx " , + table_types[i].name, table);return 1 ; } }
drivers/firmware/efi/libstub/arm32-stub.c +37 -0
@@ -26,6 +26,43 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)return EFI_SUCCESS ; } +static efi_guid_t screen_info_guid =LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID ; + +struct screen_info *alloc_screen_info (efi_system_table_t *sys_table_arg) +{ +struct screen_info *si; +efi_status_t status; + +/* +* Unlike on arm64, where we can directly fill out the screen_info +* structure from the stub, we need to allocate a buffer to hold +* its contents while we hand over to the kernel proper from the +* decompressor. +*/ + status =efi_call_early (allocate_pool,EFI_RUNTIME_SERVICES_DATA , +sizeof (*si), (void **)&si); + +if (status !=EFI_SUCCESS ) +return NULL ; + + status =efi_call_early (install_configuration_table, + &screen_info_guid, si); +if (status ==EFI_SUCCESS ) +return si; + +efi_call_early (free_pool, si); +return NULL ; +} + +void free_screen_info (efi_system_table_t *sys_table_arg,struct screen_info *si) +{ +if (!si) +return ; + +efi_call_early (install_configuration_table, &screen_info_guid,NULL ); +efi_call_early (free_pool, si); +} + efi_status_t handle_kernel_image(efi_system_table_t *sys_table, unsigned long *image_addr, unsigned long *image_size,
include/linux/efi.h +10 -1
@@ -286,7 +286,7 @@ typedef struct {efi_status_t (*locate_handle)(int ,efi_guid_t *,void *,unsigned long *,efi_handle_t *);void *locate_device_path; -void *install_configuration_table; +efi_status_t (*install_configuration_table)(efi_guid_t *,void *);void *load_image;void *start_image;void *exit;
@@ -633,6 +633,15 @@ void efi_native_runtime_setup(void);EFI_GUID (0xd3b36f2c ,0xd551 ,0x11d4 , \0x9a ,0x46 ,0x00 ,0x90 ,0x27 ,0x3f ,0xc1 ,0x4d ) +/* +* This GUID is used to pass to the kernel proper the struct screen_info +* structure that was populated by the stub based on the GOP protocol instance +* associated with ConOut + */ +#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID \ + EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, \ + 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) + typedef struct { efi_guid_t guid; u64 table;
PATCH 22/40 efi/arm*: libstub: Wire up GOP protocol to struct screen_info
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
This adds the code to the ARM and arm64 versions of the UEFI stub to populate struct screen_info based on the information received from the firmware via the GOP protocol.
--- drivers/firmware/efi/libstub/arm-stub.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
drivers/firmware/efi/libstub/arm-stub.c +23 -0
@@ -169,6 +169,25 @@ void efi_char16_printk(efi_system_table_t *sys_table_arg, out->output_string (out, str); } +static struct screen_info *setup_graphics (efi_system_table_t *sys_table_arg) +{ +efi_guid_t gop_proto =EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID ; +efi_status_t status; +unsigned long size; +void **gop_handle =NULL ; +struct screen_info *si =NULL ; + + size =0 ; + status =efi_call_early (locate_handle,EFI_LOCATE_BY_PROTOCOL , + &gop_proto,NULL , &size, gop_handle); +if (status ==EFI_BUFFER_TOO_SMALL ) { + si =alloc_screen_info (sys_table_arg); +if (!si) +return NULL ; +efi_setup_gop (sys_table_arg, si, &gop_proto, size); + } +return si; +}/* * This function handles the architcture specific differences between arm and
@@ -208,6 +227,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,unsigned long reserve_addr =0 ;unsigned long reserve_size =0 ;int secure_boot =0 ; +struct screen_info *si;/* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature !=EFI_SYSTEM_TABLE_SIGNATURE )
@@ -260,6 +280,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, __nokaslr = true; } + si =setup_graphics (sys_table); + status = handle_kernel_image(sys_table, image_addr, &image_size, &reserve_addr, &reserve_size,
@@ -341,6 +363,7 @@ fail_free_image:efi_free (sys_table, image_size, *image_addr);efi_free (sys_table, reserve_size, reserve_addr); fail_free_cmdline: +free_screen_info (sys_table, si);efi_free (sys_table, cmdline_size, (unsigned long )cmdline_ptr); fail:return EFI_ERROR ;
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/arm*/libstub: Wire up GOP protocol to 'struct screen_info'
efi/arm*/libstub: Wire up GOP protocol to 'struct screen_info'
Commit-ID: f0827e18a7a1da574ba8201a8b18f63778451aae Gitweb: http://git.kernel.org/tip/f0827e18a7a1da574ba8201a8b18f63778451aae Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:54 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:00 +0200
efi/arm*/libstub: Wire up GOP protocol to 'struct screen_info'
This adds the code to the ARM and arm64 versions of the UEFI stub to populate struct screen_info based on the information received from the firmware via the GOP protocol.
--- drivers/firmware/efi/libstub/arm-stub.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
drivers/firmware/efi/libstub/arm-stub.c +23 -0
@@ -169,6 +169,25 @@ void efi_char16_printk(efi_system_table_t *sys_table_arg, out->output_string (out, str); } +static struct screen_info *setup_graphics (efi_system_table_t *sys_table_arg) +{ +efi_guid_t gop_proto =EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID ; +efi_status_t status; +unsigned long size; +void **gop_handle =NULL ; +struct screen_info *si =NULL ; + + size =0 ; + status =efi_call_early (locate_handle,EFI_LOCATE_BY_PROTOCOL , + &gop_proto,NULL , &size, gop_handle); +if (status ==EFI_BUFFER_TOO_SMALL ) { + si =alloc_screen_info (sys_table_arg); +if (!si) +return NULL ; +efi_setup_gop (sys_table_arg, si, &gop_proto, size); + } +return si; +}/* * This function handles the architcture specific differences between arm and
@@ -208,6 +227,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,unsigned long reserve_addr =0 ;unsigned long reserve_size =0 ;int secure_boot =0 ; +struct screen_info *si;/* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature !=EFI_SYSTEM_TABLE_SIGNATURE )
@@ -260,6 +280,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, __nokaslr = true; } + si =setup_graphics (sys_table); + status = handle_kernel_image(sys_table, image_addr, &image_size, &reserve_addr, &reserve_size,
@@ -341,6 +363,7 @@ fail_free_image:efi_free (sys_table, image_size, *image_addr);efi_free (sys_table, reserve_size, reserve_addr); fail_free_cmdline: +free_screen_info (sys_table, si);efi_free (sys_table, cmdline_size, (unsigned long )cmdline_ptr); fail:return EFI_ERROR ;
PATCH 23/40 efi/arm*: Wire up struct screen_info to efi-framebuffer platform device
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
This adds code to the ARM and arm64 EFI init routines to expose a platform device of type 'efi-framebuffer' if struct screen_info has been populated appropriately from the GOP protocol by the stub. Since the framebuffer may potentially be located in system RAM, make sure that the region is reserved and marked MEMBLOCK_NOMAP.
--- drivers/firmware/efi/arm-init.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/firmware/efi/arm-init.c +18 -0
@@ -19,6 +19,7 @@#include <linux/mm_types.h> #include <linux/of.h> #include <linux/of_fdt.h> +#include <linux/platform_device.h> #include <linux/screen_info.h> #include <asm/efi.h>
@@ -78,6 +79,10 @@ static void __init init_screen_info(void) screen_info.orig_video_cols =80 ; screen_info.orig_video_lines =25 ; } + +if (screen_info.orig_video_isVGA ==VIDEO_TYPE_EFI && +memblock_is_map_memory (screen_info.lfb_base)) +memblock_mark_nomap (screen_info.lfb_base, screen_info.lfb_size); }static int __init uefi_init (void )
@@ -256,3 +261,16 @@ void __init efi_init(void)init_screen_info (); } + +static int __init register_gop_device (void ) +{ +void *pd; + +if (screen_info.orig_video_isVGA !=VIDEO_TYPE_EFI ) +return 0 ; + + pd =platform_device_register_data (NULL ,"efi-framebuffer" ,0 , + &screen_info,sizeof (screen_info)); +return PTR_ERR_OR_ZERO (pd); +} +subsys_initcall (register_gop_device);
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/arm*: Wire up 'struct screen_info' to efi-framebuffer platform device
efi/arm*: Wire up 'struct screen_info' to efi-framebuffer platform device
Commit-ID: e3271c96ca7d01957b03b5f1e2bdc00e08fd7160 Gitweb: http://git.kernel.org/tip/e3271c96ca7d01957b03b5f1e2bdc00e08fd7160 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:55 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:01 +0200
efi/arm*: Wire up 'struct screen_info' to efi-framebuffer platform device
This adds code to the ARM and arm64 EFI init routines to expose a platform device of type 'efi-framebuffer' if 'struct screen_info' has been populated appropriately from the GOP protocol by the stub. Since the framebuffer may potentially be located in system RAM, make sure that the region is reserved and marked MEMBLOCK_NOMAP.
--- drivers/firmware/efi/arm-init.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/firmware/efi/arm-init.c +18 -0
@@ -19,6 +19,7 @@#include <linux/mm_types.h> #include <linux/of.h> #include <linux/of_fdt.h> +#include <linux/platform_device.h> #include <linux/screen_info.h> #include <asm/efi.h>
@@ -78,6 +79,10 @@ static void __init init_screen_info(void) screen_info.orig_video_cols =80 ; screen_info.orig_video_lines =25 ; } + +if (screen_info.orig_video_isVGA ==VIDEO_TYPE_EFI && +memblock_is_map_memory (screen_info.lfb_base)) +memblock_mark_nomap (screen_info.lfb_base, screen_info.lfb_size); }static int __init uefi_init (void )
@@ -256,3 +261,16 @@ void __init efi_init(void)init_screen_info (); } + +static int __init register_gop_device (void ) +{ +void *pd; + +if (screen_info.orig_video_isVGA !=VIDEO_TYPE_EFI ) +return 0 ; + + pd =platform_device_register_data (NULL ,"efi-framebuffer" ,0 , + &screen_info,sizeof (screen_info)); +return PTR_ERR_OR_ZERO (pd); +} +subsys_initcall (register_gop_device);
PATCH 24/40 efifb: Enable the efi-framebuffer platform driver for ARM and arm64
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Allows the efifb driver to be built for ARM and arm64. This simply involves updating the Kconfig dependency expression, and supplying dummy versions of efifb_setup_from_dmi().
--- arch/arm/include/asm/efi.h | 4 ++++ arch/arm64/include/asm/efi.h | 4 ++++ drivers/video/fbdev/Kconfig | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-)
arch/arm/include/asm/efi.h +4 -0
@@ -67,6 +67,10 @@ void efi_virtmap_unload(void);struct screen_info *alloc_screen_info (efi_system_table_t *sys_table_arg);void free_screen_info (efi_system_table_t *sys_table,struct screen_info *si); +static inline void efifb_setup_from_dmi (struct screen_info *si,const char *opt) +{ +} +/* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, * so we will reserve that amount of memory. We have no easy way to tell what
arch/arm64/include/asm/efi.h +4 -0
@@ -59,6 +59,10 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); #define alloc_screen_info(x...) &screen_info #define free_screen_info(x...) +static inline void efifb_setup_from_dmi (struct screen_info *si,const char *opt) +{ +} +#define EFI_ALLOC_ALIGN SZ_64K/*
drivers/video/fbdev/Kconfig +1 -1
@@ -761,7 +761,7 @@ config FB_VESA config FB_EFI bool "EFI-based Framebuffer Support" - depends on (FB = y) && X86 && EFI + depends on (FB = y) && !IA64 && EFI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efifb: Enable the efi-framebuffer platform driver for ARM and arm64
efifb: Enable the efi-framebuffer platform driver for ARM and arm64
Commit-ID: 9822504c1fa5c557ea8776765f03fd16eb4de4c9 Gitweb: http://git.kernel.org/tip/9822504c1fa5c557ea8776765f03fd16eb4de4c9 Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:56 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:01 +0200
efifb: Enable the efi-framebuffer platform driver for ARM and arm64
Allows the efifb driver to be built for ARM and arm64. This simply involves updating the Kconfig dependency expression, and supplying dummy versions of efifb_setup_from_dmi().
--- arch/arm/include/asm/efi.h | 4 ++++ arch/arm64/include/asm/efi.h | 4 ++++ drivers/video/fbdev/Kconfig | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-)
arch/arm/include/asm/efi.h +4 -0
@@ -67,6 +67,10 @@ void efi_virtmap_unload(void);struct screen_info *alloc_screen_info (efi_system_table_t *sys_table_arg);void free_screen_info (efi_system_table_t *sys_table,struct screen_info *si); +static inline void efifb_setup_from_dmi (struct screen_info *si,const char *opt) +{ +} +/* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, * so we will reserve that amount of memory. We have no easy way to tell what
arch/arm64/include/asm/efi.h +4 -0
@@ -59,6 +59,10 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); #define alloc_screen_info(x...) &screen_info #define free_screen_info(x...) +static inline void efifb_setup_from_dmi (struct screen_info *si,const char *opt) +{ +} +#define EFI_ALLOC_ALIGN SZ_64K/*
drivers/video/fbdev/Kconfig +1 -1
@@ -761,7 +761,7 @@ config FB_VESA config FB_EFI bool "EFI-based Framebuffer Support" - depends on (FB = y) && X86 && EFI + depends on (FB = y) && !IA64 && EFI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT
PATCH 25/40 efibc: EFI Bootloader Control
In reply to Matt FlemingFrom: "Compostella, Jeremy" <[email protected]>
This module installs a reboot hook, such that if reboot() is invoked with a string argument NNN, "NNN" is copied to the "LoaderEntryOneShot" EFI variable, to be read by the bootloader. If the string matches one of the boot labels defined in its configuration, the bootloader will boot once to that label. The "LoaderEntryRebootReason" EFI variable is set with the reboot reason:
"reboot", "shutdown". The bootloader reads this reboot reason and takes particular action according to its policy.
There are reboot implementations that do "reboot <reason>", such as Android's reboot command and Upstart's reboot replacement, which pass the reason as an argument to the reboot syscall. There is no platform-agnostic way how those could be modified to pass the reason to the bootloader, regardless of platform or bootloader.
--- drivers/firmware/efi/Kconfig | 15 +++++++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efibc.c | 101 ++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 4 ++ 4 files changed, 121 insertions(+) create mode 100644 drivers/firmware/efi/efibc.c
drivers/firmware/efi/Kconfig +15 -0
@@ -87,6 +87,21 @@ config EFI_RUNTIME_WRAPPERS config EFI_ARMSTUB bool +config EFI_BOOTLOADER_CONTROL + tristate "EFI Bootloader Control" + depends on EFI_VARS + default n + ---help--- + This module installs a reboot hook, such that if reboot() is + invoked with a string argument NNN, "NNN" is copied to the + "LoaderEntryOneShot" EFI variable, to be read by the + bootloader. If the string matches one of the boot labels + defined in its configuration, the bootloader will boot once + to that label. The "LoaderEntryRebootReason" EFI variable is + set with the reboot reason: "reboot" or "shutdown". The + bootloader reads this reboot reason and takes particular + action according to its policy. + endmenu config UEFI_CPER
drivers/firmware/efi/Makefile +1 -0
@@ -18,6 +18,7 @@ obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o obj-$(CONFIG_EFI_STUB) += libstub/ obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o +obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y)
drivers/firmware/efi/efibc.c new file +101 -0
101 lines not on this page · raw message
include/linux/efi.h +4 -0
@@ -642,6 +642,10 @@ void efi_native_runtime_setup(void);EFI_GUID (0xe03fc20a ,0x85dc ,0x406e , \ 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) +#define LINUX_EFI_LOADER_ENTRY_GUID \ + EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, \ + 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) + typedef struct { efi_guid_t guid; u64 table;
Signature · 1 line
2.7.3
tip-bot for Compostella, Jeremy
merge bot[tip:efi/core] efibc: Add EFI Bootloader Control module
efibc: Add EFI Bootloader Control module
Commit-ID: 06f7d4a1618dbb086e738c93cd1ef416ab01027d Gitweb: http://git.kernel.org/tip/06f7d4a1618dbb086e738c93cd1ef416ab01027d Author: Compostella, Jeremy <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:57 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:02 +0200
efibc: Add EFI Bootloader Control module
This module installs a reboot callback, such that if reboot() is invoked with a string argument NNN, "NNN" is copied to the "LoaderEntryOneShot" EFI variable, to be read by the bootloader.
If the string matches one of the boot labels defined in its configuration, the bootloader will boot once to that label. The "LoaderEntryRebootReason" EFI variable is set with the reboot reason: "reboot", "shutdown".
The bootloader reads this reboot reason and takes particular action according to its policy.
There are reboot implementations that do "reboot <reason>", such as Android's reboot command and Upstart's reboot replacement, which pass the reason as an argument to the reboot syscall. There is no platform-agnostic way how those could be modified to pass the reason to the bootloader, regardless of platform or bootloader.
--- drivers/firmware/efi/Kconfig | 15 +++++++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efibc.c | 101 ++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 4 ++ 4 files changed, 121 insertions(+)
drivers/firmware/efi/Kconfig +15 -0
@@ -87,6 +87,21 @@ config EFI_RUNTIME_WRAPPERS config EFI_ARMSTUB bool +config EFI_BOOTLOADER_CONTROL + tristate "EFI Bootloader Control" + depends on EFI_VARS + default n + ---help--- + This module installs a reboot hook, such that if reboot() is + invoked with a string argument NNN, "NNN" is copied to the + "LoaderEntryOneShot" EFI variable, to be read by the + bootloader. If the string matches one of the boot labels + defined in its configuration, the bootloader will boot once + to that label. The "LoaderEntryRebootReason" EFI variable is + set with the reboot reason: "reboot" or "shutdown". The + bootloader reads this reboot reason and takes particular + action according to its policy. + endmenu config UEFI_CPER
drivers/firmware/efi/Makefile +1 -0
@@ -18,6 +18,7 @@ obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o obj-$(CONFIG_EFI_STUB) += libstub/ obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o +obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y)
drivers/firmware/efi/efibc.c new file +101 -0
101 lines not on this page · raw message
include/linux/efi.h +4 -0
@@ -642,6 +642,10 @@ void efi_native_runtime_setup(void);EFI_GUID (0xe03fc20a ,0x85dc ,0x406e , \ 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) +#define LINUX_EFI_LOADER_ENTRY_GUID \ + EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, \ + 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) + typedef struct { efi_guid_t guid; u64 table;
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 13 lines · tip-bot for Compostella, Jeremy
Commit-ID: 06f7d4a1618dbb086e738c93cd1ef416ab01027d Gitweb: http://git.kernel.org/tip/06f7d4a1618dbb086e738c93cd1ef416ab01027d Author: Compostella, Jeremy <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:57 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:02 +0200efibc: Add EFI Bootloader Control module
This module installs a reboot callback, such that if
reboot()is invoked with a string argument NNN, "NNN" is copied to the "LoaderEntryOneShot" EFI variable, to be read by the bootloader.
Quoted 5 lines
drivers/firmware/efi/Kconfig | 15 +++++++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efibc.c | 101 ++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 4 ++ 4 files changed, 121 insertions(+)
So this bloated things a bit on 32-bit x86 allyesconfig kernels, we now have this new warning:
drivers/firmware/efi/efibc.c:53:1: warning: the frame size of 2256 bytes is larger than 1024 bytes [-Wframe-larger-than=]
2K of stack use for a function is quite excessive, can we improve the stack footprint of this code?
Thanks,
Ingo
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 22 lines · Ingo Molnar
Quoted 13 lines · tip-bot for Compostella, Jeremy
Commit-ID: 06f7d4a1618dbb086e738c93cd1ef416ab01027d Gitweb: http://git.kernel.org/tip/06f7d4a1618dbb086e738c93cd1ef416ab01027d Author: Compostella, Jeremy <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:57 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:02 +0200efibc: Add EFI Bootloader Control module
This module installs a reboot callback, such that if
reboot()is invoked with a string argument NNN, "NNN" is copied to the "LoaderEntryOneShot" EFI variable, to be read by the bootloader.Quoted 5 lines
drivers/firmware/efi/Kconfig | 15 +++++++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efibc.c | 101 ++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 4 ++ 4 files changed, 121 insertions(+)
Quoted 7 lines
So this bloated things a bit on 32-bit x86 allyesconfig kernels, we now have this new warning:
drivers/firmware/efi/efibc.c:53:1: warning: the frame size of 2256 bytes is larger than 1024 bytes [-Wframe-larger-than=]2K of stack use for a function is quite excessive, can we improve the stack footprint of this code?
I'm waiting to hear from Jeremy on whether we can simply move the struct efivar_entry (which is the cause of the stack bloat) off the stack and into the .bss, because it only gets used from the reboot notifier call chain.
But upon reading kernel_restart() I'm no longer sure it's guaranteed to be called only once, or even non-concurrently. It seems that if the user executes the reboot command and either the sysrq reboot code is invoked, or an error is encountered dm-verify-target driver or any other kernel_restart() caller is invoked we could race.
Perhaps we should guard efi_reboot_notifier_call() with an atomic_t and exit if we've already invoked it?
Alternatively, we could just kmalloc() the object ;)
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 43 lines · Matt Fleming
Quoted 22 lines · Ingo Molnar
Quoted 13 lines · tip-bot for Compostella, Jeremy
Commit-ID: 06f7d4a1618dbb086e738c93cd1ef416ab01027d Gitweb: http://git.kernel.org/tip/06f7d4a1618dbb086e738c93cd1ef416ab01027d Author: Compostella, Jeremy <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:57 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:02 +0200efibc: Add EFI Bootloader Control module
This module installs a reboot callback, such that if
reboot()is invoked with a string argument NNN, "NNN" is copied to the "LoaderEntryOneShot" EFI variable, to be read by the bootloader.Quoted 5 lines
drivers/firmware/efi/Kconfig | 15 +++++++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efibc.c | 101 ++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 4 ++ 4 files changed, 121 insertions(+)Quoted 8 lines
So this bloated things a bit on 32-bit x86 allyesconfig kernels, we now have this new warning:
drivers/firmware/efi/efibc.c:53:1: warning: the frame size of 2256
bytes is larger than 1024 bytes [-Wframe-larger-than=]2K of stack use for a function is quite excessive, can we improve the stack footprint of this code?
I'm waiting to hear from Jeremy on whether we can simply move the struct
efivar_entry(which is the cause of the stack bloat) off the stack and into the .bss, because it only gets used from the reboot notifier call chain.But upon reading
kernel_restart()I'm no longer sure it's guaranteed to be called only once, or even non-concurrently. It seems that if the user executes the reboot command and either the sysrq reboot code is invoked, or an error is encountered dm-verify-target driver or any otherkernel_restart()caller is invoked we could race.
Quoted 4 lines
Perhaps we should guard
efi_reboot_notifier_call()with anatomic_tand exit if we've already invoked it?Alternatively, we could just
kmalloc()the object ;)
I would go for this last proposal because it fixes the issue, it works with the potential race condition you mentioned and it is a simple solution. Yet, it means that if we really run into a race condition, the LoaderEntryOneShot value might be indeterminate.
Though, this is a very unlikely situation and if it happens I cannot think of any good reason to prefer to store the first restart target or the second.
Do you want me to make this change ?
Jérémy
Signature · 1 line
One Emacs to rule them all
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 10 lines · Jeremy Compostella
I would go for this last proposal because it fixes the issue, it works with the potential race condition you mentioned and it is a simple solution. Yet, it means that if we really run into a race condition, the LoaderEntryOneShot value might be indeterminate.
Though, this is a very unlikely situation and if it happens I cannot think of any good reason to prefer to store the first restart target or the second.
Do you want me to make this change ?
Yes please, that'd be greatly appreciated. Be sure to do it on top of either the EFI 'next' branch or tip:efi/core.
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 6 lines · Matt Fleming
Quoted 5 lines · Jeremy Compostella
I would go for this last proposal because it fixes the issue, it works with the potential race condition you mentioned and it is a simple solution. Yet, it means that if we really run into a race condition, the LoaderEntryOneShot value might be indeterminate.
Quoted 8 lines
Quoted 5 lines
Though, this is a very unlikely situation and if it happens I cannot think of any good reason to prefer to store the first restart target or the second.
Do you want me to make this change ?
Yes please, that'd be greatly appreciated. Be sure to do it on top of either the EFI 'next' branch or tip:efi/core.
Please, find the patch in attachment. I wrote it on top of tip:efi/core.
Quoted 1 line
From
ef3a2941769e59b11d1ec36117209dc4c90c7cf9Mon Sep 17 00:00:00 2001
From: Jeremy Compostella <[email protected]>
Date: Fri, 29 Apr 2016 15:29:59 +0200
Subject: [PATCH] efibc: fix excessive stack footprint warning
Use dynamic memory allocation instead of stack memory for the entry object.
This patch also fixes a potential buffer override.
--- drivers/firmware/efi/efibc.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)
drivers/firmware/efi/efibc.c +24 -12
@@ -17,6 +17,7 @@#include <linux/efi.h> #include <linux/module.h> #include <linux/reboot.h> +#include <linux/slab.h> static void efibc_str_to_str16 (const char *str,efi_char16_t *str16) {
@@ -28,42 +29,53 @@ static void efibc_str_to_str16(const char *str, efi_char16_t *str16) str16[i] ='\0' ; } -static void efibc_set_variable (const char *name,const char *value) +static int efibc_set_variable (const char *name,const char *value) {int ret;efi_guid_t guid =LINUX_EFI_LOADER_ENTRY_GUID ; -struct efivar_entry entry; +struct efivar_entry *entry;size_t size = (strlen (value) +1 ) *sizeof (efi_char16_t); -if (size >sizeof (entry.var.Data)) +if (size >sizeof (entry->var.Data)) {pr_err ("value is too large" ); +return -1 ; + } -efibc_str_to_str16 (name, entry.var.VariableName); -efibc_str_to_str16 (value, (efi_char16_t *)entry.var.Data); -memcpy (&entry.var.VendorGuid, &guid,sizeof (guid)); + entry =kmalloc (sizeof (*entry),GFP_KERNEL ); +if (!entry) { +pr_err ("failed to allocate efivar entry" ); +return -1 ; + } - ret =efivar_entry_set (&entry, +efibc_str_to_str16 (name, entry->var.VariableName); +efibc_str_to_str16 (value, (efi_char16_t *)entry->var.Data); +memcpy (&entry->var.VendorGuid, &guid,sizeof (guid)); + + ret =efivar_entry_set (entry,EFI_VARIABLE_NON_VOLATILE |EFI_VARIABLE_BOOTSERVICE_ACCESS |EFI_VARIABLE_RUNTIME_ACCESS , - size, entry.var.Data,NULL ); + size, entry->var.Data,NULL );if (ret)pr_err ("failed to set %s EFI variable: 0x%x\n" , name, ret); + +kfree (entry); +return ret; }static int efibc_reboot_notifier_call (struct notifier_block *notifier,unsigned long event,void *data) {const char *reason ="shutdown" ; +int ret;if (event ==SYS_RESTART ) reason ="reboot" ; -efibc_set_variable ("LoaderEntryRebootReason" , reason); - -if (!data) -return NOTIFY_DONE ; + ret =efibc_set_variable ("LoaderEntryRebootReason" , reason); +if (ret || !data) +return NOTIFY_DONE ;efibc_set_variable ("LoaderEntryOneShot" , (char *)data);
Signature · 1 line
1.9.1
Jérémy
Signature · 1 line
One Emacs to rule them all
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 51 lines · Compostella, Jeremy
drivers/firmware/efi/efibc.c +20
-8-static void efibc_set_variable (const char *name,const char *value) +static int efibc_set_variable (const char *name,const char *value) {int ret;efi_guid_t guid =LINUX_EFI_LOADER_ENTRY_GUID ; -struct efivar_entry entry; +struct efivar_entry *entry;size_t size = (strlen (value) +1 ) *sizeof (efi_char16_t); -if (size >sizeof (entry.var.Data)) +if (size >sizeof (entry->var.Data)) {pr_err ("value is too large" ); +return -1 ; + } -efibc_str_to_str16 (name, entry.var.VariableName); -efibc_str_to_str16 (value, (efi_char16_t *)entry.var.Data); -memcpy (&entry.var.VendorGuid, &guid,sizeof (guid)); + entry =kmalloc (sizeof (*entry),GFP_KERNEL ); +if (!entry) { +pr_err ("failed to allocate efivar entry" ); +return -1 ; + } - ret =efivar_entry_set (&entry, +efibc_str_to_str16 (name, entry->var.VariableName); +efibc_str_to_str16 (value, (efi_char16_t *)entry->var.Data); +memcpy (&entry->var.VendorGuid, &guid,sizeof (guid)); + + ret =efivar_entry_set (entry,EFI_VARIABLE_NON_VOLATILE |EFI_VARIABLE_BOOTSERVICE_ACCESS |EFI_VARIABLE_RUNTIME_ACCESS , - size, entry.var.Data,NULL ); + size, entry->var.Data,NULL );if (ret)pr_err ("failed to set %s EFI variable: 0x%x\n" , name, ret); + +kfree (entry); +return ret; }static int efibc_reboot_notifier_call (struct notifier_block *notifier,unsigned long event,void *data) {const char *reason ="shutdown" ; +int ret;if (event ==SYS_RESTART ) reason ="reboot" ;
drivers/firmware/efi/efibc.c static void efibc_str_to_str16(const char *str, efi_char16_t *str16) · line 80
Quoted 10 lines
drivers/firmware/efi/efibc.c +3
-4-efibc_set_variable ("LoaderEntryRebootReason" , reason); - -if (!data) -return NOTIFY_DONE ; + ret =efibc_set_variable ("LoaderEntryRebootReason" , reason); +if (ret || !data) +return NOTIFY_DONE ;efibc_set_variable ("LoaderEntryOneShot" , (char *)data);
Hm, can reboot notifiers do non-atomic allocations?
Why is efivar_entry so huge?
Thanks,
Ingo
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 62 lines · Ingo Molnar
Quoted 60 lines · Compostella, Jeremy
drivers/firmware/efi/efibc.c +23
-12-static void efibc_set_variable (const char *name,const char *value) +static int efibc_set_variable (const char *name,const char *value) {int ret;efi_guid_t guid =LINUX_EFI_LOADER_ENTRY_GUID ; -struct efivar_entry entry; +struct efivar_entry *entry;size_t size = (strlen (value) +1 ) *sizeof (efi_char16_t); -if (size >sizeof (entry.var.Data)) +if (size >sizeof (entry->var.Data)) {pr_err ("value is too large" ); +return -1 ; + } -efibc_str_to_str16 (name, entry.var.VariableName); -efibc_str_to_str16 (value, (efi_char16_t *)entry.var.Data); -memcpy (&entry.var.VendorGuid, &guid,sizeof (guid)); + entry =kmalloc (sizeof (*entry),GFP_KERNEL ); +if (!entry) { +pr_err ("failed to allocate efivar entry" ); +return -1 ; + } - ret =efivar_entry_set (&entry, +efibc_str_to_str16 (name, entry->var.VariableName); +efibc_str_to_str16 (value, (efi_char16_t *)entry->var.Data); +memcpy (&entry->var.VendorGuid, &guid,sizeof (guid)); + + ret =efivar_entry_set (entry,EFI_VARIABLE_NON_VOLATILE |EFI_VARIABLE_BOOTSERVICE_ACCESS |EFI_VARIABLE_RUNTIME_ACCESS , - size, entry.var.Data,NULL ); + size, entry->var.Data,NULL );if (ret)pr_err ("failed to set %s EFI variable: 0x%x\n" , name, ret); + +kfree (entry); +return ret; }static int efibc_reboot_notifier_call (struct notifier_block *notifier,unsigned long event,void *data) {const char *reason ="shutdown" ; +int ret;if (event ==SYS_RESTART ) reason ="reboot" ; -efibc_set_variable ("LoaderEntryRebootReason" , reason); - -if (!data) -return NOTIFY_DONE ; + ret =efibc_set_variable ("LoaderEntryRebootReason" , reason); +if (ret || !data) +return NOTIFY_DONE ;
Quoted 3 lines
Quoted 1 line
efibc_set_variable("LoaderEntryOneShot", (char *)data);Hm, can reboot notifiers do non-atomic allocations?
The reboot notifier chain is a blocking notifier chain. AFAIK, it allows non-atomic allocation, right ?
Quoted 1 line
Why is
efivar_entryso huge?
efivar_entry structure include two "big" arrays of 1024 bytes each for the EFI variable name and data.
Thanks,
Jérémy
Signature · 1 line
One Emacs to rule them all
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 5 lines · Jeremy Compostella
Quoted 2 lines · Ingo Molnar
Hm, can reboot notifiers do non-atomic allocations?
The reboot notifier chain is a blocking notifier chain. AFAIK, it allows non-atomic allocation, right ?
I would assume so, yes.
Quoted 3 lines
Quoted 1 line
Why is
efivar_entryso huge?
efivar_entrystructure include two "big" arrays of 1024 bytes each for the EFI variable name and data.
Yeah. This is partially historical in that the EFI variable code has always had these arrays.
But it's also that if you're dealing with EFI variables you always want someplace to cache the data and name, so no one has ever proposed to split out the data/name from struct efivar_entry.
We've never put them on the stack before either ;)
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
In reply to Compostella, JeremyQuoted 35 lines · Jeremy Compostella
From
ef3a2941769e59b11d1ec36117209dc4c90c7cf9Mon Sep 17 00:00:00 2001
From: Jeremy Compostella <[email protected]>
Date: Fri, 29 Apr 2016 15:29:59 +0200
Subject: [PATCH] efibc: fix excessive stack footprint warningUse dynamic memory allocation instead of stack memory for the entry object.
This patch also fixes a potential buffer override.
Signed-off-by Jeremy Compostella <[email protected]>--- drivers/firmware/efi/efibc.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)drivers/firmware/efi/efibc.c +2
-1@@ -17,6 +17,7 @@#include <linux/efi.h> #include <linux/module.h> #include <linux/reboot.h> +#include <linux/slab.h> static void efibc_str_to_str16 (const char *str,efi_char16_t *str16) {@@ -28,42 +29,53 @@ static void efibc_str_to_str16(const char *str, efi_char16_t *str16) str16[i] ='\0' ; } -static void efibc_set_variable (const char *name,const char *value) +static int efibc_set_variable (const char *name,const char *value) {int ret;
drivers/firmware/efi/efibc.c static void efibc_str_to_str16(const char *str, efi_char16_t *str16) · line 42
Quoted 10 lines
drivers/firmware/efi/efibc.c +4
-2efi_guid_t guid =LINUX_EFI_LOADER_ENTRY_GUID ; -struct efivar_entry entry; +struct efivar_entry *entry;size_t size = (strlen (value) +1 ) *sizeof (efi_char16_t); -if (size >sizeof (entry.var.Data)) +if (size >sizeof (entry->var.Data)) {pr_err ("value is too large" ); +return -1 ; + }
This isn't right. The usual return value for this scenario would be either -ENOMEM or -EINVAL. Personally I'd lean towards -EINVAL.
drivers/firmware/efi/efibc.c static void efibc_str_to_str16(const char *str, efi_char16_t *str16) · line 48
Quoted 9 lines
drivers/firmware/efi/efibc.c +5
-3-efibc_str_to_str16 (name, entry.var.VariableName); -efibc_str_to_str16 (value, (efi_char16_t *)entry.var.Data); -memcpy (&entry.var.VendorGuid, &guid,sizeof (guid)); + entry =kmalloc (sizeof (*entry),GFP_KERNEL ); +if (!entry) { +pr_err ("failed to allocate efivar entry" ); +return -1 ; + }
This should be -ENOMEM.
Quoted 28 lines
drivers/firmware/efi/efibc.c +10
-2- ret =efivar_entry_set (&entry, +efibc_str_to_str16 (name, entry->var.VariableName); +efibc_str_to_str16 (value, (efi_char16_t *)entry->var.Data); +memcpy (&entry->var.VendorGuid, &guid,sizeof (guid)); + + ret =efivar_entry_set (entry,EFI_VARIABLE_NON_VOLATILE |EFI_VARIABLE_BOOTSERVICE_ACCESS |EFI_VARIABLE_RUNTIME_ACCESS , - size, entry.var.Data,NULL ); + size, entry->var.Data,NULL );if (ret)pr_err ("failed to set %s EFI variable: 0x%x\n" , name, ret); + +kfree (entry); +return ret; }static int efibc_reboot_notifier_call (struct notifier_block *notifier,unsigned long event,void *data) {const char *reason ="shutdown" ; +int ret;if (event ==SYS_RESTART ) reason ="reboot" ;
drivers/firmware/efi/efibc.c static void efibc_str_to_str16(const char *str, efi_char16_t *str16) · line 80
Quoted 10 lines
drivers/firmware/efi/efibc.c +3
-4-efibc_set_variable ("LoaderEntryRebootReason" , reason); - -if (!data) -return NOTIFY_DONE ; + ret =efibc_set_variable ("LoaderEntryRebootReason" , reason); +if (ret || !data) +return NOTIFY_DONE ;efibc_set_variable ("LoaderEntryOneShot" , (char *)data);
You need to check this return value too now.
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 41 lines · Matt Fleming
Quoted 40 lines · Jeremy Compostella
From
ef3a2941769e59b11d1ec36117209dc4c90c7cf9Mon Sep 17 00:00:00 2001
From: Jeremy Compostella <[email protected]>
Date: Fri, 29 Apr 2016 15:29:59 +0200
Subject: [PATCH] efibc: fix excessive stack footprint warningUse dynamic memory allocation instead of stack memory for the entry object.
This patch also fixes a potential buffer override.
Signed-off-by Jeremy Compostella <[email protected]>--- drivers/firmware/efi/efibc.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)drivers/firmware/efi/efibc.c +3
-2@@ -17,6 +17,7 @@#include <linux/efi.h> #include <linux/module.h> #include <linux/reboot.h> +#include <linux/slab.h> static void efibc_str_to_str16 (const char *str,efi_char16_t *str16) {@@ -28,42 +29,53 @@ static void efibc_str_to_str16(const char *str, efi_char16_t *str16) str16[i] ='\0' ; } -static void efibc_set_variable (const char *name,const char *value) +static int efibc_set_variable (const char *name,const char *value) {int ret;efi_guid_t guid =LINUX_EFI_LOADER_ENTRY_GUID ; -struct efivar_entry entry; +struct efivar_entry *entry;size_t size = (strlen (value) +1 ) *sizeof (efi_char16_t);
Quoted 8 lines
drivers/firmware/efi/efibc.c static void efibc_str_to_str16(const char *str, efi_char16_t *str16) · line 42
Quoted 5 lines
drivers/firmware/efi/efibc.c +3
-1-if (size >sizeof (entry.var.Data)) +if (size >sizeof (entry->var.Data)) {pr_err ("value is too large" ); +return -1 ; + }This isn't right. The usual return value for this scenario would be either
-ENOMEMor-EINVAL. Personally I'd lean towards-EINVAL.
Right. Done.
Quoted 11 lines
drivers/firmware/efi/efibc.c static void efibc_str_to_str16(const char *str, efi_char16_t *str16) · line 47
Quoted 9 lines
drivers/firmware/efi/efibc.c +5
-3-efibc_str_to_str16 (name, entry.var.VariableName); -efibc_str_to_str16 (value, (efi_char16_t *)entry.var.Data); -memcpy (&entry.var.VendorGuid, &guid,sizeof (guid)); + entry =kmalloc (sizeof (*entry),GFP_KERNEL ); +if (!entry) { +pr_err ("failed to allocate efivar entry" ); +return -1 ; + }This should be
-ENOMEM.
Done.
Quoted 37 lines
Quoted 37 lines
drivers/firmware/efi/efibc.c +13
-6- ret =efivar_entry_set (&entry, +efibc_str_to_str16 (name, entry->var.VariableName); +efibc_str_to_str16 (value, (efi_char16_t *)entry->var.Data); +memcpy (&entry->var.VendorGuid, &guid,sizeof (guid)); + + ret =efivar_entry_set (entry,EFI_VARIABLE_NON_VOLATILE |EFI_VARIABLE_BOOTSERVICE_ACCESS |EFI_VARIABLE_RUNTIME_ACCESS , - size, entry.var.Data,NULL ); + size, entry->var.Data,NULL );if (ret)pr_err ("failed to set %s EFI variable: 0x%x\n" , name, ret); + +kfree (entry); +return ret; }static int efibc_reboot_notifier_call (struct notifier_block *notifier,unsigned long event,void *data) {const char *reason ="shutdown" ; +int ret;if (event ==SYS_RESTART ) reason ="reboot" ; -efibc_set_variable ("LoaderEntryRebootReason" , reason); - -if (!data) -return NOTIFY_DONE ; + ret =efibc_set_variable ("LoaderEntryRebootReason" , reason); +if (ret || !data) +return NOTIFY_DONE ;
Quoted 3 lines
drivers/firmware/efi/efibc.c static void efibc_str_to_str16(const char *str, efi_char16_t *str16) · line 78
Quoted 1 line
drivers/firmware/efi/efibc.c +0
-0efibc_set_variable ("LoaderEntryOneShot" , (char *)data);You need to check this return value too now.
We are leaving this function returning NOTIFY_DONE whatever the return value of that last efibc_set_variable() call.
Please find the updated patch in attachment.
Also, thank you for answering Ard's questions. I promised I won't look at my emails on Labor day ;)
Jérémy
Quoted 1 line
From
e50a50dce0762edbc63f15d951b43b21fa7ca784Mon Sep 17 00:00:00 2001
From: Jeremy Compostella <[email protected]>
Date: Fri, 29 Apr 2016 15:29:59 +0200
Subject: [PATCH] efibc: fix excessive stack footprint warning
Use dynamic memory allocation instead of stack memory for the entry object.
This patch also fixes a potential buffer override.
--- drivers/firmware/efi/efibc.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)
drivers/firmware/efi/efibc.c +24 -12
@@ -17,6 +17,7 @@#include <linux/efi.h> #include <linux/module.h> #include <linux/reboot.h> +#include <linux/slab.h> static void efibc_str_to_str16 (const char *str,efi_char16_t *str16) {
@@ -28,42 +29,53 @@ static void efibc_str_to_str16(const char *str, efi_char16_t *str16) str16[i] ='\0' ; } -static void efibc_set_variable (const char *name,const char *value) +static int efibc_set_variable (const char *name,const char *value) {int ret;efi_guid_t guid =LINUX_EFI_LOADER_ENTRY_GUID ; -struct efivar_entry entry; +struct efivar_entry *entry;size_t size = (strlen (value) +1 ) *sizeof (efi_char16_t); -if (size >sizeof (entry.var.Data)) +if (size >sizeof (entry->var.Data)) {pr_err ("value is too large" ); +return -EINVAL ; + } -efibc_str_to_str16 (name, entry.var.VariableName); -efibc_str_to_str16 (value, (efi_char16_t *)entry.var.Data); -memcpy (&entry.var.VendorGuid, &guid,sizeof (guid)); + entry =kmalloc (sizeof (*entry),GFP_KERNEL ); +if (!entry) { +pr_err ("failed to allocate efivar entry" ); +return -ENOMEM ; + } - ret =efivar_entry_set (&entry, +efibc_str_to_str16 (name, entry->var.VariableName); +efibc_str_to_str16 (value, (efi_char16_t *)entry->var.Data); +memcpy (&entry->var.VendorGuid, &guid,sizeof (guid)); + + ret =efivar_entry_set (entry,EFI_VARIABLE_NON_VOLATILE |EFI_VARIABLE_BOOTSERVICE_ACCESS |EFI_VARIABLE_RUNTIME_ACCESS , - size, entry.var.Data,NULL ); + size, entry->var.Data,NULL );if (ret)pr_err ("failed to set %s EFI variable: 0x%x\n" , name, ret); + +kfree (entry); +return ret; }static int efibc_reboot_notifier_call (struct notifier_block *notifier,unsigned long event,void *data) {const char *reason ="shutdown" ; +int ret;if (event ==SYS_RESTART ) reason ="reboot" ; -efibc_set_variable ("LoaderEntryRebootReason" , reason); - -if (!data) -return NOTIFY_DONE ; + ret =efibc_set_variable ("LoaderEntryRebootReason" , reason); +if (ret || !data) +return NOTIFY_DONE ;efibc_set_variable ("LoaderEntryOneShot" , (char *)data);
Signature · 1 line
1.9.1
Signature · 1 line
One Emacs to rule them all
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 2 lines · Jeremy Compostella
Please find the updated patch in attachment.
Thanks Jeremy. Applied.
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
In reply to Ingo MolnarQuoted 10 lines · Ingo Molnar
Quoted 7 lines · tip-bot for Compostella, Jeremy
Commit-ID: 06f7d4a1618dbb086e738c93cd1ef416ab01027d Gitweb: http://git.kernel.org/tip/06f7d4a1618dbb086e738c93cd1ef416ab01027d Author: Compostella, Jeremy <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:57 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:02 +0200
Quoted 6 lines
Quoted 5 lines
efibc: Add EFI Bootloader Control module
This module installs a reboot callback, such that if
reboot()is invoked with a string argument NNN, "NNN" is copied to the "LoaderEntryOneShot" EFI variable, to be read by the bootloader.
Apologies for only mentioning this now, but I wonder why we need this in the kernel in the first place? The UEFI spec defines 'BootNext' as the way to set the boot entry for the next boot only, and this could also be set from userland. (i.e., the agent that knows how to invoke reboot with this particular string argument could simply set the EFI variable from userspace)
As far as reboot/shutdown is concerned, there is a ResetSystem() runtime service which reboots via the UEFI firmware, which seems like a better place to record the reboot/shutdown value.
So what bootloader is this exactly that requires this?
Thanks,
Ard.
Quoted 17 lines
Quoted 5 lines
drivers/firmware/efi/Kconfig | 15 +++++++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efibc.c | 101 ++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 4 ++ 4 files changed, 121 insertions(+)So this bloated things a bit on 32-bit x86 allyesconfig kernels, we now have this new warning:
drivers/firmware/efi/efibc.c:53:1: warning: the frame size of 2256 bytes is larger than 1024 bytes [-Wframe-larger-than=]2K of stack use for a function is quite excessive, can we improve the stack footprint of this code?
Thanks,
Ingo
Re: [tip:efi/core] efibc: Add EFI Bootloader Control module
Quoted 7 lines · Ard Biesheuvel
Apologies for only mentioning this now, but I wonder why we need this in the kernel in the first place? The UEFI spec defines 'BootNext' as the way to set the boot entry for the next boot only, and this could also be set from userland. (i.e., the agent that knows how to invoke reboot with this particular string argument could simply set the EFI variable from userspace)
Right, I raised this general point when Stefan sent the patch originally. Specifically, I asked why this can't be solved entirely in userspace and Stefan replied,
: It is possible, but that means modifying those userspace apps :) : There are reboot implementations that do "reboot <reason>", such as : Android's reboot command [1] and Upstart's reboot replacement [2], which : pass the reason as an argument to the reboot syscall.
: Probably your first question will be - "Why don't you modify those : apps?" Well, I don't see platform-agnostic way how those could be : modified to pass the reason to the bootloader, regardless of platform or : bootloader.
The difference with BootNext is that setting BootNext requires smarts in the OS to pick the next boot entry. This driver allows the boot loader to make that call.
Quoted 3 lines
As far as reboot/shutdown is concerned, there is a
ResetSystem()runtime service which reboots via the UEFI firmware, which seems like a better place to record the reboot/shutdown value.
But remember, on x86 we rarely use ResetSystem() because of the firmware bugs we've hit in the past. Users may want this driver even though ResetSystem() isn't used to reboot the machine.
Quoted 1 line
So what bootloader is this exactly that requires this?
I think gummiboot and the android boot loader can make use of it, but none require it.
PATCH 26/40 efi: Move efi_status_to_err() to drivers/firmware/efi/
In reply to Matt FlemingMove efi_status_to_err() to the architecture independent code as it's generally useful in all bits of EFI code where there is a need to convert an efi_status_t to a kernel error value.
--- drivers/firmware/efi/efi.c | 33 +++++++++++++++++++++++++++++++++ drivers/firmware/efi/vars.c | 33 --------------------------------- include/linux/efi.h | 2 ++ 3 files changed, 35 insertions(+), 33 deletions(-)
drivers/firmware/efi/efi.c +33 -0
@@ -636,3 +636,36 @@ u64 __weak efi_mem_attributes(unsigned long phys_addr) }return 0 ; } + +int efi_status_to_err (efi_status_t status) +{ +int err; + +switch (status) { +case EFI_SUCCESS : + err =0 ; +break ; +case EFI_INVALID_PARAMETER : + err = -EINVAL ; +break ; +case EFI_OUT_OF_RESOURCES : + err = -ENOSPC ; +break ; +case EFI_DEVICE_ERROR : + err = -EIO ; +break ; +case EFI_WRITE_PROTECTED : + err = -EROFS ; +break ; +case EFI_SECURITY_VIOLATION : + err = -EACCES ; +break ; +case EFI_NOT_FOUND : + err = -ENOENT ; +break ; +default : + err = -EINVAL ; + } + +return err; +}
drivers/firmware/efi/vars.c +0 -33
@@ -314,39 +314,6 @@ check_var_size_nonblocking(u32 attributes, unsigned long size)return fops->query_variable_store (attributes, size, true); } -static int efi_status_to_err (efi_status_t status) -{ -int err; - -switch (status) { -case EFI_SUCCESS : - err =0 ; -break ; -case EFI_INVALID_PARAMETER : - err = -EINVAL ; -break ; -case EFI_OUT_OF_RESOURCES : - err = -ENOSPC ; -break ; -case EFI_DEVICE_ERROR : - err = -EIO ; -break ; -case EFI_WRITE_PROTECTED : - err = -EROFS ; -break ; -case EFI_SECURITY_VIOLATION : - err = -EACCES ; -break ; -case EFI_NOT_FOUND : - err = -ENOENT ; -break ; -default : - err = -EINVAL ; - } - -return err; -} -static bool variable_is_present (efi_char16_t *variable_name,efi_guid_t *vendor,struct list_head *head) {
include/linux/efi.h +2 -0
@@ -1080,6 +1080,8 @@ static inline void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {}#endif +extern int efi_status_to_err (efi_status_t status); +/* * Variable Attributes */
Signature · 1 line
2.7.3
tip-bot for Matt Fleming
merge bot[tip:efi/core] efi: Move efi_status_to_err() to drivers/firmware/efi/
efi: Move efi_status_to_err() to drivers/firmware/efi/
Commit-ID: 806b0351c9ff9890c1ef0ba2c46237baef49ac79 Gitweb: http://git.kernel.org/tip/806b0351c9ff9890c1ef0ba2c46237baef49ac79 Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:58 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:03 +0200
efi: Move efi_status_to_err() to drivers/firmware/efi/
Move efi_status_to_err() to the architecture independent code as it's generally useful in all bits of EFI code where there is a need to convert an efi_status_t to a kernel error value.
--- drivers/firmware/efi/efi.c | 33 +++++++++++++++++++++++++++++++++ drivers/firmware/efi/vars.c | 33 --------------------------------- include/linux/efi.h | 2 ++ 3 files changed, 35 insertions(+), 33 deletions(-)
drivers/firmware/efi/efi.c +33 -0
@@ -636,3 +636,36 @@ u64 __weak efi_mem_attributes(unsigned long phys_addr) }return 0 ; } + +int efi_status_to_err (efi_status_t status) +{ +int err; + +switch (status) { +case EFI_SUCCESS : + err =0 ; +break ; +case EFI_INVALID_PARAMETER : + err = -EINVAL ; +break ; +case EFI_OUT_OF_RESOURCES : + err = -ENOSPC ; +break ; +case EFI_DEVICE_ERROR : + err = -EIO ; +break ; +case EFI_WRITE_PROTECTED : + err = -EROFS ; +break ; +case EFI_SECURITY_VIOLATION : + err = -EACCES ; +break ; +case EFI_NOT_FOUND : + err = -ENOENT ; +break ; +default : + err = -EINVAL ; + } + +return err; +}
drivers/firmware/efi/vars.c +0 -33
@@ -329,39 +329,6 @@ check_var_size_nonblocking(u32 attributes, unsigned long size)return fops->query_variable_store (attributes, size, true); } -static int efi_status_to_err (efi_status_t status) -{ -int err; - -switch (status) { -case EFI_SUCCESS : - err =0 ; -break ; -case EFI_INVALID_PARAMETER : - err = -EINVAL ; -break ; -case EFI_OUT_OF_RESOURCES : - err = -ENOSPC ; -break ; -case EFI_DEVICE_ERROR : - err = -EIO ; -break ; -case EFI_WRITE_PROTECTED : - err = -EROFS ; -break ; -case EFI_SECURITY_VIOLATION : - err = -EACCES ; -break ; -case EFI_NOT_FOUND : - err = -ENOENT ; -break ; -default : - err = -EINVAL ; - } - -return err; -} -static bool variable_is_present (efi_char16_t *variable_name,efi_guid_t *vendor,struct list_head *head) {
include/linux/efi.h +2 -0
@@ -1080,6 +1080,8 @@ static inline void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {}#endif +extern int efi_status_to_err (efi_status_t status); +/* * Variable Attributes */
PATCH 27/40 efi: Capsule update support
In reply to Matt FlemingThe EFI capsule mechanism allows data blobs to be passed to the EFI firmware. A common use case is performing firmware updates. This patch just introduces the main infrastructure for interacting with the firmware, and a driver that allows users to upload capsules will come in a later patch.
Once a capsule has been passed to the firmware, the next reboot must be performed using the ResetSystem() EFI runtime service, which may involve overriding the reboot type specified by reboot=. This ensures the reset value returned by QueryCapsuleCapabilities() is used to reset the system, which is required for the capsule to be processed. efi_capsule_pending() is provided for this purpose.
At the moment we only allow a single capsule blob to be sent to the firmware despite the fact that UpdateCapsule() takes a 'CapsuleCount' parameter. This simplifies the API and shouldn't result in any downside since it is still possible to send multiple capsules by repeatedly calling UpdateCapsule().
--- drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/capsule.c | 300 +++++++++++++++++++++++++++++++++++++++++ drivers/firmware/efi/reboot.c | 12 +- include/linux/efi.h | 14 ++ 4 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/efi/capsule.c
drivers/firmware/efi/Makefile +1 -0
@@ -10,6 +10,7 @@ KASAN_SANITIZE_runtime-wrappers.o := n obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o +obj-$(CONFIG_EFI) += capsule.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_ESRT) += esrt.o obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
drivers/firmware/efi/capsule.c new file +300 -0
300 lines not on this page · raw message
drivers/firmware/efi/reboot.c +11 -1
@@ -9,7 +9,8 @@ int efi_reboot_quirk_mode = -1;void efi_reboot (enum reboot_mode reboot_mode,const char *__unused) { -int efi_mode; +const char *str[] = {"cold" ,"warm" ,"shutdown" ,"platform" }; +int efi_mode, cap_reset_mode;if (!efi_enabled (EFI_RUNTIME_SERVICES ))return ;
@@ -30,6 +31,15 @@ void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)if (efi_reboot_quirk_mode !=-1 ) efi_mode = efi_reboot_quirk_mode; +if (efi_capsule_pending (&cap_reset_mode)) { +if (efi_mode != cap_reset_mode) +printk (KERN_CRIT "efi: %s reset requested but pending " +"capsule update requires %s reset... Performing " +"%s reset.\n" , str[efi_mode], str[cap_reset_mode], + str[cap_reset_mode]); + efi_mode = cap_reset_mode; + } + efi.reset_system (efi_mode,EFI_SUCCESS ,0 ,NULL ); }
include/linux/efi.h +14 -0
@@ -125,6 +125,13 @@ typedef struct { } efi_capsule_header_t;/* +* EFI capsule flags +*/ +#define EFI_CAPSULE_PERSIST_ACROSS_RESET 0x00010000 +#define EFI_CAPSULE_POPULATE_SYSTEM_TABLE 0x00020000 +#define EFI_CAPSULE_INITIATE_RESET 0x00040000 + +/* * Allocation types for calls to boottime->allocate_pages. */ #define EFI_ALLOCATE_ANY_PAGES 0
@@ -1370,6 +1377,13 @@ int efivars_sysfs_init(void);#define EFIVARS_DATA_SIZE_MAX 1024#endif /* CONFIG_EFI_VARS */ +extern bool efi_capsule_pending (int *reset_type); + +extern int efi_capsule_supported (efi_guid_t guid,u32 flags, +size_t size,int *reset); + +extern int efi_capsule_update (efi_capsule_header_t *capsule, +struct page **pages);#ifdef CONFIG_EFI_RUNTIME_MAP int efi_runtime_map_init (struct kobject *);
Signature · 1 line
2.7.3
tip-bot for Matt Fleming
merge bot[tip:efi/core] efi: Add 'capsule' update support
efi: Add 'capsule' update support
Commit-ID: f0133f3c5b8bb34ec4dec50c27e7a655aeee8935 Gitweb: http://git.kernel.org/tip/f0133f3c5b8bb34ec4dec50c27e7a655aeee8935 Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:06:59 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:03 +0200
efi: Add 'capsule' update support
The EFI capsule mechanism allows data blobs to be passed to the EFI firmware. A common use case is performing firmware updates. This patch just introduces the main infrastructure for interacting with the firmware, and a driver that allows users to upload capsules will come in a later patch.
Once a capsule has been passed to the firmware, the next reboot must be performed using the ResetSystem() EFI runtime service, which may involve overriding the reboot type specified by reboot=. This ensures the reset value returned by QueryCapsuleCapabilities() is used to reset the system, which is required for the capsule to be processed. efi_capsule_pending() is provided for this purpose.
At the moment we only allow a single capsule blob to be sent to the firmware despite the fact that UpdateCapsule() takes a 'CapsuleCount' parameter. This simplifies the API and shouldn't result in any downside since it is still possible to send multiple capsules by repeatedly calling UpdateCapsule().
--- drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/capsule.c | 300 +++++++++++++++++++++++++++++++++++++++++ drivers/firmware/efi/reboot.c | 12 +- include/linux/efi.h | 14 ++ 4 files changed, 326 insertions(+), 1 deletion(-)
drivers/firmware/efi/Makefile +1 -0
@@ -10,6 +10,7 @@ KASAN_SANITIZE_runtime-wrappers.o := n obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o +obj-$(CONFIG_EFI) += capsule.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_ESRT) += esrt.o obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
drivers/firmware/efi/capsule.c new file +300 -0
300 lines not on this page · raw message
drivers/firmware/efi/reboot.c +11 -1
@@ -9,7 +9,8 @@ int efi_reboot_quirk_mode = -1;void efi_reboot (enum reboot_mode reboot_mode,const char *__unused) { -int efi_mode; +const char *str[] = {"cold" ,"warm" ,"shutdown" ,"platform" }; +int efi_mode, cap_reset_mode;if (!efi_enabled (EFI_RUNTIME_SERVICES ))return ;
@@ -30,6 +31,15 @@ void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)if (efi_reboot_quirk_mode !=-1 ) efi_mode = efi_reboot_quirk_mode; +if (efi_capsule_pending (&cap_reset_mode)) { +if (efi_mode != cap_reset_mode) +printk (KERN_CRIT "efi: %s reset requested but pending " +"capsule update requires %s reset... Performing " +"%s reset.\n" , str[efi_mode], str[cap_reset_mode], + str[cap_reset_mode]); + efi_mode = cap_reset_mode; + } + efi.reset_system (efi_mode,EFI_SUCCESS ,0 ,NULL ); }
include/linux/efi.h +14 -0
@@ -125,6 +125,13 @@ typedef struct { } efi_capsule_header_t;/* +* EFI capsule flags +*/ +#define EFI_CAPSULE_PERSIST_ACROSS_RESET 0x00010000 +#define EFI_CAPSULE_POPULATE_SYSTEM_TABLE 0x00020000 +#define EFI_CAPSULE_INITIATE_RESET 0x00040000 + +/* * Allocation types for calls to boottime->allocate_pages. */ #define EFI_ALLOCATE_ANY_PAGES 0
@@ -1370,6 +1377,13 @@ int efivars_sysfs_init(void);#define EFIVARS_DATA_SIZE_MAX 1024#endif /* CONFIG_EFI_VARS */ +extern bool efi_capsule_pending (int *reset_type); + +extern int efi_capsule_supported (efi_guid_t guid,u32 flags, +size_t size,int *reset); + +extern int efi_capsule_update (efi_capsule_header_t *capsule, +struct page **pages);#ifdef CONFIG_EFI_RUNTIME_MAP int efi_runtime_map_init (struct kobject *);
PATCH 28/40 x86/efi: Force EFI reboot to process pending capsules
In reply to Matt FlemingIf an EFI capsule has been sent to the firmware we must match the type of EFI reset against that required by the capsule to ensure it is processed correctly.
Force an EFI reboot if a capsule is pending for the next reset.
--- arch/x86/kernel/reboot.c | 9 +++++++++ include/linux/efi.h | 6 ++++++ 2 files changed, 15 insertions(+)
arch/x86/kernel/reboot.c +9 -0
@@ -535,6 +535,15 @@ static void native_machine_emergency_restart(void) mode = reboot_mode ==REBOOT_WARM ?0x1234 :0 ; *((unsigned short *)__va (0x472 )) = mode; +/* +* If an EFI capsule has been registered with the firmware then +* override the reboot= parameter. +*/ +if (efi_capsule_pending (NULL )) { +pr_info ("EFI capsule is pending, forcing EFI reboot.\n" ); + reboot_type =BOOT_EFI ; + } +for (;;) {/* Could also try the reset bit in the Hammer NB */ switch (reboot_type) {
include/linux/efi.h +6 -0
@@ -1085,6 +1085,12 @@ static inline bool efi_enabled(int feature) }static inline void efi_reboot (enum reboot_mode reboot_mode,const char *__unused) {} + +static inline bool +efi_capsule_pending (int *reset_type) +{ +return false; +}#endif extern int efi_status_to_err (efi_status_t status);
Signature · 1 line
2.7.3
tip-bot for Matt Fleming
merge bot[tip:efi/core] x86/efi: Force EFI reboot to process pending capsules
x86/efi: Force EFI reboot to process pending capsules
Commit-ID: 87615a34d561ef59bd0cffc73256a21220dfdffd Gitweb: http://git.kernel.org/tip/87615a34d561ef59bd0cffc73256a21220dfdffd Author: Matt Fleming <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:00 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:04 +0200
x86/efi: Force EFI reboot to process pending capsules
If an EFI capsule has been sent to the firmware we must match the type of EFI reset against that required by the capsule to ensure it is processed correctly.
Force an EFI reboot if a capsule is pending for the next reset.
--- arch/x86/kernel/reboot.c | 9 +++++++++ include/linux/efi.h | 6 ++++++ 2 files changed, 15 insertions(+)
arch/x86/kernel/reboot.c +9 -0
@@ -535,6 +535,15 @@ static void native_machine_emergency_restart(void) mode = reboot_mode ==REBOOT_WARM ?0x1234 :0 ; *((unsigned short *)__va (0x472 )) = mode; +/* +* If an EFI capsule has been registered with the firmware then +* override the reboot= parameter. +*/ +if (efi_capsule_pending (NULL )) { +pr_info ("EFI capsule is pending, forcing EFI reboot.\n" ); + reboot_type =BOOT_EFI ; + } +for (;;) {/* Could also try the reset bit in the Hammer NB */ switch (reboot_type) {
include/linux/efi.h +6 -0
@@ -1085,6 +1085,12 @@ static inline bool efi_enabled(int feature) }static inline void efi_reboot (enum reboot_mode reboot_mode,const char *__unused) {} + +static inline bool +efi_capsule_pending (int *reset_type) +{ +return false; +}#endif extern int efi_status_to_err (efi_status_t status);
PATCH 29/40 efi: A misc char interface to update EFI firmware
In reply to Matt FlemingFrom: "Kweh, Hock Leong" <[email protected]>
This patch introduces a kernel module to expose a capsule loader interface (misc char device file note) for users to upload capsule binaries.
Example:
cat firmware.bin > /dev/efi_capsule_loader
Any upload error will be returned while doing "cat" through file operation write() function call.
--- drivers/firmware/efi/Kconfig | 10 + drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/capsule-loader.c | 343 ++++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 drivers/firmware/efi/capsule-loader.c
drivers/firmware/efi/Kconfig +10 -0
@@ -102,6 +102,16 @@ config EFI_BOOTLOADER_CONTROL bootloader reads this reboot reason and takes particular action according to its policy. +config EFI_CAPSULE_LOADER + tristate "EFI capsule loader" + depends on EFI + help + This option exposes a loader interface "/dev/efi_capsule_loader" for + users to load EFI capsules. This driver requires working runtime + capsule support in the firmware, which many OEMs do not provide. + + Most users should say N. + endmenu config UEFI_CPER
drivers/firmware/efi/Makefile +1 -0
@@ -24,3 +24,4 @@ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y) obj-$(CONFIG_ARM64) += $(arm-obj-y) +obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o
drivers/firmware/efi/capsule-loader.c new file +343 -0
343 lines not on this page · raw message
Signature · 1 line
2.7.3
tip-bot for Kweh, Hock Leong
merge bot[tip:efi/core] efi: Add misc char driver interface to update EFI firmware
efi: Add misc char driver interface to update EFI firmware
Commit-ID: 65117f1aa1b2d145fd5ca376bde642794d0aae1b Gitweb: http://git.kernel.org/tip/65117f1aa1b2d145fd5ca376bde642794d0aae1b Author: Kweh, Hock Leong <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:01 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:05 +0200
efi: Add misc char driver interface to update EFI firmware
This patch introduces a kernel module to expose a capsule loader interface (misc char device file note) for users to upload capsule binaries.
Example:
cat firmware.bin > /dev/efi_capsule_loader
Any upload error will be returned while doing "cat" through file operation write() function call.
--- drivers/firmware/efi/Kconfig | 10 + drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/capsule-loader.c | 343 ++++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+)
drivers/firmware/efi/Kconfig +10 -0
@@ -102,6 +102,16 @@ config EFI_BOOTLOADER_CONTROL bootloader reads this reboot reason and takes particular action according to its policy. +config EFI_CAPSULE_LOADER + tristate "EFI capsule loader" + depends on EFI + help + This option exposes a loader interface "/dev/efi_capsule_loader" for + users to load EFI capsules. This driver requires working runtime + capsule support in the firmware, which many OEMs do not provide. + + Most users should say N. + endmenu config UEFI_CPER
drivers/firmware/efi/Makefile +1 -0
@@ -24,3 +24,4 @@ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y) obj-$(CONFIG_ARM64) += $(arm-obj-y) +obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o
drivers/firmware/efi/capsule-loader.c new file +343 -0
343 lines not on this page · raw message
PATCH 30/40 efi/arm-init: Reserve rather than unmap the memory map for ARM as well
In reply to Matt FlemingFrom: Ard Biesheuvel <[email protected]>
Now that ARM has a fully functional memremap() implementation, there is no longer a need to remove the UEFI memory map from the linear mapping in order to be able to create a permanent mapping for it using generic code.
So remove the 'IS_ENABLED(CONFIG_ARM)' conditional we added in commit 7cc8cbcf82d1 ("efi/arm64: Don't apply MEMBLOCK_NOMAP to UEFI memory map mapping"), and revert to using memblock_reserve() for both ARM and arm64
--- drivers/firmware/efi/arm-init.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/firmware/efi/arm-init.c +3 -14
@@ -244,20 +244,9 @@ void __init efi_init(void)efi_memattr_init ();early_memunmap (efi.memmap.map, params.mmap_size); -if (IS_ENABLED (CONFIG_ARM )) { -/* -* ARM currently does not allow ioremap_cache() to be called on -* memory regions that are covered by struct page. So remove the -* UEFI memory map from the linear mapping. -*/ -memblock_mark_nomap (params.mmap &PAGE_MASK , -PAGE_ALIGN (params.mmap_size + - (params.mmap & ~PAGE_MASK ))); - }else { -memblock_reserve (params.mmap &PAGE_MASK , -PAGE_ALIGN (params.mmap_size + - (params.mmap & ~PAGE_MASK ))); - } +memblock_reserve (params.mmap &PAGE_MASK , +PAGE_ALIGN (params.mmap_size + + (params.mmap & ~PAGE_MASK )));init_screen_info (); }
Signature · 1 line
2.7.3
tip-bot for Ard Biesheuvel
merge bot[tip:efi/core] efi/arm-init: Reserve rather than unmap the memory map for ARM as well
efi/arm-init: Reserve rather than unmap the memory map for ARM as well
Commit-ID: 249f7632162980b286f30166436471f8ba81fc1e Gitweb: http://git.kernel.org/tip/249f7632162980b286f30166436471f8ba81fc1e Author: Ard Biesheuvel <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:02 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:05 +0200
efi/arm-init: Reserve rather than unmap the memory map for ARM as well
Now that ARM has a fully functional memremap() implementation, there is no longer a need to remove the UEFI memory map from the linear mapping in order to be able to create a permanent mapping for it using generic code.
So remove the 'IS_ENABLED(CONFIG_ARM)' conditional we added in:
7cc8cbcf82d1 ("efi/arm64: Don't apply MEMBLOCK_NOMAP to UEFI memory map mapping")
... and revert to using memblock_reserve() for both ARM and arm64.
--- drivers/firmware/efi/arm-init.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/firmware/efi/arm-init.c +3 -14
@@ -244,20 +244,9 @@ void __init efi_init(void)efi_memattr_init ();early_memunmap (efi.memmap.map, params.mmap_size); -if (IS_ENABLED (CONFIG_ARM )) { -/* -* ARM currently does not allow ioremap_cache() to be called on -* memory regions that are covered by struct page. So remove the -* UEFI memory map from the linear mapping. -*/ -memblock_mark_nomap (params.mmap &PAGE_MASK , -PAGE_ALIGN (params.mmap_size + - (params.mmap & ~PAGE_MASK ))); - }else { -memblock_reserve (params.mmap &PAGE_MASK , -PAGE_ALIGN (params.mmap_size + - (params.mmap & ~PAGE_MASK ))); - } +memblock_reserve (params.mmap &PAGE_MASK , +PAGE_ALIGN (params.mmap_size + + (params.mmap & ~PAGE_MASK )));init_screen_info (); }
PATCH 31/40 efi/runtime-wrappers: Add {__,}efi_call_virt templates
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Currently each architecture must implement two macros, efi_call_virt and __efi_call_virt, which only differ by the presence or absence of a return type. Otherwise, the logic surrounding the call is identical.
As each architecture must define the entire body of each, we can't place any generic manipulation (e.g. irq flag validation) in the middle.
This patch adds template implementations of these macros. With these, arch code can implement three template macros, avoiding reptition for the void/non-void return cases:
* arch_efi_call_virt_setup
Sets up the environment for the call (e.g. switching page tables, allowing kernel-mode use of floating point, if required).
* arch_efi_call_virt
Performs the call. The last expression in the macro must be the call itself, allowing the logic to be shared by the void and non-void cases.
* arch_efi_call_virt_teardown
Restores the usual kernel environment once the call has returned.
While the savings from repition are minimal, we additionally gain the ability to add common code around the call with the call environment set up. This can be used to detect common firmware issues (e.g. bad irq mask management).
--- drivers/firmware/efi/runtime-wrappers.c | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
drivers/firmware/efi/runtime-wrappers.c +40 -0
@@ -21,6 +21,46 @@#include <asm/efi.h> /* +* Arch code can implement the following three template macros, avoiding +* reptition for the void/non-void return cases of {__,}efi_call_virt: +* +* * arch_efi_call_virt_setup +* +* Sets up the environment for the call (e.g. switching page tables, +* allowing kernel-mode use of floating point, if required). +* +* * arch_efi_call_virt +* +* Performs the call. The last expression in the macro must be the call +* itself, allowing the logic to be shared by the void and non-void +* cases. +* +* * arch_efi_call_virt_teardown +* +* Restores the usual kernel environment once the call has returned. +*/ + +#ifndef efi_call_virt +#define efi_call_virt(f, args...) \ +({ \ + efi_status_t __s; \ + arch_efi_call_virt_setup(); \ + __s = arch_efi_call_virt(f, args); \ + arch_efi_call_virt_teardown(); \ + __s; \ +}) +#endif + +#ifndef __efi_call_virt +#define __efi_call_virt(f, args...) \ +({ \ + arch_efi_call_virt_setup(); \ + arch_efi_call_virt(f, args); \ + arch_efi_call_virt_teardown(); \ +}) +#endif + +/* * According to section 7.1 of the UEFI spec, Runtime Services are not fully * reentrant, and there are particular combinations of calls that need to be * serialized. (source: UEFI Specification v2.4A)
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] efi/runtime-wrappers: Add {__,}efi_call_virt() templates
efi/runtime-wrappers: Add {__,}efi_call_virt() templates
Commit-ID: f51c35f291062df14a3e9cc5779e417fe662e50e Gitweb: http://git.kernel.org/tip/f51c35f291062df14a3e9cc5779e417fe662e50e Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:03 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:06 +0200
efi/runtime-wrappers: Add {__,}efi_call_virt() templates
Currently each architecture must implement two macros, efi_call_virt() and __efi_call_virt(), which only differ by the presence or absence of a return type. Otherwise, the logic surrounding the call is identical.
As each architecture must define the entire body of each, we can't place any generic manipulation (e.g. irq flag validation) in the middle.
This patch adds template implementations of these macros. With these, arch code can implement three template macros, avoiding reptition for the void/non-void return cases:
* arch_efi_call_virt_setup()
Sets up the environment for the call (e.g. switching page tables, allowing kernel-mode use of floating point, if required).
* arch_efi_call_virt()
Performs the call. The last expression in the macro must be the call itself, allowing the logic to be shared by the void and non-void cases.
* arch_efi_call_virt_teardown()
Restores the usual kernel environment once the call has returned.
While the savings from repition are minimal, we additionally gain the ability to add common code around the call with the call environment set up. This can be used to detect common firmware issues (e.g. bad irq mask management).
--- drivers/firmware/efi/runtime-wrappers.c | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
drivers/firmware/efi/runtime-wrappers.c +40 -0
@@ -21,6 +21,46 @@#include <asm/efi.h> /* +* Arch code can implement the following three template macros, avoiding +* reptition for the void/non-void return cases of {__,}efi_call_virt: +* +* * arch_efi_call_virt_setup +* +* Sets up the environment for the call (e.g. switching page tables, +* allowing kernel-mode use of floating point, if required). +* +* * arch_efi_call_virt +* +* Performs the call. The last expression in the macro must be the call +* itself, allowing the logic to be shared by the void and non-void +* cases. +* +* * arch_efi_call_virt_teardown +* +* Restores the usual kernel environment once the call has returned. +*/ + +#ifndef efi_call_virt +#define efi_call_virt(f, args...) \ +({ \ + efi_status_t __s; \ + arch_efi_call_virt_setup(); \ + __s = arch_efi_call_virt(f, args); \ + arch_efi_call_virt_teardown(); \ + __s; \ +}) +#endif + +#ifndef __efi_call_virt +#define __efi_call_virt(f, args...) \ +({ \ + arch_efi_call_virt_setup(); \ + arch_efi_call_virt(f, args); \ + arch_efi_call_virt_teardown(); \ +}) +#endif + +/* * According to section 7.1 of the UEFI spec, Runtime Services are not fully * reentrant, and there are particular combinations of calls that need to be * serialized. (source: UEFI Specification v2.4A)
PATCH 32/40 arm64/efi: Move to generic {__,}efi_call_virt
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Now there's a common template for {__,}efi_call_virt, remove the duplicate logic from the arm64 efi code.
--- arch/arm64/include/asm/efi.h | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-)
arch/arm64/include/asm/efi.h +7 -14
@@ -16,28 +16,21 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);#define efi_set_mapping_permissions efi_create_mapping -#define efi_call_virt (f, ...) \ +#define arch_efi_call_virt_setup () \ ({ \ - efi_##f##_t *__f; \ - efi_status_t __s; \ - \ kernel_neon_begin(); \ efi_virtmap_load(); \ - __f = efi.systab->runtime->f; \ - __s = __f(__VA_ARGS__); \ - efi_virtmap_unload(); \ - kernel_neon_end(); \ - __s; \ }) -#define __efi_call_virt (f, ...) \ +#define arch_efi_call_virt(f, args...) \ ({ \ efi_##f##_t *__f; \ - \ - kernel_neon_begin(); \ - efi_virtmap_load(); \ __f = efi.systab->runtime->f; \ - __f(__VA_ARGS__); \ + __f(args); \ +}) + +#define arch_efi_call_virt_teardown () \ +({ \ efi_virtmap_unload(); \ kernel_neon_end(); \ })
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] arm64/efi: Move to generic {__,}efi_call_virt()
arm64/efi: Move to generic {__,}efi_call_virt()
Commit-ID: 489f80f72f7528d2a1b10346657a1a1a42533cea Gitweb: http://git.kernel.org/tip/489f80f72f7528d2a1b10346657a1a1a42533cea Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:04 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:07 +0200
arm64/efi: Move to generic {__,}efi_call_virt()
Now there's a common template for {__,}efi_call_virt(), remove the duplicate logic from the arm64 EFI code.
--- arch/arm64/include/asm/efi.h | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-)
arch/arm64/include/asm/efi.h +7 -14
@@ -16,28 +16,21 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);#define efi_set_mapping_permissions efi_create_mapping -#define efi_call_virt (f, ...) \ +#define arch_efi_call_virt_setup () \ ({ \ - efi_##f##_t *__f; \ - efi_status_t __s; \ - \ kernel_neon_begin(); \ efi_virtmap_load(); \ - __f = efi.systab->runtime->f; \ - __s = __f(__VA_ARGS__); \ - efi_virtmap_unload(); \ - kernel_neon_end(); \ - __s; \ }) -#define __efi_call_virt (f, ...) \ +#define arch_efi_call_virt(f, args...) \ ({ \ efi_##f##_t *__f; \ - \ - kernel_neon_begin(); \ - efi_virtmap_load(); \ __f = efi.systab->runtime->f; \ - __f(__VA_ARGS__); \ + __f(args); \ +}) + +#define arch_efi_call_virt_teardown () \ +({ \ efi_virtmap_unload(); \ kernel_neon_end(); \ })
PATCH 33/40 arm/efi: Move to generic {__,}efi_call_virt
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Now there's a common template for {__,}efi_call_virt, remove the duplicate logic from the arm efi code.
--- arch/arm/include/asm/efi.h | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-)
arch/arm/include/asm/efi.h +4 -16
@@ -24,26 +24,14 @@ void efi_init(void);int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md);int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md); -#define efi_call_virt (f, ...) \ -({ \ - efi_##f##_t *__f; \ - efi_status_t __s; \ - \ - efi_virtmap_load(); \ - __f = efi.systab->runtime->f; \ - __s = __f(__VA_ARGS__); \ - efi_virtmap_unload(); \ - __s; \ -}) +#define arch_efi_call_virt_setup () efi_virtmap_load() +#define arch_efi_call_virt_teardown () efi_virtmap_unload() -#define __efi_call_virt (f, ...) \ +#define arch_efi_call_virt(f, args...) \ ({ \ efi_##f##_t *__f; \ - \ - efi_virtmap_load(); \ __f = efi.systab->runtime->f; \ - __f(__VA_ARGS__); \ - efi_virtmap_unload(); \ + __f(args); \ })static inline void efi_set_pgd (struct mm_struct *mm)
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] arm/efi: Move to generic {__,}efi_call_virt()
arm/efi: Move to generic {__,}efi_call_virt()
Commit-ID: 819fc126edcb458f26e9a7fda54bfdd36dfbce06 Gitweb: http://git.kernel.org/tip/819fc126edcb458f26e9a7fda54bfdd36dfbce06 Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:05 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:08 +0200
arm/efi: Move to generic {__,}efi_call_virt()
Now there's a common template for {__,}efi_call_virt(), remove the duplicate logic from the ARM EFI code.
--- arch/arm/include/asm/efi.h | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-)
arch/arm/include/asm/efi.h +4 -16
@@ -24,26 +24,14 @@ void efi_init(void);int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md);int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md); -#define efi_call_virt (f, ...) \ -({ \ - efi_##f##_t *__f; \ - efi_status_t __s; \ - \ - efi_virtmap_load(); \ - __f = efi.systab->runtime->f; \ - __s = __f(__VA_ARGS__); \ - efi_virtmap_unload(); \ - __s; \ -}) +#define arch_efi_call_virt_setup () efi_virtmap_load() +#define arch_efi_call_virt_teardown () efi_virtmap_unload() -#define __efi_call_virt (f, ...) \ +#define arch_efi_call_virt(f, args...) \ ({ \ efi_##f##_t *__f; \ - \ - efi_virtmap_load(); \ __f = efi.systab->runtime->f; \ - __f(__VA_ARGS__); \ - efi_virtmap_unload(); \ + __f(args); \ })static inline void efi_set_pgd (struct mm_struct *mm)
PATCH 34/40 x86/efi: Move to generic {__,}efi_call_virt
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Now there's a common template for {__,}efi_call_virt, remove the duplicate logic from the x86 efi code.
--- arch/x86/include/asm/efi.h | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-)
arch/x86/include/asm/efi.h +12 -29
@@ -33,28 +33,16 @@extern unsigned long asmlinkage efi_call_phys (void *, ...); +#define arch_efi_call_virt_setup () kernel_fpu_begin() +#define arch_efi_call_virt_teardown () kernel_fpu_end() +/* * Wrap all the virtual calls in a way that forces the parameters on the stack. */ - -/* Use this macro if your virtual returns a non-void value */ -#define efi_call_virt(f, args...) \ -({ \ - efi_status_t __s; \ - kernel_fpu_begin(); \ - __s = ((efi_##f##_t __attribute__((regparm(0)))*) \ - efi.systab->runtime->f)(args); \ - kernel_fpu_end(); \ - __s; \ -}) - -/* Use this macro if your virtual call does not return any value */ -#define __efi_call_virt(f, args...) \ +#define arch_efi_call_virt(f, args...) \ ({ \ - kernel_fpu_begin(); \ ((efi_##f##_t __attribute__((regparm(0)))*) \ efi.systab->runtime->f)(args); \ - kernel_fpu_end(); \ })#define efi_ioremap (addr, size, type, attr) ioremap_cache(addr, size)
@@ -78,10 +66,8 @@ struct efi_scratch {u64 phys_stack; } __packed; -#define efi_call_virt (f, ...) \ +#define arch_efi_call_virt_setup () \ ({ \ - efi_status_t __s; \ - \ efi_sync_low_kernel_mappings(); \ preempt_disable(); \ __kernel_fpu_begin(); \
@@ -91,9 +77,13 @@ struct efi_scratch {write_cr3 ((unsigned long )efi_scratch.efi_pgt); \__flush_tlb_all (); \ } \ - \ - __s =efi_call ((void *)efi.systab->runtime->f, __VA_ARGS__); \ - \ +}) + +#define arch_efi_call_virt(f, args...) \ + efi_call((void *)efi.systab->runtime->f, args) \ + +#define arch_efi_call_virt_teardown () \ +({ \ if (efi_scratch.use_pgd) { \ write_cr3(efi_scratch.prev_cr3); \ __flush_tlb_all(); \
@@ -101,15 +91,8 @@ struct efi_scratch { \__kernel_fpu_end (); \preempt_enable (); \ - __s; \ }) -/* -* All X86_64 virt calls return non-void values. Thus, use non-void call for -* virt calls that would be void on X86_32. -*/ -#define __efi_call_virt(f, args...) efi_call_virt(f, args) -extern void __iomem *__init efi_ioremap (unsigned long addr,unsigned long size,u32 type,u64 attribute);
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] x86/efi: Move to generic {__,}efi_call_virt()
x86/efi: Move to generic {__,}efi_call_virt()
Commit-ID: bc25f9dba149a1392b016a6d35300c8d79177298 Gitweb: http://git.kernel.org/tip/bc25f9dba149a1392b016a6d35300c8d79177298 Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:06 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:09 +0200
x86/efi: Move to generic {__,}efi_call_virt()
Now there's a common template for {__,}efi_call_virt(), remove the duplicate logic from the x86 EFI code.
--- arch/x86/include/asm/efi.h | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-)
arch/x86/include/asm/efi.h +12 -29
@@ -33,28 +33,16 @@extern unsigned long asmlinkage efi_call_phys (void *, ...); +#define arch_efi_call_virt_setup () kernel_fpu_begin() +#define arch_efi_call_virt_teardown () kernel_fpu_end() +/* * Wrap all the virtual calls in a way that forces the parameters on the stack. */ - -/* Use this macro if your virtual returns a non-void value */ -#define efi_call_virt(f, args...) \ -({ \ - efi_status_t __s; \ - kernel_fpu_begin(); \ - __s = ((efi_##f##_t __attribute__((regparm(0)))*) \ - efi.systab->runtime->f)(args); \ - kernel_fpu_end(); \ - __s; \ -}) - -/* Use this macro if your virtual call does not return any value */ -#define __efi_call_virt(f, args...) \ +#define arch_efi_call_virt(f, args...) \ ({ \ - kernel_fpu_begin(); \ ((efi_##f##_t __attribute__((regparm(0)))*) \ efi.systab->runtime->f)(args); \ - kernel_fpu_end(); \ })#define efi_ioremap (addr, size, type, attr) ioremap_cache(addr, size)
@@ -78,10 +66,8 @@ struct efi_scratch {u64 phys_stack; } __packed; -#define efi_call_virt (f, ...) \ +#define arch_efi_call_virt_setup () \ ({ \ - efi_status_t __s; \ - \ efi_sync_low_kernel_mappings(); \ preempt_disable(); \ __kernel_fpu_begin(); \
@@ -91,9 +77,13 @@ struct efi_scratch {write_cr3 ((unsigned long )efi_scratch.efi_pgt); \__flush_tlb_all (); \ } \ - \ - __s =efi_call ((void *)efi.systab->runtime->f, __VA_ARGS__); \ - \ +}) + +#define arch_efi_call_virt(f, args...) \ + efi_call((void *)efi.systab->runtime->f, args) \ + +#define arch_efi_call_virt_teardown () \ +({ \ if (efi_scratch.use_pgd) { \ write_cr3(efi_scratch.prev_cr3); \ __flush_tlb_all(); \
@@ -101,15 +91,8 @@ struct efi_scratch { \__kernel_fpu_end (); \preempt_enable (); \ - __s; \ }) -/* -* All X86_64 virt calls return non-void values. Thus, use non-void call for -* virt calls that would be void on X86_32. -*/ -#define __efi_call_virt(f, args...) efi_call_virt(f, args) -extern void __iomem *__init efi_ioremap (unsigned long addr,unsigned long size,u32 type,u64 attribute);
PATCH 35/40 efi/runtime-wrappers: Remove redundant ifdefs
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Now that all users of the EFI runtime wrappers (arm,arm64,x86) have been migrated to the new setup/teardown macros, we don't need to support overridden {__,}efi_call_virt implementations.
This patch removes the unnecessary ifdefs.
--- drivers/firmware/efi/runtime-wrappers.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/firmware/efi/runtime-wrappers.c +0 -4
@@ -40,7 +40,6 @@* Restores the usual kernel environment once the call has returned. */ -#ifndef efi_call_virt #define efi_call_virt(f, args...) \ ({ \ efi_status_t __s; \
@@ -49,16 +48,13 @@arch_efi_call_virt_teardown (); \ __s; \ }) -#endif -#ifndef __efi_call_virt #define __efi_call_virt(f, args...) \ ({ \ arch_efi_call_virt_setup(); \ arch_efi_call_virt(f, args); \ arch_efi_call_virt_teardown(); \ }) -#endif /* * According to section 7.1 of the UEFI spec, Runtime Services are not fully
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] efi/runtime-wrappers: Remove redundant #ifdefs
efi/runtime-wrappers: Remove redundant #ifdefs
Commit-ID: d9c6e1d0faec6d750b5cc08d036e9c3da6e8e50c Gitweb: http://git.kernel.org/tip/d9c6e1d0faec6d750b5cc08d036e9c3da6e8e50c Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:07 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:10 +0200
efi/runtime-wrappers: Remove redundant #ifdefs
Now that all users of the EFI runtime wrappers (arm,arm64,x86) have been migrated to the new setup/teardown macros, we don't need to support overridden {__,}efi_call_virt() implementations.
This patch removes the unnecessary #ifdefs.
--- drivers/firmware/efi/runtime-wrappers.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/firmware/efi/runtime-wrappers.c +0 -4
@@ -40,7 +40,6 @@* Restores the usual kernel environment once the call has returned. */ -#ifndef efi_call_virt #define efi_call_virt(f, args...) \ ({ \ efi_status_t __s; \
@@ -49,16 +48,13 @@arch_efi_call_virt_teardown (); \ __s; \ }) -#endif -#ifndef __efi_call_virt #define __efi_call_virt(f, args...) \ ({ \ arch_efi_call_virt_setup(); \ arch_efi_call_virt(f, args); \ arch_efi_call_virt_teardown(); \ }) -#endif /* * According to section 7.1 of the UEFI spec, Runtime Services are not fully
PATCH 36/40 efi/runtime-wrappers: Detect firmware irq flag corruption
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
The UEFI spec allows runtime services to be called with interrupts masked or unmasked, and if a runtime service function needs to mask interrupts, it must restore the mask to its original state before returning (i.e. from the PoV of the OS, this does not change across a call). Firmware should never unmask exceptions, as these may then be taken by the OS unexpectedly.
Unfortunately, some firmware has been seen to unmask IRQs (and potentially other maskable exceptions) across runtime services calls, leaving irq flags corrupted after returning from a runtime services function call. This may be detected by the IRQ tracing code, but often goes unnoticed, leaving a potentially disastrous bug hidden.
This patch detects when the irq flags are corrupted by an EFI runtime services call, logging the call and specific corruption to the console. While restoring the expected value of the flags is insufficient to avoid problems, we do so to avoid redundant warnings from elsewhere (e.g. IRQ tracing).
The set of bits in flags which we want to check is architecture-specific (e.g. we want to check FIQ on arm64, but not the zero flag on x86), so each arch must provide ARCH_EFI_IRQ_FLAGS_MASK to describe those. In the absence of this mask, the check is a no-op, and we redundantly save the flags twice, but that will be short-lived as subsequent patches will implement this and remove the scaffolding.
--- drivers/firmware/efi/runtime-wrappers.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
drivers/firmware/efi/runtime-wrappers.c +31 -0
@@ -16,11 +16,36 @@#include <linux/bug.h> #include <linux/efi.h> +#include <linux/irqflags.h> #include <linux/mutex.h> #include <linux/spinlock.h> +#include <linux/stringify.h> #include <asm/efi.h> /* +* Temporary scaffolding until all users provide ARCH_EFI_IRQ_FLAGS_MASK. +*/ +#ifdef ARCH_EFI_IRQ_FLAGS_MASK +static void efi_call_virt_check_flags (unsigned long flags,const char *call) +{ +unsigned long cur_flags, mismatch; + +local_save_flags (cur_flags); + + mismatch = flags ^ cur_flags; +if (!WARN_ON_ONCE (mismatch &ARCH_EFI_IRQ_FLAGS_MASK )) +return ; + +add_taint (TAINT_FIRMWARE_WORKAROUND ,LOCKDEP_NOW_UNRELIABLE ); +pr_err_ratelimited (FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n" , + flags, cur_flags, call); +local_irq_restore (flags); +} +#else /* ARCH_EFI_IRQ_FLAGS_MASK */ +static inline void efi_call_virt_check_flags (unsigned long flags,const char *call) {} +#endif /* ARCH_EFI_IRQ_FLAGS_MASK */ + +/* * Arch code can implement the following three template macros, avoiding * reptition for the void/non-void return cases of {__,}efi_call_virt: *
@@ -43,16 +68,22 @@ #define efi_call_virt(f, args...) \ ({ \ efi_status_t __s; \ + unsigned long flags; \ arch_efi_call_virt_setup(); \ + local_save_flags(flags); \ __s = arch_efi_call_virt(f, args); \ + efi_call_virt_check_flags(flags, __stringify(f)); \ arch_efi_call_virt_teardown(); \ __s; \ }) #define __efi_call_virt(f, args...) \ ({ \ + unsigned long flags; \ arch_efi_call_virt_setup(); \ + local_save_flags(flags); \ arch_efi_call_virt(f, args); \ + efi_call_virt_check_flags(flags, __stringify(f)); \ arch_efi_call_virt_teardown(); \ })
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] efi/runtime-wrappers: Detect firmware IRQ flag corruption
efi/runtime-wrappers: Detect firmware IRQ flag corruption
Commit-ID: 1d04ba1796936244a514db320976f65e2605640d Gitweb: http://git.kernel.org/tip/1d04ba1796936244a514db320976f65e2605640d Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:08 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:11 +0200
efi/runtime-wrappers: Detect firmware IRQ flag corruption
The UEFI spec allows runtime services to be called with interrupts masked or unmasked, and if a runtime service function needs to mask interrupts, it must restore the mask to its original state before returning (i.e. from the PoV of the OS, this does not change across a call). Firmware should never unmask exceptions, as these may then be taken by the OS unexpectedly.
Unfortunately, some firmware has been seen to unmask IRQs (and potentially other maskable exceptions) across runtime services calls, leaving IRQ flags corrupted after returning from a runtime services function call. This may be detected by the IRQ tracing code, but often goes unnoticed, leaving a potentially disastrous bug hidden.
This patch detects when the IRQ flags are corrupted by an EFI runtime services call, logging the call and specific corruption to the console. While restoring the expected value of the flags is insufficient to avoid problems, we do so to avoid redundant warnings from elsewhere (e.g. IRQ tracing).
The set of bits in flags which we want to check is architecture-specific (e.g. we want to check FIQ on arm64, but not the zero flag on x86), so each arch must provide ARCH_EFI_IRQ_FLAGS_MASK to describe those. In the absence of this mask, the check is a no-op, and we redundantly save the flags twice, but that will be short-lived as subsequent patches will implement this and remove the scaffolding.
--- drivers/firmware/efi/runtime-wrappers.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
drivers/firmware/efi/runtime-wrappers.c +31 -0
@@ -16,11 +16,36 @@#include <linux/bug.h> #include <linux/efi.h> +#include <linux/irqflags.h> #include <linux/mutex.h> #include <linux/spinlock.h> +#include <linux/stringify.h> #include <asm/efi.h> /* +* Temporary scaffolding until all users provide ARCH_EFI_IRQ_FLAGS_MASK. +*/ +#ifdef ARCH_EFI_IRQ_FLAGS_MASK +static void efi_call_virt_check_flags (unsigned long flags,const char *call) +{ +unsigned long cur_flags, mismatch; + +local_save_flags (cur_flags); + + mismatch = flags ^ cur_flags; +if (!WARN_ON_ONCE (mismatch &ARCH_EFI_IRQ_FLAGS_MASK )) +return ; + +add_taint (TAINT_FIRMWARE_WORKAROUND ,LOCKDEP_NOW_UNRELIABLE ); +pr_err_ratelimited (FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n" , + flags, cur_flags, call); +local_irq_restore (flags); +} +#else /* ARCH_EFI_IRQ_FLAGS_MASK */ +static inline void efi_call_virt_check_flags (unsigned long flags,const char *call) {} +#endif /* ARCH_EFI_IRQ_FLAGS_MASK */ + +/* * Arch code can implement the following three template macros, avoiding * reptition for the void/non-void return cases of {__,}efi_call_virt: *
@@ -43,16 +68,22 @@ #define efi_call_virt(f, args...) \ ({ \ efi_status_t __s; \ + unsigned long flags; \ arch_efi_call_virt_setup(); \ + local_save_flags(flags); \ __s = arch_efi_call_virt(f, args); \ + efi_call_virt_check_flags(flags, __stringify(f)); \ arch_efi_call_virt_teardown(); \ __s; \ }) #define __efi_call_virt(f, args...) \ ({ \ + unsigned long flags; \ arch_efi_call_virt_setup(); \ + local_save_flags(flags); \ arch_efi_call_virt(f, args); \ + efi_call_virt_check_flags(flags, __stringify(f)); \ arch_efi_call_virt_teardown(); \ })
PATCH 37/40 arm64/efi: Enable runtime call flag checking
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Define ARCH_EFI_IRQ_FLAGS_MASK for arm64, which will enable the generic runtime wrapper code to detect when firmware erroneously modifies flags over a runtime services function call.
--- arch/arm64/include/asm/efi.h | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/include/asm/efi.h +3 -0
@@ -4,6 +4,7 @@#include <asm/io.h> #include <asm/mmu_context.h> #include <asm/neon.h> +#include <asm/ptrace.h> #include <asm/tlbflush.h> #ifdef CONFIG_EFI
@@ -35,6 +36,8 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);kernel_neon_end (); \ }) +#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT) +/* arch specific definitions used by the stub code */ /*
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] arm64/efi: Enable runtime call flag checking
arm64/efi: Enable runtime call flag checking
Commit-ID: ee6cab5d4aba1df12e0386d22c5a1c4e71d34b31 Gitweb: http://git.kernel.org/tip/ee6cab5d4aba1df12e0386d22c5a1c4e71d34b31 Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:09 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:11 +0200
arm64/efi: Enable runtime call flag checking
Define ARCH_EFI_IRQ_FLAGS_MASK for arm64, which will enable the generic runtime wrapper code to detect when firmware erroneously modifies flags over a runtime services function call.
--- arch/arm64/include/asm/efi.h | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/include/asm/efi.h +3 -0
@@ -4,6 +4,7 @@#include <asm/io.h> #include <asm/mmu_context.h> #include <asm/neon.h> +#include <asm/ptrace.h> #include <asm/tlbflush.h> #ifdef CONFIG_EFI
@@ -35,6 +36,8 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);kernel_neon_end (); \ }) +#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT) +/* arch specific definitions used by the stub code */ /*
PATCH 38/40 arm/efi: Enable runtime call flag checking
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Define ARCH_EFI_IRQ_FLAGS_MASK for arm, which will enable the generic runtime wrapper code to detect when firmware erroneously modifies flags over a runtime services function call.
We check all allocated flags, barring those which firmware has legitimate reason to modify (condition flags and IT state). While in practice corruption of some flags (e.g. J) would already be fatal, we include these for consistency and documentation purposes.
--- arch/arm/include/asm/efi.h | 5 +++++ 1 file changed, 5 insertions(+)
arch/arm/include/asm/efi.h +5 -0
@@ -17,6 +17,7 @@#include <asm/mach/map.h> #include <asm/mmu_context.h> #include <asm/pgtable.h> +#include <asm/ptrace.h> #ifdef CONFIG_EFI void efi_init (void );
@@ -34,6 +35,10 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);__f (args); \ }) +#define ARCH_EFI_IRQ_FLAGS_MASK \ + (PSR_J_BIT | PSR_E_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | \ + PSR_T_BIT | MODE_MASK) +static inline void efi_set_pgd (struct mm_struct *mm) {check_and_switch_context (mm,NULL );
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] arm/efi: Enable runtime call flag checking
arm/efi: Enable runtime call flag checking
Commit-ID: 207a90e5cbcdb0674c8a4b499c1407962c46f6d3 Gitweb: http://git.kernel.org/tip/207a90e5cbcdb0674c8a4b499c1407962c46f6d3 Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:10 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:12 +0200
arm/efi: Enable runtime call flag checking
Define ARCH_EFI_IRQ_FLAGS_MASK for arm, which will enable the generic runtime wrapper code to detect when firmware erroneously modifies flags over a runtime services function call.
We check all allocated flags, barring those which firmware has legitimate reason to modify (condition flags and IT state). While in practice corruption of some flags (e.g. J) would already be fatal, we include these for consistency and documentation purposes.
--- arch/arm/include/asm/efi.h | 5 +++++ 1 file changed, 5 insertions(+)
arch/arm/include/asm/efi.h +5 -0
@@ -17,6 +17,7 @@#include <asm/mach/map.h> #include <asm/mmu_context.h> #include <asm/pgtable.h> +#include <asm/ptrace.h> #ifdef CONFIG_EFI void efi_init (void );
@@ -34,6 +35,10 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);__f (args); \ }) +#define ARCH_EFI_IRQ_FLAGS_MASK \ + (PSR_J_BIT | PSR_E_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | \ + PSR_T_BIT | MODE_MASK) +static inline void efi_set_pgd (struct mm_struct *mm) {check_and_switch_context (mm,NULL );
PATCH 39/40 x86/efi: Enable runtime call flag checking
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Define ARCH_EFI_IRQ_FLAGS_MASK for x86, which will enable the generic runtime wrapper code to detect when firmware erroneously modifies flags over a runtime services function call.
For x86 (both 32-bit and 64-bit), we only need check the interrupt flag.
--- arch/x86/include/asm/efi.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/include/asm/efi.h +3 -1
@@ -3,6 +3,7 @@#include <asm/fpu/api.h> #include <asm/pgtable.h> +#include <asm/processor-flags.h> #include <asm/tlb.h> /*
@@ -28,8 +29,9 @@#define MAX_CMDLINE_ADDRESS UINT_MAX -#ifdef CONFIG_X86_32 +#define ARCH_EFI_IRQ_FLAGS_MASK X86_EFLAGS_IF +#ifdef CONFIG_X86_32 extern unsigned long asmlinkage efi_call_phys (void *, ...);
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] x86/efi: Enable runtime call flag checking
x86/efi: Enable runtime call flag checking
Commit-ID: 9788375dc4cdc9c00645028384fb40402eab774f Gitweb: http://git.kernel.org/tip/9788375dc4cdc9c00645028384fb40402eab774f Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:11 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:13 +0200
x86/efi: Enable runtime call flag checking
Define ARCH_EFI_IRQ_FLAGS_MASK for x86, which will enable the generic runtime wrapper code to detect when firmware erroneously modifies flags over a runtime services function call.
For x86 (both 32-bit and 64-bit), we only need check the interrupt flag.
--- arch/x86/include/asm/efi.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/include/asm/efi.h +3 -1
@@ -3,6 +3,7 @@#include <asm/fpu/api.h> #include <asm/pgtable.h> +#include <asm/processor-flags.h> #include <asm/tlb.h> /*
@@ -28,8 +29,9 @@#define MAX_CMDLINE_ADDRESS UINT_MAX -#ifdef CONFIG_X86_32 +#define ARCH_EFI_IRQ_FLAGS_MASK X86_EFLAGS_IF +#ifdef CONFIG_X86_32 extern unsigned long asmlinkage efi_call_phys (void *, ...);
PATCH 40/40 efi/runtime-wrappers: Remove ARCH_EFI_IRQ_FLAGS_MASK ifdef
In reply to Matt FlemingFrom: Mark Rutland <[email protected]>
Now that arm, arm64, and x86 all provide ARCH_EFI_IRQ_FLAGS_MASK, we can get rid of the trivial and now unused implementation of efi_call_virt_check_flags.
--- drivers/firmware/efi/runtime-wrappers.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/firmware/efi/runtime-wrappers.c +0 -7
@@ -22,10 +22,6 @@#include <linux/stringify.h> #include <asm/efi.h> -/* -* Temporary scaffolding until all users provide ARCH_EFI_IRQ_FLAGS_MASK. -*/ -#ifdef ARCH_EFI_IRQ_FLAGS_MASK static void efi_call_virt_check_flags (unsigned long flags,const char *call) {unsigned long cur_flags, mismatch;
@@ -41,9 +37,6 @@ static void efi_call_virt_check_flags(unsigned long flags, const char *call) flags, cur_flags, call);local_irq_restore (flags); } -#else /* ARCH_EFI_IRQ_FLAGS_MASK */ -static inline void efi_call_virt_check_flags (unsigned long flags,const char *call) {} -#endif /* ARCH_EFI_IRQ_FLAGS_MASK */ /* * Arch code can implement the following three template macros, avoiding
Signature · 1 line
2.7.3
tip-bot for Mark Rutland
merge bot[tip:efi/core] efi/runtime-wrappers: Remove ARCH_EFI_IRQ_FLAGS_MASK #ifdef
efi/runtime-wrappers: Remove ARCH_EFI_IRQ_FLAGS_MASK #ifdef
Commit-ID: 0cf0223c8370af0fcedb15a408d3c17bb4b9e21d Gitweb: http://git.kernel.org/tip/0cf0223c8370af0fcedb15a408d3c17bb4b9e21d Author: Mark Rutland <[email protected]> AuthorDate: Mon, 25 Apr 2016 21:07:12 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 28 Apr 2016 11:34:13 +0200
efi/runtime-wrappers: Remove ARCH_EFI_IRQ_FLAGS_MASK #ifdef
Now that arm, arm64, and x86 all provide ARCH_EFI_IRQ_FLAGS_MASK, we can get rid of the trivial and now unused implementation of efi_call_virt_check_flags().
--- drivers/firmware/efi/runtime-wrappers.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/firmware/efi/runtime-wrappers.c +0 -7
@@ -22,10 +22,6 @@#include <linux/stringify.h> #include <asm/efi.h> -/* -* Temporary scaffolding until all users provide ARCH_EFI_IRQ_FLAGS_MASK. -*/ -#ifdef ARCH_EFI_IRQ_FLAGS_MASK static void efi_call_virt_check_flags (unsigned long flags,const char *call) {unsigned long cur_flags, mismatch;
@@ -41,9 +37,6 @@ static void efi_call_virt_check_flags(unsigned long flags, const char *call) flags, cur_flags, call);local_irq_restore (flags); } -#else /* ARCH_EFI_IRQ_FLAGS_MASK */ -static inline void efi_call_virt_check_flags (unsigned long flags,const char *call) {} -#endif /* ARCH_EFI_IRQ_FLAGS_MASK */ /* * Arch code can implement the following three template macros, avoiding