Skip to contentSkip to conversation

Fix ACPI BGRT support for images located in EFI boot services memory

PATCH Superseded Josh Triplett 4 participants 14 messages Sep 8, 2012 – Oct 1, 2012

Subsystems (3)

v3 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v3 cover Fix ACPI BGRT support for images located in EFI boot services memory

The ACPI BGRT lets the OS access the BIOS logo image and its position on the screen at boot time, allowing it to maintain that image on the screen until ready to display something else, making boot more seamless. This series fixes support for accessing the boot logo image via the BGRT when the BIOS stores it in EFI boot services memory, as recommended by the ACPI 5.0 spec. Linux needs to copy the image out of boot services memory before reclaiming boot services memory.

The first patch cleans up the existing x86-specific efi_enter_virtual_mode function to have a stub version on non-x86 platforms, to eliminate an ifdef in
init/main.c. The second patch refactors EFI initialization to defer freeing
boot services memory until much later in the boot process, and in particular until after we have ACPI available. The third patch adds a helper function to look up existing EFI boot services mappings, to avoid re-mapping them. The fourth patch moves BGRT initialization to before the reclamation of boot services memory, copies the logo at that point, and reworks the existing BGRT driver to use that existing copy.

v2: Made the new internal function efi_unmap_memmap static. Incorporated
feedback from H. Peter Anvin and Matt Fleming: added stubs for x86-specific EFI functions called from init/main.c to eliminate the corresponding ifdefs in start_kernel; deferred efi_free_boot_services even later, to just before free_initmem.

v3: Moved efi_free_boot_services back to right after EFI initialization, to
avoid a WARN from check_early_ioremap_leak about not calling early_iounmap soon enough.

Josh Triplett (4):
efi: Add a stub for efi_enter_virtual_mode on non-x86
efi: Defer freeing boot services memory until after ACPI init
efi: Add a function to look up existing IO memory mappings
efi: Fix the ACPI BGRT driver for images located in EFI boot services
memory

 arch/x86/platform/efi/Makefile   |    1 +
 arch/x86/platform/efi/efi-bgrt.c |   76 ++++++++++++++++++++++++++++++++++++++
 arch/x86/platform/efi/efi.c      |   65 +++++++++++++++++++++++++-------
 drivers/acpi/Kconfig             |    4 +-
 drivers/acpi/bgrt.c              |   76 +++++---------------------------------
 include/linux/efi-bgrt.h         |   21 +++++++++++
 include/linux/efi.h              |    9 +++++
 init/main.c                      |    7 +++-
 8 files changed, 175 insertions(+), 84 deletions(-)
 create mode 100644 arch/x86/platform/efi/efi-bgrt.c
 create mode 100644 include/linux/efi-bgrt.h
Signature · 1 line
1.7.10.4
#1 lore raw

PATCH v3 1/4 efi: Add a stub for efi_enter_virtual_mode on non-x86

This eliminates an ifdef in init/main.c.

---
 include/linux/efi.h |    4 ++++
 init/main.c         |    2 --
 2 files changed, 4 insertions(+), 2 deletions(-)
include/linux/efi.h +4 -0
index ec45ccd..52fbedf 100644
@@ -495,7 +495,11 @@ extern void *efi_get_pal_addr (void);
 extern void efi_map_pal_code (void);
 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
+#ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+#else
+static void efi_enter_virtual_mode(void) {}
+#endif
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
init/main.c +0 -2
index b286730..ebb1ba5 100644
@@ -602,10 +602,8 @@ asmlinkage void __init start_kernel(void)
 	calibrate_delay();
 	pidmap_init();
 	anon_vma_init();
-#ifdef CONFIG_X86
 	if (efi_enabled)
 		efi_enter_virtual_mode();
-#endif
 	thread_info_cache_init();
 	cred_init();
 	fork_init(totalram_pages);
Signature · 1 line
1.7.10.4
#2 lore raw

[tip:x86/efi] efi: Add a stub for efi_enter_virtual_mode on non-x86

Commit-ID:  f383a1e37bc3fc93d19ed23dfdb1adfc5a7d1010
Gitweb:     http://git.kernel.org/tip/f383a1e37bc3fc93d19ed23dfdb1adfc5a7d1010
Author:     Josh Triplett <[email protected]>
AuthorDate: Sat, 8 Sep 2012 15:06:49 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 27 Sep 2012 14:43:32 -0700

efi: Add a stub for efi_enter_virtual_mode on non-x86

This eliminates an ifdef in init/main.c.

---
 include/linux/efi.h |    4 ++++
 init/main.c         |    2 --
 2 files changed, 4 insertions(+), 2 deletions(-)
include/linux/efi.h +4 -0
index ec45ccd..52fbedf 100644
@@ -495,7 +495,11 @@ extern void *efi_get_pal_addr (void);
 extern void efi_map_pal_code (void);
 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
+#ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+#else
+static void efi_enter_virtual_mode(void) {}
+#endif
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
init/main.c +0 -2
index b286730..ebb1ba5 100644
@@ -602,10 +602,8 @@ asmlinkage void __init start_kernel(void)
 	calibrate_delay();
 	pidmap_init();
 	anon_vma_init();
-#ifdef CONFIG_X86
 	if (efi_enabled)
 		efi_enter_virtual_mode();
-#endif
 	thread_info_cache_init();
 	cred_init();
 	fork_init(totalram_pages);
#3 lore raw

Re: [PATCHv3 1/4] efi: Add a stub for efi_enter_virtual_mode on non-x86

In reply to Josh Triplett

Review

Quoted 5 lines · Josh Triplett
(quoted diff) +4 -0
+#ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);     /* switch EFI to virtual mode, if possible */
+#else
+static void efi_enter_virtual_mode(void) {}
+#endif

This has suddenly appeared in linux-next now and is causing warnings.

8<---
efi: fix prototype for API stubs

Some functions in the efi API have recently been added as versions for non-x86, but are missing an "inline" keyword, which causes these warnings:

include/linux/efi.h:503:13: error: 'efi_enter_virtual_mode' defined but not used [-Werror=unused-function] include/linux/efi.h:504:13: error: 'efi_late_init' defined but not used [-Werror=unused-function] include/linux/efi.h:505:13: error: 'efi_free_boot_services' defined but not used [-Werror=unused-function]

include/linux/efi.h +3 -3
index 798bd1d..58f31c3 100644
@@ -500,9 +500,9 @@ extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if pos
 extern void efi_late_init(void);
 extern void efi_free_boot_services(void);
 #else
-static void efi_enter_virtual_mode(void) {}
-static void efi_late_init(void) {}
-static void efi_free_boot_services(void) {}
+static inline void efi_enter_virtual_mode(void) {}
+static inline void efi_late_init(void) {}
+static inline void efi_free_boot_services(void) {}
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
 extern u64 efi_get_iobase (void);
#4 lore raw

Re: [PATCHv3 1/4] efi: Add a stub for efi_enter_virtual_mode on non-x86

Quoted 12 lines · Arnd Bergmann

Review

Quoted 5 lines · Josh Triplett
(quoted diff) +4 -0
+#ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);     /* switch EFI to virtual mode, if possible */
+#else
+static void efi_enter_virtual_mode(void) {}
+#endif

This has suddenly appeared in linux-next now and is causing warnings.

8<---
efi: fix prototype for API stubs

Quoted 6 lines

Some functions in the efi API have recently been added as versions for non-x86, but are missing an "inline" keyword, which causes these warnings:

include/linux/efi.h:503:13: error: 'efi_enter_virtual_mode' defined but not used [-Werror=unused-function] include/linux/efi.h:504:13: error: 'efi_late_init' defined but not used [-Werror=unused-function] include/linux/efi.h:505:13: error: 'efi_free_boot_services' defined but not used [-Werror=unused-function]

Already fixed in current tip; please refresh from there.

- Josh Triplett

#5 lore raw

PATCH v3 2/4 efi: Defer freeing boot services memory until after ACPI init

In reply to Josh Triplett

Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it.

---
 arch/x86/platform/efi/efi.c |   31 ++++++++++++++++++-------------
 include/linux/efi.h         |    2 ++
 init/main.c                 |    3 +++
 3 files changed, 23 insertions(+), 13 deletions(-)
arch/x86/platform/efi/efi.c +18 -13
index 92660eda..ab2cfe8 100644
@@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void)
 	}
 }
 
-static void __init efi_free_boot_services(void)
+static void __init efi_unmap_memmap(void)
+{
+	if (memmap.map) {
+		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+		memmap.map = NULL;
+	}
+}
+
+void __init efi_free_boot_services(void)
 {
 	void *p;
 
+	if (!efi_native)
+		return;
+
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
 		efi_memory_desc_t *md = p;
 		unsigned long long start = md->phys_addr;
@@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void)
 
 		free_bootmem_late(start, size);
 	}
+
+	efi_unmap_memmap();
 }
 
 static int __init efi_systab_init(void *phys)
@@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void)
 	 * non-native EFI
 	 */
 
-	if (!efi_native)
-		goto out;
+	if (!efi_native) {
+		efi_unmap_memmap();
+		return;
+	}
 
 	/* Merge contiguous regions of the same type and attribute */
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void)
 	}
 
 	/*
-	 * Thankfully, it does seem that no runtime services other than
-	 * SetVirtualAddressMap() will touch boot services code, so we can
-	 * get rid of it all at this point
-	 */
-	efi_free_boot_services();
-
-	/*
 	 * Now that EFI is in virtual mode, update the function
 	 * pointers in the runtime service table to the new virtual addresses.
 	 *
@@ -906,9 +914,6 @@ void __init efi_enter_virtual_mode(void)
 	if (__supported_pte_mask & _PAGE_NX)
 		runtime_code_page_mkexec();
 
-out:
-	early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
-	memmap.map = NULL;
 	kfree(new_memmap);
 }
 
include/linux/efi.h +2 -0
index 52fbedf..3c72c27 100644
@@ -497,8 +497,10 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
 #ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+extern void efi_free_boot_services(void);
 #else
 static void efi_enter_virtual_mode(void) {}
+static void efi_free_boot_services(void) {}
 #endif
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
init/main.c +3 -0
index ebb1ba5..78e5491 100644
@@ -629,6 +629,9 @@ asmlinkage void __init start_kernel(void)
 	acpi_early_init(); /* before LAPIC and SMP init */
 	sfi_init_late();
 
+	if (efi_enabled)
+		efi_free_boot_services();
+
 	ftrace_init();
 
 	/* Do the rest non-__init'ed, we're now alive */
Signature · 1 line
1.7.10.4
#6 lore raw

[tip:x86/efi] efi: Defer freeing boot services memory until after ACPI init

Commit-ID:  668b132e837a2d1b346699bad4ae2e85bce52f55
Gitweb:     http://git.kernel.org/tip/668b132e837a2d1b346699bad4ae2e85bce52f55
Author:     Josh Triplett <[email protected]>
AuthorDate: Sat, 8 Sep 2012 15:06:56 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 27 Sep 2012 14:43:32 -0700

efi: Defer freeing boot services memory until after ACPI init

Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it.

---
 arch/x86/platform/efi/efi.c |   31 ++++++++++++++++++-------------
 include/linux/efi.h         |    2 ++
 init/main.c                 |    3 +++
 3 files changed, 23 insertions(+), 13 deletions(-)
arch/x86/platform/efi/efi.c +18 -13
index f55a4ce..b3dbbdb 100644
@@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void)
 	}
 }
 
-static void __init efi_free_boot_services(void)
+static void __init efi_unmap_memmap(void)
+{
+	if (memmap.map) {
+		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+		memmap.map = NULL;
+	}
+}
+
+void __init efi_free_boot_services(void)
 {
 	void *p;
 
+	if (!efi_native)
+		return;
+
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
 		efi_memory_desc_t *md = p;
 		unsigned long long start = md->phys_addr;
@@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void)
 
 		free_bootmem_late(start, size);
 	}
+
+	efi_unmap_memmap();
 }
 
 static int __init efi_systab_init(void *phys)
@@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void)
 	 * non-native EFI
 	 */
 
-	if (!efi_native)
-		goto out;
+	if (!efi_native) {
+		efi_unmap_memmap();
+		return;
+	}
 
 	/* Merge contiguous regions of the same type and attribute */
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void)
 	}
 
 	/*
-	 * Thankfully, it does seem that no runtime services other than
-	 * SetVirtualAddressMap() will touch boot services code, so we can
-	 * get rid of it all at this point
-	 */
-	efi_free_boot_services();
-
-	/*
 	 * Now that EFI is in virtual mode, update the function
 	 * pointers in the runtime service table to the new virtual addresses.
 	 *
@@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void)
 	if (__supported_pte_mask & _PAGE_NX)
 		runtime_code_page_mkexec();
 
-out:
-	early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
-	memmap.map = NULL;
 	kfree(new_memmap);
 }
 
include/linux/efi.h +2 -0
index 52fbedf..3c72c27 100644
@@ -497,8 +497,10 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
 #ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+extern void efi_free_boot_services(void);
 #else
 static void efi_enter_virtual_mode(void) {}
+static void efi_free_boot_services(void) {}
 #endif
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
init/main.c +3 -0
index ebb1ba5..78e5491 100644
@@ -629,6 +629,9 @@ asmlinkage void __init start_kernel(void)
 	acpi_early_init(); /* before LAPIC and SMP init */
 	sfi_init_late();
 
+	if (efi_enabled)
+		efi_free_boot_services();
+
 	ftrace_init();
 
 	/* Do the rest non-__init'ed, we're now alive */
#7 lore raw

PATCH v3 3/4 efi: Add a function to look up existing IO memory mappings

In reply to Josh Triplett

The EFI initialization creates virtual mappings for EFI boot services memory, so if a driver wants to access EFI boot services memory, it cannot call ioremap itself; doing so will trip the WARN about mapping RAM twice. Thus, a driver accessing EFI boot services memory must do so via the existing mapping already created during EFI intiialization. Since the EFI code already maintains a memory map for that memory, add a function efi_lookup_mapped_addr to look up mappings in that memory map.

---
 arch/x86/platform/efi/efi.c |   28 ++++++++++++++++++++++++++++
 include/linux/efi.h         |    1 +
 2 files changed, 29 insertions(+)
arch/x86/platform/efi/efi.c +28 -0
index ab2cfe8..90023d1 100644
@@ -777,6 +777,34 @@ static void __init runtime_code_page_mkexec(void)
 }
 
 /*
+ * We can't ioremap data in EFI boot services RAM, because we've already mapped
+ * it as RAM.  So, look it up in the existing EFI memory map instead.  Only
+ * callable after efi_enter_virtual_mode and before efi_free_boot_services.
+ */
+void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
+{
+	void *p;
+	if (WARN_ON(!memmap.map))
+		return NULL;
+	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+		efi_memory_desc_t *md = p;
+		u64 size = md->num_pages << EFI_PAGE_SHIFT;
+		u64 end = md->phys_addr + size;
+		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
+		    md->type != EFI_BOOT_SERVICES_CODE &&
+		    md->type != EFI_BOOT_SERVICES_DATA)
+			continue;
+		if (!md->virt_addr)
+			continue;
+		if (phys_addr >= md->phys_addr && phys_addr < end) {
+			phys_addr += md->virt_addr - md->phys_addr;
+			return (__force void __iomem *)phys_addr;
+		}
+	}
+	return NULL;
+}
+
+/*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
  * has the runtime attribute bit set in its memory descriptor and update
include/linux/efi.h +1 -0
index 3c72c27..00aa5de 100644
@@ -502,6 +502,7 @@ extern void efi_free_boot_services(void);
 static void efi_enter_virtual_mode(void) {}
 static void efi_free_boot_services(void) {}
 #endif
+extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
Signature · 1 line
1.7.10.4
#8 lore raw

[tip:x86/efi] efi: Add a function to look up existing IO memory mappings

Commit-ID:  429c5a7fa9294e9792116d6ba1016b2cf39572e4
Gitweb:     http://git.kernel.org/tip/429c5a7fa9294e9792116d6ba1016b2cf39572e4
Author:     Josh Triplett <[email protected]>
AuthorDate: Sat, 8 Sep 2012 15:09:19 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 27 Sep 2012 14:43:32 -0700

efi: Add a function to look up existing IO memory mappings

The EFI initialization creates virtual mappings for EFI boot services memory, so if a driver wants to access EFI boot services memory, it cannot call ioremap itself; doing so will trip the WARN about mapping RAM twice. Thus, a driver accessing EFI boot services memory must do so via the existing mapping already created during EFI intiialization. Since the EFI code already maintains a memory map for that memory, add a function efi_lookup_mapped_addr to look up mappings in that memory map.

---
 arch/x86/platform/efi/efi.c |   28 ++++++++++++++++++++++++++++
 include/linux/efi.h         |    1 +
 2 files changed, 29 insertions(+), 0 deletions(-)
arch/x86/platform/efi/efi.c +28 -0
index b3dbbdb..78d3343 100644
@@ -777,6 +777,34 @@ static void __init runtime_code_page_mkexec(void)
 }
 
 /*
+ * We can't ioremap data in EFI boot services RAM, because we've already mapped
+ * it as RAM.  So, look it up in the existing EFI memory map instead.  Only
+ * callable after efi_enter_virtual_mode and before efi_free_boot_services.
+ */
+void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
+{
+	void *p;
+	if (WARN_ON(!memmap.map))
+		return NULL;
+	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+		efi_memory_desc_t *md = p;
+		u64 size = md->num_pages << EFI_PAGE_SHIFT;
+		u64 end = md->phys_addr + size;
+		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
+		    md->type != EFI_BOOT_SERVICES_CODE &&
+		    md->type != EFI_BOOT_SERVICES_DATA)
+			continue;
+		if (!md->virt_addr)
+			continue;
+		if (phys_addr >= md->phys_addr && phys_addr < end) {
+			phys_addr += md->virt_addr - md->phys_addr;
+			return (__force void __iomem *)phys_addr;
+		}
+	}
+	return NULL;
+}
+
+/*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
  * has the runtime attribute bit set in its memory descriptor and update
include/linux/efi.h +1 -0
index 3c72c27..00aa5de 100644
@@ -502,6 +502,7 @@ extern void efi_free_boot_services(void);
 static void efi_enter_virtual_mode(void) {}
 static void efi_free_boot_services(void) {}
 #endif
+extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
#9 lore raw

PATCH v3 4/4 efi: Fix the ACPI BGRT driver for images located in EFI boot services memory

In reply to Josh Triplett

The ACPI BGRT driver accesses the BIOS logo image when it initializes. However, ACPI 5.0 (which introduces the BGRT) recommends putting the logo image in EFI boot services memory, so that the OS can reclaim that memory. Production systems follow this recommendation, breaking the ACPI BGRT driver.

Move the bulk of the BGRT code to run during a new EFI late initialization phase, which occurs after switching EFI to virtual mode, and after initializing ACPI, but before freeing boot services memory. Copy the BIOS logo image to kernel memory at that point, and make it accessible to the BGRT driver. Rework the existing ACPI BGRT driver to act as a simple wrapper exposing that image (and the properties from the BGRT) via sysfs.

---
 arch/x86/platform/efi/Makefile   |    1 +
 arch/x86/platform/efi/efi-bgrt.c |   76 ++++++++++++++++++++++++++++++++++++++
 arch/x86/platform/efi/efi.c      |    6 +++
 drivers/acpi/Kconfig             |    4 +-
 drivers/acpi/bgrt.c              |   76 +++++---------------------------------
 include/linux/efi-bgrt.h         |   21 +++++++++++
 include/linux/efi.h              |    2 +
 init/main.c                      |    4 +-
 8 files changed, 120 insertions(+), 70 deletions(-)
 create mode 100644 arch/x86/platform/efi/efi-bgrt.c
 create mode 100644 include/linux/efi-bgrt.h
arch/x86/platform/efi/Makefile +1 -0
index 73b8be0..6db1cc4 100644
@@ -1 +1,2 @@
 obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
+obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
arch/x86/platform/efi/efi-bgrt.c new file +76 -0

76 lines not on this page · raw message

arch/x86/platform/efi/efi.c +6 -0
index 90023d1..faa04f7 100644
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/efi.h>
+#include <linux/efi-bgrt.h>
 #include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
@@ -745,6 +746,11 @@ void __init efi_init(void)
 #endif
 }
 
+void __init efi_late_init(void)
+{
+	efi_bgrt_init();
+}
+
 void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
 {
 	u64 addr, npages;
drivers/acpi/Kconfig +2 -2
index 8099895..119d58d 100644
@@ -385,8 +385,8 @@ config ACPI_CUSTOM_METHOD
 	  to override that restriction).
 
 config ACPI_BGRT
-        tristate "Boottime Graphics Resource Table support"
-        default n
+	bool "Boottime Graphics Resource Table support"
+	depends on EFI
         help
 	  This driver adds support for exposing the ACPI Boottime Graphics
 	  Resource Table, which allows the operating system to obtain
drivers/acpi/bgrt.c +9 -67

119 lines not on this page · raw message

include/linux/efi-bgrt.h new file +21 -0
new file mode 100644
index 0000000..051b21f
@@ -0,0 +1,21 @@
+#ifndef _LINUX_EFI_BGRT_H
+#define _LINUX_EFI_BGRT_H
+
+#ifdef CONFIG_ACPI_BGRT
+
+#include <linux/acpi.h>
+
+void efi_bgrt_init(void);
+
+/* The BGRT data itself; only valid if bgrt_image != NULL. */
+extern void *bgrt_image;
+extern size_t bgrt_image_size;
+extern struct acpi_table_bgrt *bgrt_tab;
+
+#else /* !CONFIG_ACPI_BGRT */
+
+static inline void efi_bgrt_init(void) {}
+
+#endif /* !CONFIG_ACPI_BGRT */
+
+#endif /* _LINUX_EFI_BGRT_H */
include/linux/efi.h +2 -0
index 00aa5de..798bd1d 100644
@@ -497,9 +497,11 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
 #ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+extern void efi_late_init(void);
 extern void efi_free_boot_services(void);
 #else
 static void efi_enter_virtual_mode(void) {}
+static void efi_late_init(void) {}
 static void efi_free_boot_services(void) {}
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
init/main.c +3 -1
index 78e5491..adb3f46 100644
@@ -629,8 +629,10 @@ asmlinkage void __init start_kernel(void)
 	acpi_early_init(); /* before LAPIC and SMP init */
 	sfi_init_late();
 
-	if (efi_enabled)
+	if (efi_enabled) {
+		efi_late_init();
 		efi_free_boot_services();
+	}
 
 	ftrace_init();
 
Signature · 1 line
1.7.10.4
reviewer Acked-by on v3 4/4
#10 lore raw

Re: [PATCHv3 4/4] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory

for drivers/acpi/

As this is mostly an EFI thing, I assume HPA is handling this series.

-Len Brown, Intel Open Source Technology Center

#11 lore raw

[tip:x86/efi] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory

In reply to Josh Triplett
Commit-ID:  ba49efa14f97ca6fe57390539e70a359aea779cd
Gitweb:     http://git.kernel.org/tip/ba49efa14f97ca6fe57390539e70a359aea779cd
Author:     Josh Triplett <[email protected]>
AuthorDate: Sat, 8 Sep 2012 15:09:26 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 27 Sep 2012 14:43:32 -0700

efi: Fix the ACPI BGRT driver for images located in EFI boot services memory

The ACPI BGRT driver accesses the BIOS logo image when it initializes. However, ACPI 5.0 (which introduces the BGRT) recommends putting the logo image in EFI boot services memory, so that the OS can reclaim that memory. Production systems follow this recommendation, breaking the ACPI BGRT driver.

Move the bulk of the BGRT code to run during a new EFI late initialization phase, which occurs after switching EFI to virtual mode, and after initializing ACPI, but before freeing boot services memory. Copy the BIOS logo image to kernel memory at that point, and make it accessible to the BGRT driver. Rework the existing ACPI BGRT driver to act as a simple wrapper exposing that image (and the properties from the BGRT) via sysfs.

---
 arch/x86/platform/efi/Makefile   |    1 +
 arch/x86/platform/efi/efi-bgrt.c |   76 ++++++++++++++++++++++++++++++++++++++
 arch/x86/platform/efi/efi.c      |    6 +++
 drivers/acpi/Kconfig             |    4 +-
 drivers/acpi/bgrt.c              |   76 ++++---------------------------------
 include/linux/efi-bgrt.h         |   21 ++++++++++
 include/linux/efi.h              |    2 +
 init/main.c                      |    4 +-
 8 files changed, 120 insertions(+), 70 deletions(-)
arch/x86/platform/efi/Makefile +1 -0
index 73b8be0..6db1cc4 100644
@@ -1 +1,2 @@
 obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
+obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
arch/x86/platform/efi/efi-bgrt.c new file +76 -0

76 lines not on this page · raw message

arch/x86/platform/efi/efi.c +6 -0
index 78d3343..f8a30da 100644
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/efi.h>
+#include <linux/efi-bgrt.h>
 #include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
@@ -745,6 +746,11 @@ void __init efi_init(void)
 #endif
 }
 
+void __init efi_late_init(void)
+{
+	efi_bgrt_init();
+}
+
 void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
 {
 	u64 addr, npages;
drivers/acpi/Kconfig +2 -2
index 8099895..119d58d 100644
@@ -385,8 +385,8 @@ config ACPI_CUSTOM_METHOD
 	  to override that restriction).
 
 config ACPI_BGRT
-        tristate "Boottime Graphics Resource Table support"
-        default n
+	bool "Boottime Graphics Resource Table support"
+	depends on EFI
         help
 	  This driver adds support for exposing the ACPI Boottime Graphics
 	  Resource Table, which allows the operating system to obtain
drivers/acpi/bgrt.c +9 -67

119 lines not on this page · raw message

include/linux/efi-bgrt.h new file +21 -0
new file mode 100644
index 0000000..051b21f
@@ -0,0 +1,21 @@
+#ifndef _LINUX_EFI_BGRT_H
+#define _LINUX_EFI_BGRT_H
+
+#ifdef CONFIG_ACPI_BGRT
+
+#include <linux/acpi.h>
+
+void efi_bgrt_init(void);
+
+/* The BGRT data itself; only valid if bgrt_image != NULL. */
+extern void *bgrt_image;
+extern size_t bgrt_image_size;
+extern struct acpi_table_bgrt *bgrt_tab;
+
+#else /* !CONFIG_ACPI_BGRT */
+
+static inline void efi_bgrt_init(void) {}
+
+#endif /* !CONFIG_ACPI_BGRT */
+
+#endif /* _LINUX_EFI_BGRT_H */
include/linux/efi.h +2 -0
index 00aa5de..798bd1d 100644
@@ -497,9 +497,11 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
 #ifdef CONFIG_X86
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+extern void efi_late_init(void);
 extern void efi_free_boot_services(void);
 #else
 static void efi_enter_virtual_mode(void) {}
+static void efi_late_init(void) {}
 static void efi_free_boot_services(void) {}
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
init/main.c +3 -1
index 78e5491..adb3f46 100644
@@ -629,8 +629,10 @@ asmlinkage void __init start_kernel(void)
 	acpi_early_init(); /* before LAPIC and SMP init */
 	sfi_init_late();
 
-	if (efi_enabled)
+	if (efi_enabled) {
+		efi_late_init();
 		efi_free_boot_services();
+	}
 
 	ftrace_init();
 
Acked-by on the v3 series
#12 lore raw
In reply to Josh Triplett
Quoted 35 lines · Josh Triplett

The ACPI BGRT lets the OS access the BIOS logo image and its position on the screen at boot time, allowing it to maintain that image on the screen until ready to display something else, making boot more seamless. This series fixes support for accessing the boot logo image via the BGRT when the BIOS stores it in EFI boot services memory, as recommended by the ACPI 5.0 spec. Linux needs to copy the image out of boot services memory before reclaiming boot services memory.

The first patch cleans up the existing x86-specific efi_enter_virtual_mode function to have a stub version on non-x86 platforms, to eliminate an ifdef in
init/main.c. The second patch refactors EFI initialization to defer freeing
boot services memory until much later in the boot process, and in particular until after we have ACPI available. The third patch adds a helper function to look up existing EFI boot services mappings, to avoid re-mapping them. The fourth patch moves BGRT initialization to before the reclamation of boot services memory, copies the logo at that point, and reworks the existing BGRT driver to use that existing copy.

v2: Made the new internal function efi_unmap_memmap static. Incorporated
feedback from H. Peter Anvin and Matt Fleming: added stubs for x86-specific EFI functions called from init/main.c to eliminate the corresponding ifdefs in start_kernel; deferred efi_free_boot_services even later, to just before free_initmem.

v3: Moved efi_free_boot_services back to right after EFI initialization, to
avoid a WARN from check_early_ioremap_leak about not calling early_iounmap soon enough.

Josh Triplett (4):
efi: Add a stub for efi_enter_virtual_mode on non-x86
efi: Defer freeing boot services memory until after ACPI init
efi: Add a function to look up existing IO memory mappings
efi: Fix the ACPI BGRT driver for images located in EFI boot services
memory

Quoted 11 lines
 arch/x86/platform/efi/Makefile   |    1 +
 arch/x86/platform/efi/efi-bgrt.c |   76 ++++++++++++++++++++++++++++++++++++++
 arch/x86/platform/efi/efi.c      |   65 +++++++++++++++++++++++++-------
 drivers/acpi/Kconfig             |    4 +-
 drivers/acpi/bgrt.c              |   76 +++++---------------------------------
 include/linux/efi-bgrt.h         |   21 +++++++++++
 include/linux/efi.h              |    9 +++++
 init/main.c                      |    7 +++-
 8 files changed, 175 insertions(+), 84 deletions(-)
 create mode 100644 arch/x86/platform/efi/efi-bgrt.c
 create mode 100644 include/linux/efi-bgrt.h

Looks good to me.

Acked-by on the v3 series
#13 lore raw
In reply to Josh Triplett
Quoted 28 lines · Josh Triplett

The ACPI BGRT lets the OS access the BIOS logo image and its position on the screen at boot time, allowing it to maintain that image on the screen until ready to display something else, making boot more seamless. This series fixes support for accessing the boot logo image via the BGRT when the BIOS stores it in EFI boot services memory, as recommended by the ACPI 5.0 spec. Linux needs to copy the image out of boot services memory before reclaiming boot services memory.

The first patch cleans up the existing x86-specific efi_enter_virtual_mode function to have a stub version on non-x86 platforms, to eliminate an ifdef in
init/main.c. The second patch refactors EFI initialization to defer freeing
boot services memory until much later in the boot process, and in particular until after we have ACPI available. The third patch adds a helper function to look up existing EFI boot services mappings, to avoid re-mapping them. The fourth patch moves BGRT initialization to before the reclamation of boot services memory, copies the logo at that point, and reworks the existing BGRT driver to use that existing copy.

v2: Made the new internal function efi_unmap_memmap static. Incorporated
feedback from H. Peter Anvin and Matt Fleming: added stubs for x86-specific EFI functions called from init/main.c to eliminate the corresponding ifdefs in start_kernel; deferred efi_free_boot_services even later, to just before free_initmem.

v3: Moved efi_free_boot_services back to right after EFI initialization, to
avoid a WARN from check_early_ioremap_leak about not calling early_iounmap soon enough.

Quoted 6 lines

Josh Triplett (4):
efi: Add a stub for efi_enter_virtual_mode on non-x86
efi: Defer freeing boot services memory until after ACPI init
efi: Add a function to look up existing IO memory mappings
efi: Fix the ACPI BGRT driver for images located in EFI boot services
memory

I thought I'd replied to this but I can't find it anywhere. I think my MUA ate my ACK.