[tip:core/efi] efi: Add support for EFI_MEMORY_RO attribute introduced by UEFIv2.5

2015-08-09 Thread tip-bot for Ard Biesheuvel
Commit-ID:  87db73aebf4fefaa3eade0a28f282a1511b8
Gitweb: http://git.kernel.org/tip/87db73aebf4fefaa3eade0a28f282a1511b8
Author: Ard Biesheuvel ard.biesheu...@linaro.org
AuthorDate: Fri, 7 Aug 2015 09:36:54 +0100
Committer:  Ingo Molnar mi...@kernel.org
CommitDate: Sat, 8 Aug 2015 10:37:38 +0200

efi: Add support for EFI_MEMORY_RO attribute introduced by UEFIv2.5

The UEFI spec v2.5 introduces a new memory attribute
EFI_MEMORY_RO, which is now the preferred attribute to convey
that the nature of the contents of such a region allows it to be
mapped read-only (i.e., it contains .text and .rodata only).

The specification of the existing EFI_MEMORY_WP attribute has been
updated to align more closely with its common use as a
cacheability attribute rather than a permission attribute.

Add the #define and add the attribute to the memory map dumping
routine.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
Signed-off-by: Matt Fleming matt.flem...@intel.com
Reviewed-by: Laszlo Ersek ler...@redhat.com
Cc: H. Peter Anvin h...@zytor.com
Cc: Thomas Gleixner t...@linutronix.de
Link: 
http://lkml.kernel.org/r/1438936621-5215-1-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar mi...@kernel.org
---
 drivers/firmware/efi/efi.c | 8 +---
 include/linux/efi.h| 1 +
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index d6144e3..d7a9160 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -588,16 +588,18 @@ char * __init efi_md_typeattr_format(char *buf, size_t 
size,
 
attr = md-attribute;
if (attr  ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
-EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
-EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
+EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
+EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
+EFI_MEMORY_RUNTIME))
snprintf(pos, size, |attr=0x%016llx],
 (unsigned long long)attr);
else
-   snprintf(pos, size, |%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s],
+   snprintf(pos, size, |%3s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s],
 attr  EFI_MEMORY_RUNTIME ? RUN : ,
 attr  EFI_MEMORY_XP  ? XP  : ,
 attr  EFI_MEMORY_RP  ? RP  : ,
 attr  EFI_MEMORY_WP  ? WP  : ,
+attr  EFI_MEMORY_RO  ? RO  : ,
 attr  EFI_MEMORY_UCE ? UCE : ,
 attr  EFI_MEMORY_WB  ? WB  : ,
 attr  EFI_MEMORY_WT  ? WT  : ,
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 85ef051..26ca9e2 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -99,6 +99,7 @@ typedef   struct {
 #define EFI_MEMORY_XP  ((u64)0x4000ULL)/* 
execute-protect */
 #define EFI_MEMORY_MORE_RELIABLE \
((u64)0x0001ULL)/* higher 
reliability */
+#define EFI_MEMORY_RO  ((u64)0x0002ULL)/* read-only */
 #define EFI_MEMORY_RUNTIME ((u64)0x8000ULL)/* range 
requires runtime mapping */
 #define EFI_MEMORY_DESCRIPTOR_VERSION  1
 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[tip:core/efi] efi: Use correct type for struct efi_memory_map:: phys_map

2015-10-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  44511fb9e55ada760822b0b0d7be9d150576f17f
Gitweb: http://git.kernel.org/tip/44511fb9e55ada760822b0b0d7be9d150576f17f
Author: Ard Biesheuvel 
AuthorDate: Fri, 23 Oct 2015 11:48:16 +0200
Committer:  Ingo Molnar 
CommitDate: Wed, 28 Oct 2015 12:28:06 +0100

efi: Use correct type for struct efi_memory_map::phys_map

We have been getting away with using a void* for the physical
address of the UEFI memory map, since, even on 32-bit platforms
with 64-bit physical addresses, no truncation takes place if the
memory map has been allocated by the firmware (which only uses
1:1 virtually addressable memory), which is usually the case.

However, commit:

  0f96a99dab36 ("efi: Add "efi_fake_mem" boot option")

adds code that clones and modifies the UEFI memory map, and the
clone may live above 4 GB on 32-bit platforms.

This means our use of void* for struct efi_memory_map::phys_map has
graduated from 'incorrect but working' to 'incorrect and
broken', and we need to fix it.

So redefine struct efi_memory_map::phys_map as phys_addr_t, and
get rid of a bunch of casts that are now unneeded.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: izumi.t...@jp.fujitsu.com
Cc: kamezawa.hir...@jp.fujitsu.com
Cc: linux-...@vger.kernel.org
Cc: matt.flem...@intel.com
Link: 
http://lkml.kernel.org/r/1445593697-1342-1-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/efi.c | 4 ++--
 arch/x86/platform/efi/efi.c | 4 ++--
 drivers/firmware/efi/efi.c  | 8 
 include/linux/efi.h | 2 +-
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 4b7df34..61eb1d1 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -208,7 +208,7 @@ void __init efi_init(void)
 
memblock_reserve(params.mmap & PAGE_MASK,
 PAGE_ALIGN(params.mmap_size + (params.mmap & 
~PAGE_MASK)));
-   memmap.phys_map = (void *)params.mmap;
+   memmap.phys_map = params.mmap;
memmap.map = early_memremap(params.mmap, params.mmap_size);
memmap.map_end = memmap.map + params.mmap_size;
memmap.desc_size = params.desc_size;
@@ -282,7 +282,7 @@ static int __init arm64_enable_runtime_services(void)
pr_info("Remapping and enabling EFI services.\n");
 
mapsize = memmap.map_end - memmap.map;
-   memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
+   memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
   mapsize);
if (!memmap.map) {
pr_err("Failed to remap EFI memory map\n");
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 3e1d09e..ad28540 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -194,7 +194,7 @@ static void __init do_add_efi_memmap(void)
 int __init efi_memblock_x86_reserve_range(void)
 {
struct efi_info *e = _params.efi_info;
-   unsigned long pmap;
+   phys_addr_t pmap;
 
if (efi_enabled(EFI_PARAVIRT))
return 0;
@@ -209,7 +209,7 @@ int __init efi_memblock_x86_reserve_range(void)
 #else
pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32));
 #endif
-   memmap.phys_map = (void *)pmap;
+   memmap.phys_map = pmap;
memmap.nr_map   = e->efi_memmap_size /
  e->efi_memdesc_size;
memmap.desc_size= e->efi_memdesc_size;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 31fc864..027ca21 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -254,7 +254,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;
-   void *p, *e;
+   phys_addr_t p, e;
 
if (!efi_enabled(EFI_MEMMAP)) {
pr_err_once("EFI_MEMMAP is not enabled.\n");
@@ -286,10 +286,10 @@ int __init efi_mem_desc_lookup(u64 phys_addr, 
efi_memory_desc_t *out_md)
 * So just always get our own virtual map on the CPU.
 *
 */
-   md = early_memremap((phys_addr_t)p, sizeof (*md));
+   md = early_memremap(p, sizeof (*md));
if (!md) {
-   pr_err_once("early_memremap(%p, %zu) failed.\n",
-   p, sizeof (*md));
+   pr_err_once("early_memremap(%pa, %zu) failed.\n",
+   , sizeof (*md));
return -ENOMEM;
}
 
diff --git a/include/linux/efi.h 

[tip:core/urgent] arm64/efi: Fix boot crash by not padding between EFI_MEMORY_RUNTIME regions

2015-10-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0ce3cc008ec04258b6a6314b09f1a6012810881a
Gitweb: http://git.kernel.org/tip/0ce3cc008ec04258b6a6314b09f1a6012810881a
Author: Ard Biesheuvel 
AuthorDate: Fri, 25 Sep 2015 23:02:19 +0100
Committer:  Ingo Molnar 
CommitDate: Thu, 1 Oct 2015 12:51:28 +0200

arm64/efi: Fix boot crash by not padding between EFI_MEMORY_RUNTIME regions

The new Properties Table feature introduced in UEFIv2.5 may
split memory regions that cover PE/COFF memory images into
separate code and data regions. Since these regions only differ
in the type (runtime code vs runtime data) and the permission
bits, but not in the memory type attributes (UC/WC/WT/WB), the
spec does not require them to be aligned to 64 KB.

Since the relative offset of PE/COFF .text and .data segments
cannot be changed on the fly, this means that we can no longer
pad out those regions to be mappable using 64 KB pages.
Unfortunately, there is no annotation in the UEFI memory map
that identifies data regions that were split off from a code
region, so we must apply this logic to all adjacent runtime
regions whose attributes only differ in the permission bits.

So instead of rounding each memory region to 64 KB alignment at
both ends, only round down regions that are not directly
preceded by another runtime region with the same type
attributes. Since the UEFI spec does not mandate that the memory
map be sorted, this means we also need to sort it first.

Note that this change will result in all EFI_MEMORY_RUNTIME
regions whose start addresses are not aligned to the OS page
size to be mapped with executable permissions (i.e., on kernels
compiled with 64 KB pages). However, since these mappings are
only active during the time that UEFI Runtime Services are being
invoked, the window for abuse is rather small.

Tested-by: Mark Salter 
Tested-by: Mark Rutland  [UEFI 2.4 only]
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Mark Salter 
Reviewed-by: Mark Rutland 
Cc:  # v4.0+
Cc: Catalin Marinas 
Cc: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Mike Galbraith 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-kernel@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1443218539-7610-3-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/efi.c |  3 +-
 drivers/firmware/efi/libstub/arm-stub.c | 88 +++--
 2 files changed, 75 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index e8ca6ea..13671a9 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -258,7 +258,8 @@ static bool __init efi_virtmap_init(void)
 */
if (!is_normal_ram(md))
prot = __pgprot(PROT_DEVICE_nGnRE);
-   else if (md->type == EFI_RUNTIME_SERVICES_CODE)
+   else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+!PAGE_ALIGNED(md->phys_addr))
prot = PAGE_KERNEL_EXEC;
else
prot = PAGE_KERNEL;
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index e29560e..950c87f 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -13,6 +13,7 @@
  */
 
 #include 
+#include 
 #include 
 
 #include "efistub.h"
@@ -305,6 +306,44 @@ fail:
  */
 #define EFI_RT_VIRTUAL_BASE0x4000
 
+static int cmp_mem_desc(const void *l, const void *r)
+{
+   const efi_memory_desc_t *left = l, *right = r;
+
+   return (left->phys_addr > right->phys_addr) ? 1 : -1;
+}
+
+/*
+ * Returns whether region @left ends exactly where region @right starts,
+ * or false if either argument is NULL.
+ */
+static bool regions_are_adjacent(efi_memory_desc_t *left,
+efi_memory_desc_t *right)
+{
+   u64 left_end;
+
+   if (left == NULL || right == NULL)
+   return false;
+
+   left_end = left->phys_addr + left->num_pages * EFI_PAGE_SIZE;
+
+   return left_end == right->phys_addr;
+}
+
+/*
+ * Returns whether region @left and region @right have compatible memory type
+ * mapping attributes, and are both EFI_MEMORY_RUNTIME regions.
+ */
+static bool regions_have_compatible_memory_type_attrs(efi_memory_desc_t *left,
+ efi_memory_desc_t *right)
+{
+   static const u64 mem_type_mask = EFI_MEMORY_WB | EFI_MEMORY_WT |
+EFI_MEMORY_WC | EFI_MEMORY_UC |
+

[tip:efi/core] efi/runtime-wrappers: Remove out of date comment regarding in_nmi()

2016-02-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  774846defceb16dcab2f0215cfc467f7c93f1c26
Gitweb: http://git.kernel.org/tip/774846defceb16dcab2f0215cfc467f7c93f1c26
Author: Ard Biesheuvel 
AuthorDate: Mon, 1 Feb 2016 22:06:59 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Feb 2016 11:31:04 +0100

efi/runtime-wrappers: Remove out of date comment regarding in_nmi()

This code is long gone, so remove the comment as well.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Denys Vlasenko 
Cc: H. Peter Anvin 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1454364428-494-6-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/runtime-wrappers.c | 26 --
 1 file changed, 26 deletions(-)

diff --git a/drivers/firmware/efi/runtime-wrappers.c 
b/drivers/firmware/efi/runtime-wrappers.c
index e9f2867..311f415 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -62,32 +62,6 @@
 static DEFINE_SPINLOCK(efi_runtime_lock);
 
 /*
- * Some runtime services calls can be reentrant under NMI, even if the table
- * above says they are not. (source: UEFI Specification v2.4A)
- *
- * Table 32. Functions that may be called after Machine Check, INIT and NMI
- * ++--+
- * | Function  | Called after Machine Check, INIT and NMI |
- * ++--+
- * | GetTime() | Yes, even if previously busy.|
- * | GetVariable() | Yes, even if previously busy |
- * | GetNextVariableName() | Yes, even if previously busy |
- * | QueryVariableInfo()   | Yes, even if previously busy |
- * | SetVariable() | Yes, even if previously busy |
- * | UpdateCapsule()   | Yes, even if previously busy |
- * | QueryCapsuleCapabilities()| Yes, even if previously busy  
   |
- * | ResetSystem() | Yes, even if previously busy |
- * ++--+
- *
- * In order to prevent deadlocks under NMI, the wrappers for these functions
- * may only grab the efi_runtime_lock or rtc_lock spinlocks if !efi_in_nmi().
- * However, not all of the services listed are reachable through NMI code 
paths,
- * so the the special handling as suggested by the UEFI spec is only 
implemented
- * for QueryVariableInfo() and SetVariable(), as these can be reached in NMI
- * context through efi_pstore_write().
- */
-
-/*
  * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
  * the EFI specification requires that callers of the time related runtime
  * functions serialize with other CMOS accesses in the kernel, as the EFI time


[tip:efi/core] efi: Remove redundant efi_set_variable_nonblocking () prototype

2016-02-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  70d2a3cf2f4ae2e93b7a661842d84c2b5132cee7
Gitweb: http://git.kernel.org/tip/70d2a3cf2f4ae2e93b7a661842d84c2b5132cee7
Author: Ard Biesheuvel 
AuthorDate: Mon, 1 Feb 2016 22:06:56 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Feb 2016 11:31:02 +0100

efi: Remove redundant efi_set_variable_nonblocking() prototype

There is no need for a separate nonblocking prototype definition
for the SetVariable() UEFI Runtime Service, since it is
identical to the blocking version.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Denys Vlasenko 
Cc: H. Peter Anvin 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1454364428-494-3-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 include/linux/efi.h | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 569b5a8..8706e0a 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -507,10 +507,6 @@ typedef efi_status_t efi_get_next_variable_t (unsigned 
long *name_size, efi_char
 typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t 
*vendor, 
 u32 attr, unsigned long data_size,
 void *data);
-typedef efi_status_t
-efi_set_variable_nonblocking_t(efi_char16_t *name, efi_guid_t *vendor,
-  u32 attr, unsigned long data_size, void *data);
-
 typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
 typedef void efi_reset_system_t (int reset_type, efi_status_t status,
 unsigned long data_size, efi_char16_t *data);
@@ -851,7 +847,7 @@ extern struct efi {
efi_get_variable_t *get_variable;
efi_get_next_variable_t *get_next_variable;
efi_set_variable_t *set_variable;
-   efi_set_variable_nonblocking_t *set_variable_nonblocking;
+   efi_set_variable_t *set_variable_nonblocking;
efi_query_variable_info_t *query_variable_info;
efi_update_capsule_t *update_capsule;
efi_query_capsule_caps_t *query_capsule_caps;
@@ -1091,7 +1087,7 @@ struct efivar_operations {
efi_get_variable_t *get_variable;
efi_get_next_variable_t *get_next_variable;
efi_set_variable_t *set_variable;
-   efi_set_variable_nonblocking_t *set_variable_nonblocking;
+   efi_set_variable_t *set_variable_nonblocking;
efi_query_variable_store_t *query_variable_store;
 };
 


[tip:efi/core] efi: Add nonblocking option to efi_query_variable_store()

2016-02-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  ca0e30dcaa53a3fcb2dfdf74252d30bc40603eea
Gitweb: http://git.kernel.org/tip/ca0e30dcaa53a3fcb2dfdf74252d30bc40603eea
Author: Ard Biesheuvel 
AuthorDate: Mon, 1 Feb 2016 22:06:58 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Feb 2016 11:31:04 +0100

efi: Add nonblocking option to efi_query_variable_store()

The function efi_query_variable_store() may be invoked by
efivar_entry_set_nonblocking(), which itself takes care to only
call a non-blocking version of the SetVariable() runtime
wrapper. However, efi_query_variable_store() may call the
SetVariable() wrapper directly, as well as the wrapper for
QueryVariableInfo(), both of which could deadlock in the same
way we are trying to prevent by calling
efivar_entry_set_nonblocking() in the first place.

So instead, modify efi_query_variable_store() to use the
non-blocking variants of QueryVariableInfo() (and give up rather
than free up space if the available space is below
EFI_MIN_RESERVE) if invoked with the 'nonblocking' argument set
to true.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Denys Vlasenko 
Cc: H. Peter Anvin 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1454364428-494-5-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/quirks.c | 33 -
 drivers/firmware/efi/vars.c| 16 ++--
 include/linux/efi.h| 12 +---
 3 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 4535046..2326bf5 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -57,13 +57,41 @@ void efi_delete_dummy_variable(void)
 }
 
 /*
+ * In the nonblocking case we do not attempt to perform garbage
+ * collection if we do not have enough free space. Rather, we do the
+ * bare minimum check and give up immediately if the available space
+ * is below EFI_MIN_RESERVE.
+ *
+ * This function is intended to be small and simple because it is
+ * invoked from crash handler paths.
+ */
+static efi_status_t
+query_variable_store_nonblocking(u32 attributes, unsigned long size)
+{
+   efi_status_t status;
+   u64 storage_size, remaining_size, max_size;
+
+   status = efi.query_variable_info_nonblocking(attributes, _size,
+_size,
+_size);
+   if (status != EFI_SUCCESS)
+   return status;
+
+   if (remaining_size - size < EFI_MIN_RESERVE)
+   return EFI_OUT_OF_RESOURCES;
+
+   return EFI_SUCCESS;
+}
+
+/*
  * Some firmware implementations refuse to boot if there's insufficient space
  * in the variable store. Ensure that we never use more than a safe limit.
  *
  * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
  * store.
  */
-efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+efi_status_t efi_query_variable_store(u32 attributes, unsigned long size,
+ bool nonblocking)
 {
efi_status_t status;
u64 storage_size, remaining_size, max_size;
@@ -71,6 +99,9 @@ efi_status_t efi_query_variable_store(u32 attributes, 
unsigned long size)
if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
return 0;
 
+   if (nonblocking)
+   return query_variable_store_nonblocking(attributes, size);
+
status = efi.query_variable_info(attributes, _size,
 _size, _size);
if (status != EFI_SUCCESS)
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index 70a0fb1..d2a4962 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -234,7 +234,18 @@ check_var_size(u32 attributes, unsigned long size)
if (!fops->query_variable_store)
return EFI_UNSUPPORTED;
 
-   return fops->query_variable_store(attributes, size);
+   return fops->query_variable_store(attributes, size, false);
+}
+
+static efi_status_t
+check_var_size_nonblocking(u32 attributes, unsigned long size)
+{
+   const struct efivar_operations *fops = __efivars->ops;
+
+   if (!fops->query_variable_store)
+   return EFI_UNSUPPORTED;
+
+   return fops->query_variable_store(attributes, size, true);
 }
 
 static int efi_status_to_err(efi_status_t status)
@@ -615,7 +626,8 @@ efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t 
vendor,
if (!spin_trylock_irqsave(&__efivars->lock, flags))
return 

[tip:efi/core] efi: Runtime-wrapper: Get rid of the rtc_lock spinlock

2016-02-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  1bb6936473c07b5a7c8daced1000893b7145bb14
Gitweb: http://git.kernel.org/tip/1bb6936473c07b5a7c8daced1000893b7145bb14
Author: Ard Biesheuvel 
AuthorDate: Mon, 1 Feb 2016 22:07:00 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Feb 2016 11:31:05 +0100

efi: Runtime-wrapper: Get rid of the rtc_lock spinlock

The rtc_lock spinlock aims to serialize access to the CMOS RTC
between the UEFI firmware and the kernel drivers that use it
directly. However, x86 is the only arch that performs such
direct accesses, and that never uses the time related UEFI
runtime services. Since no other UEFI enlightened architectures
have a legcay CMOS RTC anyway, we can remove the rtc_lock
spinlock entirely.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Denys Vlasenko 
Cc: H. Peter Anvin 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1454364428-494-7-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/runtime-wrappers.c | 32 
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/drivers/firmware/efi/runtime-wrappers.c 
b/drivers/firmware/efi/runtime-wrappers.c
index 311f415..7b8b2f2 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -61,24 +61,14 @@
  */
 static DEFINE_SPINLOCK(efi_runtime_lock);
 
-/*
- * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
- * the EFI specification requires that callers of the time related runtime
- * functions serialize with other CMOS accesses in the kernel, as the EFI time
- * functions may choose to also use the legacy CMOS RTC.
- */
-__weak DEFINE_SPINLOCK(rtc_lock);
-
 static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_lock, flags);
-   spin_lock(_runtime_lock);
+   spin_lock_irqsave(_runtime_lock, flags);
status = efi_call_virt(get_time, tm, tc);
-   spin_unlock(_runtime_lock);
-   spin_unlock_irqrestore(_lock, flags);
+   spin_unlock_irqrestore(_runtime_lock, flags);
return status;
 }
 
@@ -87,11 +77,9 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_lock, flags);
-   spin_lock(_runtime_lock);
+   spin_lock_irqsave(_runtime_lock, flags);
status = efi_call_virt(set_time, tm);
-   spin_unlock(_runtime_lock);
-   spin_unlock_irqrestore(_lock, flags);
+   spin_unlock_irqrestore(_runtime_lock, flags);
return status;
 }
 
@@ -102,11 +90,9 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t 
*enabled,
unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_lock, flags);
-   spin_lock(_runtime_lock);
+   spin_lock_irqsave(_runtime_lock, flags);
status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
-   spin_unlock(_runtime_lock);
-   spin_unlock_irqrestore(_lock, flags);
+   spin_unlock_irqrestore(_runtime_lock, flags);
return status;
 }
 
@@ -115,11 +101,9 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t 
enabled, efi_time_t *tm)
unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_lock, flags);
-   spin_lock(_runtime_lock);
+   spin_lock_irqsave(_runtime_lock, flags);
status = efi_call_virt(set_wakeup_time, enabled, tm);
-   spin_unlock(_runtime_lock);
-   spin_unlock_irqrestore(_lock, flags);
+   spin_unlock_irqrestore(_runtime_lock, flags);
return status;
 }
 


[tip:efi/core] efi: Expose non-blocking set_variable() wrapper to efivars

2016-02-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9c6672ac9c91f7eb1ec436be1442b8c26d098e55
Gitweb: http://git.kernel.org/tip/9c6672ac9c91f7eb1ec436be1442b8c26d098e55
Author: Ard Biesheuvel 
AuthorDate: Mon, 1 Feb 2016 22:06:55 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Feb 2016 11:31:01 +0100

efi: Expose non-blocking set_variable() wrapper to efivars

Commit 6d80dba1c9fe ("efi: Provide a non-blocking SetVariable()
operation") implemented a non-blocking alternative for the UEFI
SetVariable() invocation performed by efivars, since it may
occur in atomic context. However, this version of the function
was never exposed via the efivars struct, so the non-blocking
versions was not actually callable. Fix that.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Denys Vlasenko 
Cc: H. Peter Anvin 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 6d80dba1c9fe ("efi: Provide a non-blocking SetVariable() operation")
Link: 
http://lkml.kernel.org/r/1454364428-494-2-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 9b815c8..20451c2 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -182,6 +182,7 @@ static int generic_ops_register(void)
 {
generic_ops.get_variable = efi.get_variable;
generic_ops.set_variable = efi.set_variable;
+   generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
generic_ops.get_next_variable = efi.get_next_variable;
generic_ops.query_variable_store = efi_query_variable_store;
 


[tip:efi/core] efi/runtime-wrappers: Add a nonblocking version of QueryVariableInfo()

2016-02-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  d3cac1f83c631b9fe5edaebcba49f6989bfff089
Gitweb: http://git.kernel.org/tip/d3cac1f83c631b9fe5edaebcba49f6989bfff089
Author: Ard Biesheuvel 
AuthorDate: Mon, 1 Feb 2016 22:06:57 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Feb 2016 11:31:03 +0100

efi/runtime-wrappers: Add a nonblocking version of QueryVariableInfo()

This introduces a new runtime wrapper for the
QueryVariableInfo() UEFI Runtime Service, which gives up
immediately rather than spins on failure to grab the efi_runtime
spinlock.

This is required in the non-blocking path of the efi-pstore
code.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Brian Gerst 
Cc: Denys Vlasenko 
Cc: H. Peter Anvin 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1454364428-494-4-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/runtime-wrappers.c | 22 ++
 include/linux/efi.h |  1 +
 2 files changed, 23 insertions(+)

diff --git a/drivers/firmware/efi/runtime-wrappers.c 
b/drivers/firmware/efi/runtime-wrappers.c
index 228bbf9..e9f2867 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -230,6 +230,27 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
return status;
 }
 
+static efi_status_t
+virt_efi_query_variable_info_nonblocking(u32 attr,
+u64 *storage_space,
+u64 *remaining_space,
+u64 *max_variable_size)
+{
+   unsigned long flags;
+   efi_status_t status;
+
+   if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+   return EFI_UNSUPPORTED;
+
+   if (!spin_trylock_irqsave(_runtime_lock, flags))
+   return EFI_NOT_READY;
+
+   status = efi_call_virt(query_variable_info, attr, storage_space,
+  remaining_space, max_variable_size);
+   spin_unlock_irqrestore(_runtime_lock, flags);
+   return status;
+}
+
 static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
 {
unsigned long flags;
@@ -300,6 +321,7 @@ void efi_native_runtime_setup(void)
efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
efi.reset_system = virt_efi_reset_system;
efi.query_variable_info = virt_efi_query_variable_info;
+   efi.query_variable_info_nonblocking = 
virt_efi_query_variable_info_nonblocking;
efi.update_capsule = virt_efi_update_capsule;
efi.query_capsule_caps = virt_efi_query_capsule_caps;
 }
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 8706e0a..ad1e177 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -849,6 +849,7 @@ extern struct efi {
efi_set_variable_t *set_variable;
efi_set_variable_t *set_variable_nonblocking;
efi_query_variable_info_t *query_variable_info;
+   efi_query_variable_info_t *query_variable_info_nonblocking;
efi_update_capsule_t *update_capsule;
efi_query_capsule_caps_t *query_capsule_caps;
efi_get_next_high_mono_count_t *get_next_high_mono_count;


[tip:efi/core] efi/arm64: Check for h/w support before booting a >4 KB granular kernel

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  42b55734030c1f724d5f47aeb872e2cccd650d79
Gitweb: http://git.kernel.org/tip/42b55734030c1f724d5f47aeb872e2cccd650d79
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:36:02 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:27 +0100

efi/arm64: Check for h/w support before booting a >4 KB granular kernel

A kernel built with support for a page size that is not supported by the
hardware it runs on cannot boot to a state where it can inform the user
about the failure.

If we happen to be booting via UEFI, we can fail gracefully so check
if the currently configured page size is supported by the hardware before
entering the kernel proper. Note that UEFI mandates support for 4 KB pages,
so in that case, no check is needed.

Tested-by: Suzuki K Poulose 
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Jeremy Linton 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-10-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm64-stub.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index 9e03427..047fc34 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -12,6 +12,26 @@
 #include 
 #include 
 #include 
+#include 
+
+efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
+{
+   u64 tg;
+
+   /* UEFI mandates support for 4 KB granularity, no need to check */
+   if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
+   return EFI_SUCCESS;
+
+   tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
+   if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
+   if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+   pr_efi_err(sys_table_arg, "This 64 KB granular kernel 
is not supported by your CPU\n");
+   else
+   pr_efi_err(sys_table_arg, "This 16 KB granular kernel 
is not supported by your CPU\n");
+   return EFI_UNSUPPORTED;
+   }
+   return EFI_SUCCESS;
+}
 
 efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
 unsigned long *image_addr,


[tip:efi/core] efi/arm-init: Use read-only early mappings

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  2eec5dedf770dc85c1fdf6b86873165e61bb1fff
Gitweb: http://git.kernel.org/tip/2eec5dedf770dc85c1fdf6b86873165e61bb1fff
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:36:00 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:27 +0100

efi/arm-init: Use read-only early mappings

The early mappings of the EFI system table contents and the UEFI memory
map are read-only from the OS point of view. So map them read-only to
protect them from inadvertent modification.

Tested-by: Mark Rutland 
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-8-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 9e15d57..aa1f743 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -61,8 +61,8 @@ static int __init uefi_init(void)
char vendor[100] = "unknown";
int i, retval;
 
-   efi.systab = early_memremap(efi_system_table,
-   sizeof(efi_system_table_t));
+   efi.systab = early_memremap_ro(efi_system_table,
+  sizeof(efi_system_table_t));
if (efi.systab == NULL) {
pr_warn("Unable to map EFI system table.\n");
return -ENOMEM;
@@ -86,8 +86,8 @@ static int __init uefi_init(void)
efi.systab->hdr.revision & 0x);
 
/* Show what we know for posterity */
-   c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
-sizeof(vendor) * sizeof(efi_char16_t));
+   c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
+   sizeof(vendor) * sizeof(efi_char16_t));
if (c16) {
for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
vendor[i] = c16[i];
@@ -100,8 +100,8 @@ static int __init uefi_init(void)
efi.systab->hdr.revision & 0x, vendor);
 
table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
-   config_tables = early_memremap(efi_to_phys(efi.systab->tables),
-  table_size);
+   config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
+ table_size);
if (config_tables == NULL) {
pr_warn("Unable to map EFI config table array.\n");
retval = -ENOMEM;
@@ -185,7 +185,7 @@ void __init efi_init(void)
efi_system_table = params.system_table;
 
memmap.phys_map = params.mmap;
-   memmap.map = early_memremap(params.mmap, params.mmap_size);
+   memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
if (memmap.map == NULL) {
/*
* If we are booting via UEFI, the UEFI memory map is the only


[tip:efi/core] efi/arm*: Perform hardware compatibility check

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b9d6769b5678dbd6cb328d20716561d35b2b1510
Gitweb: http://git.kernel.org/tip/b9d6769b5678dbd6cb328d20716561d35b2b1510
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:36:03 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:27 +0100

efi/arm*: Perform hardware compatibility check

Before proceeding with relocating the kernel and parsing the command line,
insert a call to check_platform_features() to allow an arch specific check
to be performed whether the current kernel can execute on the current
hardware.

Tested-by: Suzuki K Poulose 
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Jeremy Linton 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-11-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 4 
 drivers/firmware/efi/libstub/efistub.h  | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 3397902..6086a87 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -190,6 +190,10 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 
pr_efi(sys_table, "Booting Linux Kernel...\n");
 
+   status = check_platform_features(sys_table);
+   if (status != EFI_SUCCESS)
+   goto fail;
+
/*
 * Get a handle to the loaded image protocol.  This is used to get
 * information about the running image, such as size and the command
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index 86ff7bf..981c603 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -53,4 +53,6 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned 
long map_size,
 unsigned long desc_size, efi_memory_desc_t *runtime_map,
 int *count);
 
+efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
+
 #endif


[tip:efi/core] efi/arm: Check for LPAE support before booting a LPAE kernel

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  2ec0f0a3a4bfab90eda8b81656f62e07abf2321f
Gitweb: http://git.kernel.org/tip/2ec0f0a3a4bfab90eda8b81656f62e07abf2321f
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:36:01 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:27 +0100

efi/arm: Check for LPAE support before booting a LPAE kernel

A kernel built with support for LPAE cannot boot to a state where it
can inform the user about if it has to fail due to missing LPAE support
in the hardware.

If we happen to be booting via UEFI, we can fail gracefully so check
for LPAE support in the hardware on CONFIG_ARM_LPAE builds before
entering the kernel proper.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Jeremy Linton 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-9-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index 495ebd6..6f42be4 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -9,6 +9,23 @@
 #include 
 #include 
 
+efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
+{
+   int block;
+
+   /* non-LPAE kernels can run anywhere */
+   if (!IS_ENABLED(CONFIG_ARM_LPAE))
+   return EFI_SUCCESS;
+
+   /* LPAE kernels need compatible hardware */
+   block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
+   if (block < 5) {
+   pr_efi_err(sys_table_arg, "This LPAE kernel is not supported by 
your CPU\n");
+   return EFI_UNSUPPORTED;
+   }
+   return EFI_SUCCESS;
+}
+
 efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 unsigned long *image_addr,
 unsigned long *image_size,


[tip:efi/core] arm64/vmlinux.lds.S: Handle .init.rodata.xxx and .init.bss sections

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  1ce99bf45306ba889faadced6baabebf7770c546
Gitweb: http://git.kernel.org/tip/1ce99bf45306ba889faadced6baabebf7770c546
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:35:58 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:26 +0100

arm64/vmlinux.lds.S: Handle .init.rodata.xxx and .init.bss sections

The EFI stub is typically built into the decompressor (x86, ARM) so none
of its symbols are annotated as __init. However, on arm64, the stub is
linked into the kernel proper, and the code is __init annotated at the
section level by prepending all names of SHF_ALLOC sections with '.init'.

This results in section names like .init.rodata.str1.8 (for string literals)
and .init.bss (which is tiny), both of which can be moved into the .init.data
output section.

Tested-by: Mark Rutland 
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Will Deacon 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-6-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/vmlinux.lds.S | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index e3928f5..cbf4db4 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -134,6 +134,7 @@ SECTIONS
CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS
+   *(.init.rodata.* .init.bss) /* from the EFI stub */
}
.exit.data : {
ARM_EXIT_KEEP(EXIT_DATA)


[tip:efi/core] efi/arm64: Drop __init annotation from handle_kernel_image()

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  dae31fd2b74c35cc84128733bc210bf6b26ae408
Gitweb: http://git.kernel.org/tip/dae31fd2b74c35cc84128733bc210bf6b26ae408
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:35:57 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:26 +0100

efi/arm64: Drop __init annotation from handle_kernel_image()

After moving arm64-stub.c to libstub/, all of its sections are emitted
as .init.xxx sections automatically, and the __init annotation of
handle_kernel_image() causes it to end up in .init.init.text, which is
not recognized as an __init section by the linker scripts. So drop the
annotation.

Tested-by: Mark Rutland 
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Will Deacon 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-5-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm64-stub.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index 78dfbd3..9e03427 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -13,13 +13,13 @@
 #include 
 #include 
 
-efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
-   unsigned long *image_addr,
-   unsigned long *image_size,
-   unsigned long *reserve_addr,
-   unsigned long *reserve_size,
-   unsigned long dram_base,
-   efi_loaded_image_t *image)
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
+unsigned long *image_addr,
+unsigned long *image_size,
+unsigned long *reserve_addr,
+unsigned long *reserve_size,
+unsigned long dram_base,
+efi_loaded_image_t *image)
 {
efi_status_t status;
unsigned long kernel_size, kernel_memsize = 0;


[tip:efi/core] efi/runtime-wrappers: Run UEFI Runtime Services with interrupts enabled

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  fe3244945c47161e2486412d6412c87ba279305d
Gitweb: http://git.kernel.org/tip/fe3244945c47161e2486412d6412c87ba279305d
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:35:55 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:25 +0100

efi/runtime-wrappers: Run UEFI Runtime Services with interrupts enabled

The UEFI spec allows Runtime Services to be invoked with interrupts
enabled. The only reason we were disabling interrupts was to prevent
recursive calls into the services on the same CPU, which will lead to
deadlock. However, the only context where such invocations may occur
legally is from efi-pstore via efivars, and that code has been updated
to call a non-blocking alternative when invoked from a non-interruptible
context.

So instead, update the ordinary, blocking UEFI Runtime Services wrappers
to execute with interrupts enabled. This aims to prevent excessive interrupt
latencies on uniprocessor platforms with slow variable stores.

Note that other OSes such as Windows call UEFI Runtime Services with
interrupts enabled as well.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Andy Lutomirski 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-3-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/runtime-wrappers.c | 71 +
 1 file changed, 28 insertions(+), 43 deletions(-)

diff --git a/drivers/firmware/efi/runtime-wrappers.c 
b/drivers/firmware/efi/runtime-wrappers.c
index 7b8b2f2..de69530 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -63,23 +63,21 @@ static DEFINE_SPINLOCK(efi_runtime_lock);
 
 static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
-   unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_runtime_lock, flags);
+   spin_lock(_runtime_lock);
status = efi_call_virt(get_time, tm, tc);
-   spin_unlock_irqrestore(_runtime_lock, flags);
+   spin_unlock(_runtime_lock);
return status;
 }
 
 static efi_status_t virt_efi_set_time(efi_time_t *tm)
 {
-   unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_runtime_lock, flags);
+   spin_lock(_runtime_lock);
status = efi_call_virt(set_time, tm);
-   spin_unlock_irqrestore(_runtime_lock, flags);
+   spin_unlock(_runtime_lock);
return status;
 }
 
@@ -87,23 +85,21 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t 
*enabled,
 efi_bool_t *pending,
 efi_time_t *tm)
 {
-   unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_runtime_lock, flags);
+   spin_lock(_runtime_lock);
status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
-   spin_unlock_irqrestore(_runtime_lock, flags);
+   spin_unlock(_runtime_lock);
return status;
 }
 
 static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t 
*tm)
 {
-   unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_runtime_lock, flags);
+   spin_lock(_runtime_lock);
status = efi_call_virt(set_wakeup_time, enabled, tm);
-   spin_unlock_irqrestore(_runtime_lock, flags);
+   spin_unlock(_runtime_lock);
return status;
 }
 
@@ -113,13 +109,12 @@ static efi_status_t virt_efi_get_variable(efi_char16_t 
*name,
  unsigned long *data_size,
  void *data)
 {
-   unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_runtime_lock, flags);
+   spin_lock(_runtime_lock);
status = efi_call_virt(get_variable, name, vendor, attr, data_size,
   data);
-   spin_unlock_irqrestore(_runtime_lock, flags);
+   spin_unlock(_runtime_lock);
return status;
 }
 
@@ -127,12 +122,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned 
long *name_size,
   efi_char16_t *name,
   efi_guid_t *vendor)
 {
-   unsigned long flags;
efi_status_t status;
 
-   spin_lock_irqsave(_runtime_lock, flags);
+   spin_lock(_runtime_lock);
status = efi_call_virt(get_next_variable, name_size, name, vendor);
-   spin_unlock_irqrestore(_runtime_lock, flags);
+   spin_unlock(_runtime_lock);
return status;
 }
 
@@ -142,13 +136,12 @@ static efi_status_t 

[tip:efi/core] efi/efistub: Prevent __init annotations from being used

2016-02-23 Thread tip-bot for Ard Biesheuvel
Commit-ID:  07e83dbb75865b016f6493c119a30aac7c25051a
Gitweb: http://git.kernel.org/tip/07e83dbb75865b016f6493c119a30aac7c25051a
Author: Ard Biesheuvel 
AuthorDate: Wed, 17 Feb 2016 12:35:59 +
Committer:  Ingo Molnar 
CommitDate: Mon, 22 Feb 2016 08:26:26 +0100

efi/efistub: Prevent __init annotations from being used

__init annotations should not be used in the EFI stub, since the code is
either included in the decompressor (x86, ARM) where they have no effect,
or the whole stub is __init annotated at the section level (arm64), by
renaming the sections.

In the second case the __init annotations will be redundant, and will
result in section names like .init.init.text, and our linker script does
not expect that.

So un-#define __init so that its inadvertent use will force a build error.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1455712566-16727-7-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efistub.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index 6b6548f..86ff7bf 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -5,6 +5,16 @@
 /* error code which can't be mistaken for valid address */
 #define EFI_ERROR  (~0UL)
 
+/*
+ * __init annotations should not be used in the EFI stub, since the code is
+ * either included in the decompressor (x86, ARM) where they have no effect,
+ * or the whole stub is __init annotated at the section level (arm64), by
+ * renaming the sections, in which case the __init annotation will be
+ * redundant, and will result in section names like .init.init.text, and our
+ * linker script does not expect that.
+ */
+#undef __init
+
 void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,


[tip:efi/core] efifb: Enable the efi-framebuffer platform driver for ARM and arm64

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9822504c1fa5c557ea8776765f03fd16eb4de4c9
Gitweb: http://git.kernel.org/tip/9822504c1fa5c557ea8776765f03fd16eb4de4c9
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:56 +0100
Committer:  Ingo Molnar 
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().

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-25-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 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(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 25f8b11..b45fe39 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -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
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index fa09886..79dc8c2 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -59,6 +59,10 @@ int efi_create_mapping(struct mm_struct *mm, 
efi_memory_desc_t *md);
 #define alloc_screen_info(x...)_info
 #define free_screen_info(x...)
 
+static inline void efifb_setup_from_dmi(struct screen_info *si, const char 
*opt)
+{
+}
+
 #define EFI_ALLOC_ALIGNSZ_64K
 
 /*
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 983280e..e5a391a 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -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


[tip:efi/core] efifb: Use builtin_platform_driver and drop unused includes

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  07ea7ec5df3ee4a9fedb3d81dc69c2f8d07d44c0
Gitweb: http://git.kernel.org/tip/07ea7ec5df3ee4a9fedb3d81dc69c2f8d07d44c0
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:51 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Peter Jones 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-20-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index dd59436..f4c045c 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -6,15 +6,12 @@
  *
  */
 
-#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 
@@ -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);


[tip:efi/core] efi/arm*: Wire up 'struct screen_info' to efi-framebuffer platform device

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e3271c96ca7d01957b03b5f1e2bdc00e08fd7160
Gitweb: http://git.kernel.org/tip/e3271c96ca7d01957b03b5f1e2bdc00e08fd7160
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:55 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-24-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index ac95dd8..7a3318d 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -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,
+  _info, sizeof(screen_info));
+   return PTR_ERR_OR_ZERO(pd);
+}
+subsys_initcall(register_gop_device);


[tip:efi/core] efi/arm/libstub: Make screen_info accessible to the UEFI stub

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  801820bee9bccb7c156af2b95c7208f428a06ae7
Gitweb: http://git.kernel.org/tip/801820bee9bccb7c156af2b95c7208f428a06ae7
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:53 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-22-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 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(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index dc30d89..25f8b11 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -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
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 2c4bea3..7d4e285 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -883,7 +883,8 @@ static void __init request_standard_resources(const struct 
machine_desc *mdesc)
request_resource(_resource, );
 }
 
-#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,
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 909d974..ac95dd8 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -11,12 +11,15 @@
  *
  */
 
+#define pr_fmt(fmt)"efi: " fmt
+
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -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, _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)));
}
+
+   

[tip:efi/core] efi/arm*/libstub: Wire up GOP protocol to 'struct screen_info'

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f0827e18a7a1da574ba8201a8b18f63778451aae
Gitweb: http://git.kernel.org/tip/f0827e18a7a1da574ba8201a8b18f63778451aae
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:54 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-23-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 1286325..993aa56 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -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,
+   _proto, NULL, , 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, _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, _size,
 _addr,
 _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;


[tip:efi/core] efi: Get rid of the EFI_SYSTEM_TABLES status bit

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c5b591e96db9d99d0126acf93f24e1fb8b368343
Gitweb: http://git.kernel.org/tip/c5b591e96db9d99d0126acf93f24e1fb8b368343
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:33 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Leif Lindholm 
Cc: Luck, Tony 
Cc: Mark Rutland 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-2-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 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(-)

diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 300dac3..bf0865c 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -531,8 +531,6 @@ efi_init (void)
   efi.systab->hdr.revision >> 16,
   efi.systab->hdr.revision & 0x, vendor);
 
-   set_bit(EFI_SYSTEM_TABLES, );
-
palo_phys  = EFI_INVALID_TABLE_ADDR;
 
if (efi_config_init(arch_tables) != 0)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 994a7df8..df393ea 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -352,8 +352,6 @@ static int __init efi_systab_init(void *phys)
   efi.systab->hdr.revision >> 16,
   efi.systab->hdr.revision & 0x);
 
-   set_bit(EFI_SYSTEM_TABLES, );
-
return 0;
 }
 
diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 6ae21e4..16c7d2a 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -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, );
 
if (!efi_virtmap_init()) {
pr_err("No UEFI virtual mapping was installed -- runtime 
services will not be available\n");
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 1626474..1545098 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -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? */


[tip:efi/core] efi/arm-init: Reserve rather than unmap the memory map for ARM as well

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  249f7632162980b286f30166436471f8ba81fc1e
Gitweb: http://git.kernel.org/tip/249f7632162980b286f30166436471f8ba81fc1e
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:07:02 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Leif Lindholm 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-31-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 17 +++--
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 7a3318d..ef90f0c 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -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();
 }


[tip:efi/core] ARM/efi: Apply strict permissions for UEFI Runtime Services regions

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9fc68b717c24a215a32c1b4e05b30433cafb2599
Gitweb: http://git.kernel.org/tip/9fc68b717c24a215a32c1b4e05b30433cafb2599
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:42 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Catalin Marinas 
Cc: Leif Lindholm 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Russell King 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-11-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/arm/include/asm/efi.h |  1 +
 arch/arm/kernel/efi.c  | 41 +
 2 files changed, 42 insertions(+)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index e0eea72..b0c341d 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -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, ...)  \
 ({ \
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
index ff8a9d8..9f43ba0 100644
--- a/arch/arm/kernel/efi.c
+++ b/arch/arm/kernel/efi.c
@@ -11,6 +11,41 @@
 #include 
 #include 
 
+static int __init set_permissions(pte_t *ptep, pgtable_t token,
+ unsigned long addr, void *data)
+{
+   efi_memory_desc_t *md = data;
+   pte_t pte = *ptep;
+
+   if (md->attribute & EFI_MEMORY_RO)
+   pte = set_pte_bit(pte, __pgprot(L_PTE_RDONLY));
+   if (md->attribute & EFI_MEMORY_XP)
+   pte = set_pte_bit(pte, __pgprot(L_PTE_XN));
+   set_pte_ext(ptep, pte, PTE_EXT_NG);
+   return 0;
+}
+
+int __init efi_set_mapping_permissions(struct mm_struct *mm,
+  efi_memory_desc_t *md)
+{
+   unsigned long base, size;
+
+   base = md->virt_addr;
+   size = md->num_pages << EFI_PAGE_SHIFT;
+
+   /*
+* We can only use apply_to_page_range() if we can guarantee that the
+* entire region was mapped using pages. This should be the case if the
+* region does not cover any naturally aligned SECTION_SIZE sized
+* blocks.
+*/
+   if (round_down(base + size, SECTION_SIZE) <
+   round_up(base, SECTION_SIZE) + SECTION_SIZE)
+   return apply_to_page_range(mm, base, size, set_permissions, md);
+
+   return 0;
+}
+
 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
 {
struct map_desc desc = {
@@ -34,5 +69,11 @@ int __init efi_create_mapping(struct mm_struct *mm, 
efi_memory_desc_t *md)
desc.type = MT_DEVICE;
 
create_mapping_late(mm, , true);
+
+   /*
+* If stricter permissions were specified, apply them now.
+*/
+   if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))
+   return efi_set_mapping_permissions(mm, md);
return 0;
 }


[tip:efi/core] efi: Add support for the EFI_MEMORY_ATTRIBUTES_TABLE config table

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  a604af075a3226adaff84b7026876f0c6dfe9f52
Gitweb: http://git.kernel.org/tip/a604af075a3226adaff84b7026876f0c6dfe9f52
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:44 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Catalin Marinas 
Cc: Leif Lindholm 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-13-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c |  2 ++
 include/linux/efi.h| 13 +
 2 files changed, 15 insertions(+)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index f7d36c6..583e647 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -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_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", },
{EFI_PROPERTIES_TABLE_GUID, "PROP", _table},
+   {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", _attr_table},
{NULL_GUID, NULL, NULL},
 };
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index c2c0da4..81af5fe 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -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;


[tip:efi/core] efi: Implement generic support for the Memory Attributes table

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  10f0d2f57705350bbbe5f28e9292ae3905823c3c
Gitweb: http://git.kernel.org/tip/10f0d2f57705350bbbe5f28e9292ae3905823c3c
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:45 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
[ Trim pr_*() strings to 80 cols and use EFI consistently. ]
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Catalin Marinas 
Cc: Leif Lindholm 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-14-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/Makefile  |   2 +-
 drivers/firmware/efi/memattr.c | 182 +
 include/linux/efi.h|  13 +++
 3 files changed, 196 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 62e654f..d5be623 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -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
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
new file mode 100644
index 000..236004b
--- /dev/null
+++ b/drivers/firmware/efi/memattr.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 Linaro Ltd. 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt)"efi: memattr: " fmt
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static int __initdata tbl_size;
+
+/*
+ * Reserve the memory associated with the Memory Attributes configuration
+ * table, if it exists.
+ */
+int __init efi_memattr_init(void)
+{
+   efi_memory_attributes_table_t *tbl;
+
+   if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR)
+   return 0;
+
+   tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl));
+   if (!tbl) {
+   pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
+  efi.mem_attr_table);
+   return -ENOMEM;
+   }
+
+   if (tbl->version > 1) {
+   pr_warn("Unexpected EFI Memory Attributes table version %d\n",
+   tbl->version);
+   goto unmap;
+   }
+
+   tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
+   memblock_reserve(efi.mem_attr_table, tbl_size);
+
+unmap:
+   early_memunmap(tbl, sizeof(*tbl));
+   return 0;
+}
+
+/*
+ * Returns a copy @out of the UEFI memory descriptor @in if it is covered
+ * entirely by a UEFI memory map entry with matching attributes. The virtual
+ * address of @out is set according to the matching entry that was found.
+ */
+static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out)
+{
+   u64 in_paddr = in->phys_addr;
+   u64 in_size = in->num_pages << EFI_PAGE_SHIFT;
+   efi_memory_desc_t *md;
+
+   *out = *in;
+
+   if (in->type != EFI_RUNTIME_SERVICES_CODE &&
+   in->type != EFI_RUNTIME_SERVICES_DATA) {
+   pr_warn("Entry type should be RuntimeServiceCode/Data\n");
+   return false;
+   }
+
+   if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) {
+   pr_warn("Entry attributes invalid: RO and XP bits both 
cleared\n");
+   return false;
+   }
+
+   if (PAGE_SIZE > EFI_PAGE_SIZE &&
+   (!PAGE_ALIGNED(in->phys_addr) ||
+!PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) {
+   /*
+* Since 

[tip:efi/core] arm64/efi: Apply strict permissions to UEFI Runtime Services regions

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  1fd55a9a09b0293af95ab4299b108f030fef4464
Gitweb: http://git.kernel.org/tip/1fd55a9a09b0293af95ab4299b108f030fef4464
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:43 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Catalin Marinas 
Cc: Leif Lindholm 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-12-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/efi.c | 54 -
 1 file changed, 40 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index b6abc85..33a6da1 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -17,22 +17,48 @@
 
 #include 
 
-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,


[tip:efi/core] efi: Check EFI_MEMORY_DESCRIPTOR version explicitly

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0d054ad96e97dcd8966e9333eabcc7a466672f70
Gitweb: http://git.kernel.org/tip/0d054ad96e97dcd8966e9333eabcc7a466672f70
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:40 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-9-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/efi.c | 4 
 drivers/firmware/efi/arm-init.c | 4 
 2 files changed, 8 insertions(+)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 88d2fb2..dde46cd 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -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;
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 90a9b47..a84dddb 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -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;
 


[tip:efi/core] efi/arm*: Use memremap() to create the persistent memmap mapping

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  24d45d1dc275b818093fe1d0055a230ce5e8c4c7
Gitweb: http://git.kernel.org/tip/24d45d1dc275b818093fe1d0055a230ce5e8c4c7
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:41 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-10-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-runtime.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 55a9ea0..19283de 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -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;


[tip:efi/core] efi/arm*: Take the Memory Attributes table into account

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  789957ef72f976cb325e9057225fc4e9c4513060
Gitweb: http://git.kernel.org/tip/789957ef72f976cb325e9057225fc4e9c4513060
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:46 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Catalin Marinas 
Cc: Leif Lindholm 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-15-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 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(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 8e88a69..4dafc89 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -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_permissionsefi_create_mapping
+
 #define efi_call_virt(f, ...)  \
 ({ \
efi_##f##_t *__f;   \
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index a84dddb..909d974 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -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)) {
diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 19283de..17ccf0a 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -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(_mm, efi_set_mapping_permissions))
+   return false;
+
+   return true;
 }
 
 /*


[tip:efi/core] x86/efi/efifb: Move DMI based quirks handling out of generic code

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  21289ec02b41c4b928a0b3de1778b325d714eea3
Gitweb: http://git.kernel.org/tip/21289ec02b41c4b928a0b3de1778b325d714eea3
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:50 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: David Herrmann 
Acked-by: Peter Jones 
Cc: Borislav Petkov 
Cc: Mark Rutland 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-19-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 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(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 10e4407..8747abe 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -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(
diff --git a/arch/x86/kernel/sysfb_efi.c b/arch/x86/kernel/sysfb_efi.c
index b285d4e..e21a8a7 100644
--- a/arch/x86/kernel/sysfb_efi.c
+++ b/arch/x86/kernel/sysfb_efi.c
@@ -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))  \
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 95d293b..dd59436 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -15,7 +16,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 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(, ",")) != 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(_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))


[tip:efi/core] arm64/efi/libstub: Make screen_info accessible to the UEFI stub

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  57fdb89aeb7b0e3aab19847ab7399e5d76f11e6f
Gitweb: http://git.kernel.org/tip/57fdb89aeb7b0e3aab19847ab7399e5d76f11e6f
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:52 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Will Deacon 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-21-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h | 3 +++
 arch/arm64/kernel/efi.c  | 3 +++
 arch/arm64/kernel/image.h| 1 +
 3 files changed, 7 insertions(+)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index af40baa..fa09886 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -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...)_info
+#define free_screen_info(x...)
+
 #define EFI_ALLOC_ALIGNSZ_64K
 
 /*
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 33a6da1..78f5248 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -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);
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index 5e360ce..1428849a 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -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
 


[tip:efi/core] x86/efi: Prepare GOP handling code for reuse as generic code

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  2c23b73c2d0249c499c4784b6db08dcfc6b7b3b0
Gitweb: http://git.kernel.org/tip/2c23b73c2d0249c499c4784b6db08dcfc6b7b3b0
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:48 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-17-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 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(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 583d539..10516e2 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -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, , , _fb_base);
+   status = __gop_query32(sys_table_arg, gop32, , ,
+  _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)
 {
 

[tip:efi/core] efi/libstub: Move Graphics Output Protocol handling to generic code

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  fc37206427ce38eafbeff48099d873235e878450
Gitweb: http://git.kernel.org/tip/fc37206427ce38eafbeff48099d873235e878450
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:49 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-18-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 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(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index b0c341d..dc30d89 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -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,
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 4dafc89..af40baa 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -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_ALIGNSZ_64K
 
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 10516e2..52fef60 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -571,324 +571,6 @@ free_handle:
efi_call_early(free_pool, pci_handle);
 }
 
-static void
-setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
-struct efi_pixel_bitmask pixel_info, int pixel_format)
-{
-   if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
-   si->lfb_depth = 32;
-   si->lfb_linelength = pixels_per_scan_line * 4;
-   si->red_size = 8;
-   si->red_pos = 0;
-   si->green_size = 8;
-   si->green_pos = 8;
-   si->blue_size = 8;
-   si->blue_pos = 16;
-   si->rsvd_size = 8;
-   si->rsvd_pos = 24;
-   } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
-   si->lfb_depth = 32;
-   si->lfb_linelength = pixels_per_scan_line * 4;
-   si->red_size = 8;
-   si->red_pos = 16;
-   si->green_size = 8;
-   si->green_pos = 8;
-   si->blue_size = 8;
-   si->blue_pos = 0;
-   si->rsvd_size = 8;
-   si->rsvd_pos = 24;
-   } else if (pixel_format == PIXEL_BIT_MASK) {
-   find_bits(pixel_info.red_mask, >red_pos, >red_size);
-   find_bits(pixel_info.green_mask, >green_pos,
- >green_size);
-   find_bits(pixel_info.blue_mask, >blue_pos, >blue_size);
-   find_bits(pixel_info.reserved_mask, >rsvd_pos,
- >rsvd_size);
-   si->lfb_depth = si->red_size + si->green_size +
-   si->blue_size + si->rsvd_size;
-   si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
-   } else {
-   si->lfb_depth = 4;
-   si->lfb_linelength = 

[tip:efi/core] efi/arm*: Drop writable mapping of the UEFI System table

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  14c43be60166981f0b1f034ad9c59252c6f99e0d
Gitweb: http://git.kernel.org/tip/14c43be60166981f0b1f034ad9c59252c6f99e0d
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:34 +0100
Committer:  Ingo Molnar 
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.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Leif Lindholm 
Cc: Mark Rutland 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-3-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c|  2 ++
 drivers/firmware/efi/arm-runtime.c | 27 ---
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 8714f8c..008ed19 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -85,6 +85,8 @@ static int __init uefi_init(void)
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0x);
 
+   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));
diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 16c7d2a..771750d 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -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(_mm);
init_new_context(NULL, _mm);
 
+   systab_found = false;
for_each_efi_memory_desc(, md) {
phys_addr_t phys = md->phys_addr;
int ret;
@@ -64,8 +66,20 @@ static bool __init efi_virtmap_init(void)
, 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 = 
 
-   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)
  

[tip:efi/urgent] efi/fdt: Avoid FDT manipulation after ExitBootServices()

2017-02-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c8f325a59cfc718d13a50fbc746ed9b415c25e92
Gitweb: http://git.kernel.org/tip/c8f325a59cfc718d13a50fbc746ed9b415c25e92
Author: Ard Biesheuvel 
AuthorDate: Wed, 1 Feb 2017 17:45:02 +
Committer:  Ingo Molnar 
CommitDate: Wed, 1 Feb 2017 21:17:49 +0100

efi/fdt: Avoid FDT manipulation after ExitBootServices()

Some AArch64 UEFI implementations disable the MMU in ExitBootServices(),
after which unaligned accesses to RAM are no longer supported.

Commit:

  abfb7b686a3e ("efi/libstub/arm*: Pass latest memory map to the kernel")

fixed an issue in the memory map handling of the stub FDT code, but
inadvertently created an issue with such firmware, by moving some
of the FDT manipulation to after the invocation of ExitBootServices().

Given that the stub's libfdt implementation uses the ordinary, accelerated
string functions, which rely on hardware handling of unaligned accesses,
manipulating the FDT with the MMU off may result in alignment faults.

So fix the situation by moving the update_fdt_memmap() call into the
callback function invoked by efi_exit_boot_services() right before it
calls the ExitBootServices() UEFI service (which is arguably a better
place for it anyway)

Note that disabling the MMU in ExitBootServices() is not compliant with
the UEFI spec, and carries great risk due to the fact that switching from
cached to uncached memory accesses halfway through compiler generated code
(i.e., involving a stack) can never be done in a way that is architecturally
safe.

Fixes: abfb7b686a3e ("efi/libstub/arm*: Pass latest memory map to the kernel")
Signed-off-by: Ard Biesheuvel 
Tested-by: Riku Voipio 
Cc: 
Cc: mark.rutl...@arm.com
Cc: linux-...@vger.kernel.org
Cc: m...@codeblueprint.co.uk
Cc: leif.lindh...@linaro.org
Cc: linux-arm-ker...@lists.infradead.org
Link: 
http://lkml.kernel.org/r/1485971102-23330-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/fdt.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 921dfa0..260c4b4 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -187,6 +187,7 @@ static efi_status_t update_fdt_memmap(void *fdt, struct 
efi_boot_memmap *map)
 struct exit_boot_struct {
efi_memory_desc_t *runtime_map;
int *runtime_entry_count;
+   void *new_fdt_addr;
 };
 
 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -202,7 +203,7 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
p->runtime_map, p->runtime_entry_count);
 
-   return EFI_SUCCESS;
+   return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
 /*
@@ -300,22 +301,13 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 
priv.runtime_map = runtime_map;
priv.runtime_entry_count = _entry_count;
+   priv.new_fdt_addr = (void *)*new_fdt_addr;
status = efi_exit_boot_services(sys_table, handle, , ,
exit_boot_func);
 
if (status == EFI_SUCCESS) {
efi_set_virtual_address_map_t *svam;
 
-   status = update_fdt_memmap((void *)*new_fdt_addr, );
-   if (status != EFI_SUCCESS) {
-   /*
-* The kernel won't get far without the memory map, but
-* may still be able to print something meaningful so
-* return success here.
-*/
-   return EFI_SUCCESS;
-   }
-
/* Install the new virtual address map */
svam = sys_table->runtime->set_virtual_address_map;
status = svam(runtime_entry_count * desc_size, desc_size,


[tip:efi/core] efi/libstub: Preserve .debug sections after absolute relocation check

2017-02-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  696204faa6e8a318320ebb49d9fa69bc8275644d
Gitweb: http://git.kernel.org/tip/696204faa6e8a318320ebb49d9fa69bc8275644d
Author: Ard Biesheuvel 
AuthorDate: Tue, 31 Jan 2017 13:21:42 +
Committer:  Ingo Molnar 
CommitDate: Wed, 1 Feb 2017 08:45:47 +0100

efi/libstub: Preserve .debug sections after absolute relocation check

The build commands for the ARM and arm64 EFI stubs strip the .debug
sections and other sections that may legally contain absolute relocations,
in order to inspect the remaining sections for the presence of such
relocations.

This leaves us without debugging symbols in the stub for no good reason,
considering that these sections are omitted from the kernel binary anyway,
and that these relocations are thus only consumed by users of the ELF
binary, such as debuggers.

So move to 'strip' for performing the relocation check, and if it succeeds,
invoke objcopy as before, but leaving the .debug sections in place. Note
that these sections may refer to ksymtab/kcrctab contents, so leave those
in place as well.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1485868902-20401-11-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index d564d25..33e0e2f 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -11,7 +11,7 @@ cflags-$(CONFIG_X86)  += -m$(BITS) -D__KERNEL__ -O2 \
   -mno-mmx -mno-sse
 
 cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
-cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) -g0 \
+cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
   -fno-builtin -fpic -mno-single-pic-base
 
 cflags-$(CONFIG_EFI_ARMSTUB)   += -I$(srctree)/scripts/dtc/libfdt
@@ -60,7 +60,7 @@ CFLAGS_arm64-stub.o   := -DTEXT_OFFSET=$(TEXT_OFFSET)
 extra-$(CONFIG_EFI_ARMSTUB):= $(lib-y)
 lib-$(CONFIG_EFI_ARMSTUB)  := $(patsubst %.o,%.stub.o,$(lib-y))
 
-STUBCOPY_FLAGS-y   := -R .debug* -R *ksymtab* -R *kcrctab*
+STUBCOPY_RM-y  := -R *ksymtab* -R *kcrctab*
 STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \
   --prefix-symbols=__efistub_
 STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS
@@ -68,17 +68,25 @@ STUBCOPY_RELOC-$(CONFIG_ARM64)  := R_AARCH64_ABS
 $(obj)/%.stub.o: $(obj)/%.o FORCE
$(call if_changed,stubcopy)
 
+#
+# Strip debug sections and some other sections that may legally contain
+# absolute relocations, so that we can inspect the remaining sections for
+# such relocations. If none are found, regenerate the output object, but
+# this time, use objcopy and leave all sections in place.
+#
 quiet_cmd_stubcopy = STUBCPY $@
-  cmd_stubcopy = if $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; then \
-$(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y)\
-&& (echo >&2 "$@: absolute symbol references not allowed 
in the EFI stub"; \
-rm -f $@; /bin/false); else /bin/false; fi
+  cmd_stubcopy = if $(STRIP) --strip-debug $(STUBCOPY_RM-y) -o $@ $<; \
+then if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); \
+then (echo >&2 "$@: absolute symbol references not allowed 
in the EFI stub"; \
+  rm -f $@; /bin/false); \
+else $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; fi\
+else /bin/false; fi
 
 #
 # ARM discards the .data section because it disallows r/w data in the
 # decompressor. So move our .data to .data.efistub, which is preserved
 # explicitly by the decompressor linker script.
 #
-STUBCOPY_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub \
-  -R ___ksymtab+sort -R ___kcrctab+sort
+STUBCOPY_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub
+STUBCOPY_RM-$(CONFIG_ARM)  += -R ___ksymtab+sort -R ___kcrctab+sort
 STUBCOPY_RELOC-$(CONFIG_ARM)   := R_ARM_ABS


[tip:efi/core] efi: Use typed function pointers for the runtime services table

2017-02-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c4c39c70c5fef43655019236bec8ba5e7273b868
Gitweb: http://git.kernel.org/tip/c4c39c70c5fef43655019236bec8ba5e7273b868
Author: Ard Biesheuvel 
AuthorDate: Tue, 31 Jan 2017 13:21:39 +
Committer:  Ingo Molnar 
CommitDate: Wed, 1 Feb 2017 08:45:45 +0100

efi: Use typed function pointers for the runtime services table

Instead of using void pointers, and casting them to correctly typed
function pointers upon use, declare the runtime services pointers
as function pointers using their respective prototypes, for which
typedefs are already available.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1485868902-20401-8-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 include/linux/efi.h | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5f632bf..85e9fda 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -509,24 +509,6 @@ typedef struct {
u64 query_variable_info;
 } efi_runtime_services_64_t;
 
-typedef struct {
-   efi_table_hdr_t hdr;
-   void *get_time;
-   void *set_time;
-   void *get_wakeup_time;
-   void *set_wakeup_time;
-   void *set_virtual_address_map;
-   void *convert_pointer;
-   void *get_variable;
-   void *get_next_variable;
-   void *set_variable;
-   void *get_next_high_mono_count;
-   void *reset_system;
-   void *update_capsule;
-   void *query_capsule_caps;
-   void *query_variable_info;
-} efi_runtime_services_t;
-
 typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
 typedef efi_status_t efi_set_time_t (efi_time_t *tm);
 typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t 
*pending,
@@ -561,6 +543,24 @@ typedef efi_status_t efi_query_variable_store_t(u32 
attributes,
unsigned long size,
bool nonblocking);
 
+typedef struct {
+   efi_table_hdr_t hdr;
+   efi_get_time_t  *get_time;
+   efi_set_time_t  *set_time;
+   efi_get_wakeup_time_t   *get_wakeup_time;
+   efi_set_wakeup_time_t   *set_wakeup_time;
+   efi_set_virtual_address_map_t   *set_virtual_address_map;
+   void*convert_pointer;
+   efi_get_variable_t  *get_variable;
+   efi_get_next_variable_t *get_next_variable;
+   efi_set_variable_t  *set_variable;
+   efi_get_next_high_mono_count_t  *get_next_high_mono_count;
+   efi_reset_system_t  *reset_system;
+   efi_update_capsule_t*update_capsule;
+   efi_query_capsule_caps_t*query_capsule_caps;
+   efi_query_variable_info_t   *query_variable_info;
+} efi_runtime_services_t;
+
 void efi_native_runtime_setup(void);
 
 /*


[tip:efi/core] efi/libstub: Make file I/O chunking x86-specific

2017-02-07 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b3879a4d3a31ef14265a52e8d941cf4b0f6627ae
Gitweb: http://git.kernel.org/tip/b3879a4d3a31ef14265a52e8d941cf4b0f6627ae
Author: Ard Biesheuvel 
AuthorDate: Mon, 6 Feb 2017 11:22:46 +
Committer:  Ingo Molnar 
CommitDate: Tue, 7 Feb 2017 10:42:11 +0100

efi/libstub: Make file I/O chunking x86-specific

The ARM decompressor is finicky when it comes to uninitialized variables
with local linkage, the reason being that it may relocate .text and .bss
independently when executing from ROM. This is only possible if all
references into .bss from .text are absolute, and this happens to be the
case for references emitted under -fpic to symbols with external linkage,
and so all .bss references must involve symbols with external linkage.

When building the ARM stub using clang, the initialized local variable
__chunk_size is optimized into a zero-initialized flag that indicates
whether chunking is in effect or not. This flag is therefore emitted into
.bss, which triggers the ARM decompressor's diagnostics, resulting in a
failed build.

Under UEFI, we never execute the decompressor from ROM, so the diagnostic
makes little sense here. But we can easily work around the issue by making
__chunk_size global instead.

However, given that the file I/O chunking that is controlled by the
__chunk_size variable is intended to work around known bugs on various
x86 implementations of UEFI, we can simply make the chunking an x86
specific feature. This is an improvement by itself, and also removes the
need to parse the efi= options in the stub entirely.

Tested-by: Arnd Bergmann 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1486380166-31868-8-git-send-email-ard.biesheu...@linaro.org
[ Small readability edits. ]
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 6ee9164..919822b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -414,6 +414,14 @@ efi_status_t efi_parse_options(char *cmdline)
char *str;
 
/*
+* Currently, the only efi= option we look for is 'nochunk', which
+* is intended to work around known issues on certain x86 UEFI
+* versions. So ignore for now on other architectures.
+*/
+   if (!IS_ENABLED(CONFIG_X86))
+   return EFI_SUCCESS;
+
+   /*
 * If no EFI parameters were specified on the cmdline we've got
 * nothing to do.
 */
@@ -586,7 +594,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t 
*sys_table_arg,
size = files[j].size;
while (size) {
unsigned long chunksize;
-   if (size > __chunk_size)
+
+   if (IS_ENABLED(CONFIG_X86) && size > 
__chunk_size)
chunksize = __chunk_size;
else
chunksize = size;


[tip:efi/urgent] efi/libstub: Treat missing SecureBoot variable as Secure Boot disabled

2017-03-02 Thread tip-bot for Ard Biesheuvel
Commit-ID:  52e51f16407b7b34e26affb500a21e250d9fce0b
Gitweb: http://git.kernel.org/tip/52e51f16407b7b34e26affb500a21e250d9fce0b
Author: Ard Biesheuvel 
AuthorDate: Wed, 1 Mar 2017 19:04:35 +
Committer:  Ingo Molnar 
CommitDate: Thu, 2 Mar 2017 08:11:18 +0100

efi/libstub: Treat missing SecureBoot variable as Secure Boot disabled

The newly refactored code that infers the firmware's Secure Boot state
prints the following error when the EFI variable 'SecureBoot' does not
exist:

  EFI stub: ERROR: Could not determine UEFI Secure Boot status.

However, this variable is only guaranteed to be defined on a system that
is Secure Boot capable to begin with, and so it is not an error if it is
missing. So report Secure Boot as being disabled in this case, without
printing any error messages.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1488395076-29712-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/secureboot.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/secureboot.c 
b/drivers/firmware/efi/libstub/secureboot.c
index 6def402..5da36e5 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -45,6 +45,8 @@ enum efi_secureboot_mode 
efi_get_secureboot(efi_system_table_t *sys_table_arg)
size = sizeof(secboot);
status = get_efi_var(efi_SecureBoot_name, _variable_guid,
 NULL, , );
+   if (status == EFI_NOT_FOUND)
+   return efi_secureboot_mode_disabled;
if (status != EFI_SUCCESS)
goto out_efi_err;
 
@@ -78,7 +80,5 @@ secure_boot_enabled:
 
 out_efi_err:
pr_efi_err(sys_table_arg, "Could not determine UEFI Secure Boot 
status.\n");
-   if (status == EFI_NOT_FOUND)
-   return efi_secureboot_mode_disabled;
return efi_secureboot_mode_unknown;
 }


[tip:efi/urgent] efi/arm: Fix boot crash with CONFIG_CPUMASK_OFFSTACK=y

2017-03-02 Thread tip-bot for Ard Biesheuvel
Commit-ID:  d1eb98143c56f24fef125f5bbed49ae0b52fb7d6
Gitweb: http://git.kernel.org/tip/d1eb98143c56f24fef125f5bbed49ae0b52fb7d6
Author: Ard Biesheuvel 
AuthorDate: Wed, 1 Mar 2017 19:05:54 +
Committer:  Ingo Molnar 
CommitDate: Thu, 2 Mar 2017 08:11:19 +0100

efi/arm: Fix boot crash with CONFIG_CPUMASK_OFFSTACK=y

On ARM and arm64, we use a dedicated mm_struct to map the UEFI
Runtime Services regions, which allows us to map those regions
on demand, and in a way that is guaranteed to be compatible
with incoming kernels across kexec.

As it turns out, we don't fully initialize the mm_struct in the
same way as process mm_structs are initialized on fork(), which
results in the following crash on ARM if CONFIG_CPUMASK_OFFSTACK=y
is enabled:

  ...
  EFI Variables Facility v0.08 2004-May-17
  Unable to handle kernel NULL pointer dereference at virtual address 
  [...]
  Process swapper/0 (pid: 1)
  ...
  __memzero()
  check_and_switch_context()
  virt_efi_get_next_variable()
  efivar_init()
  efivars_sysfs_init()
  do_one_initcall()
  ...

This is due to a missing call to mm_init_cpumask(), so add it.

Signed-off-by: Ard Biesheuvel 
Cc:  # v4.5+
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1488395154-29786-1-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-runtime.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 349dc3e..974c5a3 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -65,6 +65,7 @@ static bool __init efi_virtmap_init(void)
bool systab_found;
 
efi_mm.pgd = pgd_alloc(_mm);
+   mm_init_cpumask(_mm);
init_new_context(NULL, _mm);
 
systab_found = false;


[tip:efi/core] MAINTAINERS: Add myself as EFI maintainer

2016-10-18 Thread tip-bot for Ard Biesheuvel
Commit-ID:  6026ed2fe258b61ea5aadd91a95c4f36a6dbe167
Gitweb: http://git.kernel.org/tip/6026ed2fe258b61ea5aadd91a95c4f36a6dbe167
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Oct 2016 15:33:11 +0100
Committer:  Ingo Molnar 
CommitDate: Tue, 18 Oct 2016 17:11:14 +0200

MAINTAINERS: Add myself as EFI maintainer

At the request of Matt, I am taking up co-maintainership of the EFI
subsystem. So add my name to the EFI section in MAINTAINERS, and
change the SCM tree reference to point to the new shared Git repo.

Signed-off-by: Ard Biesheuvel 
Acked-by: Will Deacon 
Acked-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161018143318.15673-2-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 MAINTAINERS | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1cd38a7..6847ba8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4620,8 +4620,9 @@ F:sound/usb/misc/ua101.c
 
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M: Matt Fleming 
+M: Ard Biesheuvel 
 L: linux-...@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
 S: Maintained
 F: Documentation/efi-stub.txt
 F: arch/ia64/kernel/efi.c


[tip:efi/urgent] efi/arm: Fix absolute relocation detection for older toolchains

2016-10-19 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b0dddf6c147e6fe61374d625c4bb2b7c52018639
Gitweb: http://git.kernel.org/tip/b0dddf6c147e6fe61374d625c4bb2b7c52018639
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Oct 2016 16:53:11 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 19 Oct 2016 14:49:44 +0200

efi/arm: Fix absolute relocation detection for older toolchains

When building the ARM kernel with CONFIG_EFI=y, the following build
error may occur when using a less recent version of binutils (2.23 or
older):

   STUBCPY drivers/firmware/efi/libstub/lib-sort.stub.o
  R_ARM_ABS32   sort
 0004 R_ARM_ABS32   __ksymtab_strings
 drivers/firmware/efi/libstub/lib-sort.stub.o: absolute symbol references not 
allowed in the EFI stub

(and when building with debug symbols, the list above is much longer, and
contains all the internal references between the .debug sections and the
actual code)

This issue is caused by the fact that objcopy v2.23 or earlier does not
support wildcards in its -R and -j options, which means the following
line from the Makefile:

  STUBCOPY_FLAGS-y  := -R .debug* -R *ksymtab* -R *kcrctab*

fails to take effect, leaving harmless absolute relocations in the binary
that are indistinguishable from relocations that may cause crashes at
runtime due to the fact that these relocations are resolved at link time
using the virtual address of the kernel, which is always different from
the address at which the EFI firmware loads and invokes the stub.

So, as a workaround, disable debug symbols explicitly when building the
stub for ARM, and strip the ksymtab and kcrctab symbols for the only
exported symbol we currently reuse in the stub, which is 'sort'.

Tested-by: Jon Hunter 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1476805991-7160-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index c069451..5e23e2d 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -11,7 +11,7 @@ cflags-$(CONFIG_X86)  += -m$(BITS) -D__KERNEL__ 
$(LINUX_INCLUDE) -O2 \
   -mno-mmx -mno-sse
 
 cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
-cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
+cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) -g0 \
   -fno-builtin -fpic -mno-single-pic-base
 
 cflags-$(CONFIG_EFI_ARMSTUB)   += -I$(srctree)/scripts/dtc/libfdt
@@ -79,5 +79,6 @@ quiet_cmd_stubcopy = STUBCPY $@
 # decompressor. So move our .data to .data.efistub, which is preserved
 # explicitly by the decompressor linker script.
 #
-STUBCOPY_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub
+STUBCOPY_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub \
+  -R ___ksymtab+sort -R ___kcrctab+sort
 STUBCOPY_RELOC-$(CONFIG_ARM)   := R_ARM_ABS


[tip:efi/core] efi/libstub: Make efi_random_alloc() allocate below 4 GB on 32-bit

2016-11-24 Thread tip-bot for Ard Biesheuvel
Commit-ID:  018edcfac4c3b140366ad51b0907f3becb5bb624
Gitweb: http://git.kernel.org/tip/018edcfac4c3b140366ad51b0907f3becb5bb624
Author: Ard Biesheuvel 
AuthorDate: Thu, 24 Nov 2016 18:02:23 +
Committer:  Ingo Molnar 
CommitDate: Fri, 25 Nov 2016 07:15:23 +0100

efi/libstub: Make efi_random_alloc() allocate below 4 GB on 32-bit

The UEFI stub executes in the context of the firmware, which identity
maps the available system RAM, which implies that only memory below
4 GB can be used for allocations on 32-bit architectures, even on [L]PAE
capable hardware.

So ignore any reported memory above 4 GB in efi_random_alloc(). This
also fixes a reported build problem on ARM under -Os, where the 64-bit
logical shift relies on a software routine that the ARM decompressor does
not provide.

A second [minor] issue is also fixed, where the '+ 1' is moved out of
the shift, where it belongs: the reason for its presence is that a
memory region where start == end should count as a single slot, given
that 'end' takes the desired size and alignment of the allocation into
account.

To clarify the code in this regard, rename start/end to 'first_slot' and
'last_slot', respectively, and introduce 'region_end' to describe the
last usable address of the current region.

Reported-by: Arnd Bergmann 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1480010543-25709-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/random.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index 3a3feac..7e72954 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -45,19 +45,20 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t 
*md,
 unsigned long align_shift)
 {
unsigned long align = 1UL << align_shift;
-   u64 start, end;
+   u64 first_slot, last_slot, region_end;
 
if (md->type != EFI_CONVENTIONAL_MEMORY)
return 0;
 
-   start = round_up(md->phys_addr, align);
-   end = round_down(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - size,
-align);
+   region_end = min((u64)ULONG_MAX, md->phys_addr + 
md->num_pages*EFI_PAGE_SIZE - 1);
 
-   if (start > end)
+   first_slot = round_up(md->phys_addr, align);
+   last_slot = round_down(region_end - size + 1, align);
+
+   if (first_slot > last_slot)
return 0;
 
-   return (end - start + 1) >> align_shift;
+   return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1;
 }
 
 /*


[tip:efi/core] efi/arm*/libstub: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  568bc4e87033d232c5fd00d5b0cd22a2ccc04944
Gitweb: http://git.kernel.org/tip/568bc4e87033d232c5fd00d5b0cd22a2ccc04944
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:33 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:15 +0100

efi/arm*/libstub: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table

Invoke the EFI_RNG_PROTOCOL protocol in the context of the stub and
install the Linux-specific RNG seed UEFI config table. This will be
picked up by the EFI routines in the core kernel to seed the kernel
entropy pool.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Kees Cook 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-6-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c |  2 ++
 drivers/firmware/efi/libstub/efistub.h  |  2 ++
 drivers/firmware/efi/libstub/random.c   | 48 +
 include/linux/efi.h |  1 +
 4 files changed, 53 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 993aa56..b4f7d78 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -340,6 +340,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (status != EFI_SUCCESS)
pr_efi_err(sys_table, "Failed initrd from command line!\n");
 
+   efi_random_get_seed(sys_table);
+
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
_fdt_addr, dram_base + MAX_FDT_OFFSET,
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index fe1f225..b98824e 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -71,4 +71,6 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
 
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+
 #endif
diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index f8e2e5a..3a3feac 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -143,3 +143,51 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
 
return status;
 }
+
+#define RANDOM_SEED_SIZE   32
+
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
+{
+   efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+   efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
+   efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+   struct efi_rng_protocol *rng;
+   struct linux_efi_random_seed *seed;
+   efi_status_t status;
+
+   status = efi_call_early(locate_protocol, _proto, NULL,
+   (void **));
+   if (status != EFI_SUCCESS)
+   return status;
+
+   status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+   sizeof(*seed) + RANDOM_SEED_SIZE,
+   (void **));
+   if (status != EFI_SUCCESS)
+   return status;
+
+   status = rng->get_rng(rng, _algo_raw, RANDOM_SEED_SIZE,
+ seed->bits);
+   if (status == EFI_UNSUPPORTED)
+   /*
+* Use whatever algorithm we have available if the raw algorithm
+* is not implemented.
+*/
+   status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+ seed->bits);
+
+   if (status != EFI_SUCCESS)
+   goto err_freepool;
+
+   seed->size = RANDOM_SEED_SIZE;
+   status = efi_call_early(install_configuration_table, _table_guid,
+   seed);
+   if (status != EFI_SUCCESS)
+   goto err_freepool;
+
+   return EFI_SUCCESS;
+
+err_freepool:
+   efi_call_early(free_pool, seed);
+   return status;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 85e28b1..f5a821d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -589,6 +589,7 @@ void efi_native_runtime_setup(void);
 #define DEVICE_TREE_GUID   EFI_GUID(0xb1b621d5, 0xf19c, 
0x41a5,  0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
 #define EFI_PROPERTIES_TABLE_GUID  EFI_GUID(0x880aaca3, 0x4adc, 
0x4a04,  0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5)
 #define EFI_RNG_PROTOCOL_GUID  EFI_GUID(0x3152bca5, 0xeade, 
0x433d,  0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 

[tip:efi/core] efi/libstub: Add random.c to ARM build

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  a6a144698db93a2c456d1e3811140cadef1ba0e3
Gitweb: http://git.kernel.org/tip/a6a144698db93a2c456d1e3811140cadef1ba0e3
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:32 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:15 +0100

efi/libstub: Add random.c to ARM build

Make random.c build for ARM by moving the fallback definition of
EFI_ALLOC_ALIGN to efistub.h, and replacing a division by a value
we know to be a power of 2 with a right shift (this is required since
ARM does not have any integer division helper routines in its decompressor)

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Kees Cook 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-5-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile  | 4 ++--
 drivers/firmware/efi/libstub/efi-stub-helper.c | 9 -
 drivers/firmware/efi/libstub/efistub.h | 9 +
 drivers/firmware/efi/libstub/random.c  | 8 +---
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index 5e23e2d..6621b13 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -36,11 +36,11 @@ arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c 
fdt_empty_tree.c fdt_sw.c sort.c
 $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
$(call if_changed_rule,cc_o_c)
 
-lib-$(CONFIG_EFI_ARMSTUB)  += arm-stub.o fdt.o string.o \
+lib-$(CONFIG_EFI_ARMSTUB)  += arm-stub.o fdt.o string.o random.o \
   $(patsubst %.c,lib-%.o,$(arm-deps))
 
 lib-$(CONFIG_ARM)  += arm32-stub.o
-lib-$(CONFIG_ARM64)+= arm64-stub.o random.o
+lib-$(CONFIG_ARM64)+= arm64-stub.o
 CFLAGS_arm64-stub.o:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 #
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 4b74bf8..757badc 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,15 +32,6 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
-/*
- * Allow the platform to override the allocation granularity: this allows
- * systems that have the capability to run with a larger page size to deal
- * with the allocations for initrd and fdt more efficiently.
- */
-#ifndef EFI_ALLOC_ALIGN
-#define EFI_ALLOC_ALIGNEFI_PAGE_SIZE
-#endif
-
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
 struct file_info {
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index ee49cd2..fe1f225 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -15,6 +15,15 @@
  */
 #undef __init
 
+/*
+ * Allow the platform to override the allocation granularity: this allows
+ * systems that have the capability to run with a larger page size to deal
+ * with the allocations for initrd and fdt more efficiently.
+ */
+#ifndef EFI_ALLOC_ALIGN
+#define EFI_ALLOC_ALIGNEFI_PAGE_SIZE
+#endif
+
 void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index 0c9f58c..f8e2e5a 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -8,6 +8,7 @@
  */
 
 #include 
+#include 
 #include 
 
 #include "efistub.h"
@@ -41,8 +42,9 @@ efi_status_t efi_get_random_bytes(efi_system_table_t 
*sys_table_arg,
  */
 static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
 unsigned long size,
-unsigned long align)
+unsigned long align_shift)
 {
+   unsigned long align = 1UL << align_shift;
u64 start, end;
 
if (md->type != EFI_CONVENTIONAL_MEMORY)
@@ -55,7 +57,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t 
*md,
if (start > end)
return 0;
 
-   return (end - start + 1) / align;
+   return (end - start + 1) >> align_shift;
 }
 
 /*
@@ -98,7 +100,7 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
efi_memory_desc_t *md = (void *)memory_map + map_offset;
unsigned long slots;
 
-   slots = get_entry_num_slots(md, size, align);
+   slots = get_entry_num_slots(md, size, ilog2(align));
MD_NUM_SLOTS(md) = slots;
  

[tip:efi/core] MAINTAINERS: Add ARM and arm64 EFI specific files to EFI subsystem

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f135a176426fc643caf6480e3200f1733f58dbf6
Gitweb: http://git.kernel.org/tip/f135a176426fc643caf6480e3200f1733f58dbf6
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:30 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:14 +0100

MAINTAINERS: Add ARM and arm64 EFI specific files to EFI subsystem

Since I will be co-maintaining the EFI subsystem, it makes sense to
mention the ARM and arm64 EFI bits in the EFI section in MAINTAINERS
so that Matt, the list and I get cc'ed on proposed changes.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Will Deacon 
Acked-by: Russell King 
Cc: Linus Torvalds 
Cc: M: Matthew Garrett 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-3-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 MAINTAINERS | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 851b89b..afaf24f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4631,12 +4631,14 @@ L:  linux-...@vger.kernel.org
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
 S: Maintained
 F: Documentation/efi-stub.txt
-F: arch/ia64/kernel/efi.c
+F: arch/*/kernel/efi.c
 F: arch/x86/boot/compressed/eboot.[ch]
-F: arch/x86/include/asm/efi.h
+F: arch/*/include/asm/efi.h
 F: arch/x86/platform/efi/
 F: drivers/firmware/efi/
 F: include/linux/efi*.h
+F: arch/arm/boot/compressed/efi-header.S
+F: arch/arm64/kernel/efi-entry.S
 
 EFI VARIABLE FILESYSTEM
 M: Matthew Garrett 


[tip:efi/core] efi: Add support for seeding the RNG from a UEFI config table

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  636259880a7e7d3446a707dddebc799da94bdd0b
Gitweb: http://git.kernel.org/tip/636259880a7e7d3446a707dddebc799da94bdd0b
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:31 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:14 +0100

efi: Add support for seeding the RNG from a UEFI config table

Specify a Linux specific UEFI configuration table that carries some
random bits, and use the contents during early boot to seed the kernel's
random number generator. This allows much strong random numbers to be
generated early on.

The entropy is fed to the kernel using add_device_randomness(), which is
documented as being appropriate for being called very early.

Since UEFI configuration tables may also be consumed by kexec'd kernels,
register a reboot notifier that updates the seed in the table.

Note that the config table could be generated by the EFI stub or by any
other UEFI driver or application (e.g., GRUB), but the random seed table
GUID and the associated functionality should be considered an internal
kernel interface (unless it is promoted to ABI later on)

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Kees Cook 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-4-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c | 72 ++
 include/linux/efi.h|  8 ++
 2 files changed, 80 insertions(+)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a4944e2..9291480 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -23,7 +23,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -48,6 +51,7 @@ struct efi __read_mostly efi = {
.esrt   = EFI_INVALID_TABLE_ADDR,
.properties_table   = EFI_INVALID_TABLE_ADDR,
.mem_attr_table = EFI_INVALID_TABLE_ADDR,
+   .rng_seed   = EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
 
@@ -440,6 +444,7 @@ static __initdata efi_config_table_type_t common_tables[] = 
{
{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", },
{EFI_PROPERTIES_TABLE_GUID, "PROP", _table},
{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", _attr_table},
+   {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", _seed},
{NULL_GUID, NULL, NULL},
 };
 
@@ -501,6 +506,29 @@ int __init efi_config_parse_tables(void *config_tables, 
int count, int sz,
pr_cont("\n");
set_bit(EFI_CONFIG_TABLES, );
 
+   if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
+   struct linux_efi_random_seed *seed;
+   u32 size = 0;
+
+   seed = early_memremap(efi.rng_seed, sizeof(*seed));
+   if (seed != NULL) {
+   size = seed->size;
+   early_memunmap(seed, sizeof(*seed));
+   } else {
+   pr_err("Could not map UEFI random seed!\n");
+   }
+   if (size > 0) {
+   seed = early_memremap(efi.rng_seed,
+ sizeof(*seed) + size);
+   if (seed != NULL) {
+   add_device_randomness(seed->bits, seed->size);
+   early_memunmap(seed, sizeof(*seed) + size);
+   } else {
+   pr_err("Could not map UEFI random seed!\n");
+   }
+   }
+   }
+
/* Parse the EFI Properties table if it exists */
if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
efi_properties_table_t *tbl;
@@ -824,3 +852,47 @@ int efi_status_to_err(efi_status_t status)
 
return err;
 }
+
+#ifdef CONFIG_KEXEC
+static int update_efi_random_seed(struct notifier_block *nb,
+ unsigned long code, void *unused)
+{
+   struct linux_efi_random_seed *seed;
+   u32 size = 0;
+
+   if (!kexec_in_progress)
+   return NOTIFY_DONE;
+
+   seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
+   if (seed != NULL) {
+   size = min(seed->size, 32U);
+   memunmap(seed);
+   } else {
+   pr_err("Could not map UEFI random seed!\n");
+   }
+   if (size > 0) {
+   seed = memremap(efi.rng_seed, sizeof(*seed) + size,
+   MEMREMAP_WB);
+   if (seed != NULL) {
+   seed->size = size;
+   get_random_bytes(seed->bits, seed->size);
+   

[tip:efi/urgent] efi/libstub/arm*: Pass latest memory map to the kernel

2016-12-29 Thread tip-bot for Ard Biesheuvel
Commit-ID:  abfb7b686a3e5be27bf81db62f9c5c895b76f5d1
Gitweb: http://git.kernel.org/tip/abfb7b686a3e5be27bf81db62f9c5c895b76f5d1
Author: Ard Biesheuvel 
AuthorDate: Sat, 24 Dec 2016 13:59:23 +
Committer:  Ingo Molnar 
CommitDate: Wed, 28 Dec 2016 09:23:32 +0100

efi/libstub/arm*: Pass latest memory map to the kernel

As reported by James Morse, the current libstub code involving the
annotated memory map only works somewhat correctly by accident, due
to the fact that a pool allocation happens to be reused immediately,
retaining its former contents on most implementations of the
UEFI boot services.

Instead of juggling memory maps, which makes the code more complex than
it needs to be, simply put placeholder values into the FDT for the memory
map parameters, and only write the actual values after ExitBootServices()
has been called.

Reported-by: James Morse 
Signed-off-by: Ard Biesheuvel 
Cc: 
Cc: Jeffrey Hugo 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-...@vger.kernel.org
Fixes: ed9cc156c42f ("efi/libstub: Use efi_exit_boot_services() in FDT")
Link: 
http://lkml.kernel.org/r/1482587963-20183-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efistub.h |  8 
 drivers/firmware/efi/libstub/fdt.c | 87 ++
 2 files changed, 56 insertions(+), 39 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index b98824e..0e2a96b 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -39,14 +39,6 @@ efi_status_t efi_file_close(void *handle);
 
 unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-   unsigned long orig_fdt_size,
-   void *fdt, int new_fdt_size, char *cmdline_ptr,
-   u64 initrd_addr, u64 initrd_size,
-   efi_memory_desc_t *memory_map,
-   unsigned long map_size, unsigned long desc_size,
-   u32 desc_ver);
-
 efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
void *handle,
unsigned long *new_fdt_addr,
diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index a6a9311..921dfa0 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -16,13 +16,10 @@
 
 #include "efistub.h"
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-   unsigned long orig_fdt_size,
-   void *fdt, int new_fdt_size, char *cmdline_ptr,
-   u64 initrd_addr, u64 initrd_size,
-   efi_memory_desc_t *memory_map,
-   unsigned long map_size, unsigned long desc_size,
-   u32 desc_ver)
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+  unsigned long orig_fdt_size,
+  void *fdt, int new_fdt_size, char *cmdline_ptr,
+  u64 initrd_addr, u64 initrd_size)
 {
int node, num_rsv;
int status;
@@ -101,25 +98,23 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, 
void *orig_fdt,
if (status)
goto fdt_set_fail;
 
-   fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+   fdt_val64 = U64_MAX; /* placeholder */
status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
 _val64,  sizeof(fdt_val64));
if (status)
goto fdt_set_fail;
 
-   fdt_val32 = cpu_to_fdt32(map_size);
+   fdt_val32 = U32_MAX; /* placeholder */
status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
 _val32,  sizeof(fdt_val32));
if (status)
goto fdt_set_fail;
 
-   fdt_val32 = cpu_to_fdt32(desc_size);
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
 _val32, sizeof(fdt_val32));
if (status)
goto fdt_set_fail;
 
-   fdt_val32 = cpu_to_fdt32(desc_ver);
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
 _val32, sizeof(fdt_val32));
if (status)
@@ -148,6 +143,43 @@ fdt_set_fail:
return EFI_LOAD_ERROR;
 }
 
+static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
+{
+   int node = 

[tip:efi/urgent] efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  5a8997342183bb792fe2c15cecf371665d784dd7
Gitweb: http://git.kernel.org/tip/5a8997342183bb792fe2c15cecf371665d784dd7
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 16:27:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:20:18 +0200

efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

On UEFI systems, the PCI subsystem is enumerated by the firmware,
and if a graphical framebuffer is exposed via a PCI device, its base
address and size are exposed to the OS via the Graphics Output
Protocol (GOP).

On arm64 PCI systems, the entire PCI hierarchy is reconfigured from
scratch at boot. This may result in the GOP framebuffer address to
become stale, if the BAR covering the framebuffer is modified. This
will cause the framebuffer to become unresponsive, and may in some
cases result in unpredictable behavior if the range is reassigned to
another device.

So add a non-x86 quirk to the EFI fb driver to find the BAR associated
with the GOP base address, and claim the BAR resource so that the PCI
core will not move it.

Signed-off-by: Ard Biesheuvel 
Cc:  # v4.7+
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: lorenzo.pieral...@arm.com
Fixes: 9822504c1fa5 ("efifb: Enable the efi-framebuffer platform driver ...")
Link: http://lkml.kernel.org/r/20170404152744.26687-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 66 -
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 8c4dc1e..758960b 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -143,6 +144,8 @@ static struct attribute *efifb_attrs[] = {
 };
 ATTRIBUTE_GROUPS(efifb);
 
+static bool pci_dev_disabled;  /* FB base matches BAR of a disabled device */
+
 static int efifb_probe(struct platform_device *dev)
 {
struct fb_info *info;
@@ -152,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
unsigned int size_total;
char *option = NULL;
 
-   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
 
if (fb_get_options("efifb", ))
@@ -360,3 +363,64 @@ static struct platform_driver efifb_driver = {
 };
 
 builtin_platform_driver(efifb_driver);
+
+#ifndef CONFIG_X86
+
+static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+
+static void claim_efifb_bar(struct pci_dev *dev, int idx)
+{
+   u16 word;
+
+   pci_bar_found = true;
+
+   pci_read_config_word(dev, PCI_COMMAND, );
+   if (!(word & PCI_COMMAND_MEMORY)) {
+   pci_dev_disabled = true;
+   dev_err(>dev,
+   "BAR %d: assigned to efifb but device is disabled!\n",
+   idx);
+   return;
+   }
+
+   if (pci_claim_resource(dev, idx)) {
+   pci_dev_disabled = true;
+   dev_err(>dev,
+   "BAR %d: failed to claim resource for efifb!\n", idx);
+   return;
+   }
+
+   dev_info(>dev, "BAR %d: assigned to efifb\n", idx);
+}
+
+static void efifb_fixup_resources(struct pci_dev *dev)
+{
+   u64 base = screen_info.lfb_base;
+   u64 size = screen_info.lfb_size;
+   int i;
+
+   if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   return;
+
+   if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+   base |= (u64)screen_info.ext_lfb_base << 32;
+
+   if (!base)
+   return;
+
+   for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
+   struct resource *res = >resource[i];
+
+   if (!(res->flags & IORESOURCE_MEM))
+   continue;
+
+   if (res->start <= base && res->end >= base + size - 1) {
+   claim_efifb_bar(dev, i);
+   break;
+   }
+   }
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
+  16, efifb_fixup_resources);
+
+#endif


[tip:efi/core] efi/arm-stub: Correct FDT and initrd allocation rules for arm64

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  5e0e04e655826dce058c75a82adaa979231e6149
Gitweb: http://git.kernel.org/tip/5e0e04e655826dce058c75a82adaa979231e6149
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:37 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:48 +0200

efi/arm-stub: Correct FDT and initrd allocation rules for arm64

On arm64, we have made some changes over the past year to the way the
kernel itself is allocated and to how it deals with the initrd and FDT.
This patch brings the allocation logic in the EFI stub in line with that,
which is necessary because the introduction of KASLR has created the
possibility for the initrd to be allocated in a place where the kernel
may not be able to map it. (This is mostly a theoretical scenario, since
it only affects systems where the physical memory footprint exceeds the
size of the linear mapping.)

Since we know the kernel itself will be covered by the linear mapping,
choose a suitably sized window (i.e., based on the size of the linear
region) covering the kernel when allocating memory for the initrd.

The FDT may be anywhere in memory on arm64 now that we map it via the
fixmap, so we can lift the address restriction there completely.

Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Jeffrey Hugo 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/include/asm/efi.h  | 14 +-
 arch/arm64/include/asm/efi.h| 23 ++-
 drivers/firmware/efi/libstub/arm-stub.c |  7 ---
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index e4e6a9d6..17f1f1a 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info 
*si, const char *opt)
  */
 #define ZIMAGE_OFFSET_LIMITSZ_128M
 #define MIN_ZIMAGE_OFFSET  MAX_UNCOMP_KERNEL_SIZE
-#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT
+
+/* on ARM, the FDT should be located in the first 128 MB of RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return dram_base + ZIMAGE_OFFSET_LIMIT;
+}
+
+/* on ARM, the initrd should be loaded in a lowmem region */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return dram_base + SZ_512M;
+}
 
 #endif /* _ASM_ARM_EFI_H */
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index e744528..083a52d3 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -46,7 +46,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, 
efi_memory_desc_t *md);
  * 2MiB so we know it won't cross a 2MiB boundary.
  */
 #define EFI_FDT_ALIGN  SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
-#define MAX_FDT_OFFSET SZ_512M
+
+/* on arm64, the FDT may be located anywhere in system RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return ULONG_MAX;
+}
+
+/*
+ * On arm64, we have to ensure that the initrd ends up in the linear region,
+ * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is
+ * guaranteed to cover the kernel Image.
+ *
+ * Since the EFI stub is part of the kernel Image, we can relax the
+ * usual requirements in Documentation/arm64/booting.txt, which still
+ * apply to other bootloaders, and are required for some kernel
+ * configurations.
+ */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1));
+}
 
 #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
 #define __efi_call_early(f, ...)   f(__VA_ARGS__)
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index d4056c6..02049ff 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -213,8 +213,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (!fdt_addr)
pr_efi(sys_table, "Generating empty DTB\n");
 
-   status = handle_cmdline_files(sys_table, image, cmdline_ptr,
- "initrd=", dram_base + SZ_512M,
+   status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
+ 

[tip:efi/core] efi/arm-stub: Round up FDT allocation to mapping size

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  05181c7c42c830e5f3fe7a0e93dfec0bd0fd8456
Gitweb: http://git.kernel.org/tip/05181c7c42c830e5f3fe7a0e93dfec0bd0fd8456
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:39 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:49 +0200

efi/arm-stub: Round up FDT allocation to mapping size

The FDT is mapped via a fixmap entry that is at least 2 MB in size and
2 MB aligned on 4 KB page size kernels.

On UEFI systems, the FDT allocation may share this 2 MB mapping with a
reserved region (or another memory region that we should never map),
unless we account for this in the size of the allocation (the alignment
is already 2 MB)

So instead of taking guesses at the needed space, simply allocate 2 MB
immediately. The allocation will be recorded as EFI_LOADER_DATA, and the
kernel only memblock_reserve()'s the actual size of the FDT, so the
unused space will be released back to the kernel.

Reviewed-By: Jeffrey Hugo 
Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h   |  1 +
 drivers/firmware/efi/libstub/fdt.c | 57 --
 2 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 083a52d3..8f3043a 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_EFI_H
 #define _ASM_EFI_H
 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 260c4b4..41f457b 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -206,6 +206,10 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
+#ifndef MAX_FDT_SIZE
+#define MAX_FDT_SIZE   SZ_2M
+#endif
+
 /*
  * Allocate memory for a new FDT, then add EFI, commandline, and
  * initrd related fields to the FDT.  This routine increases the
@@ -233,7 +237,6 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
u32 desc_ver;
unsigned long mmap_key;
efi_memory_desc_t *memory_map, *runtime_map;
-   unsigned long new_fdt_size;
efi_status_t status;
int runtime_entry_count = 0;
struct efi_boot_memmap map;
@@ -262,41 +265,29 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
   "Exiting boot services and installing virtual address map...\n");
 
map.map = _map;
+   status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
+   new_fdt_addr, max_addr);
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table,
+  "Unable to allocate memory for new device tree.\n");
+   goto fail;
+   }
+
/*
-* Estimate size of new FDT, and allocate memory for it. We
-* will allocate a bigger buffer if this ends up being too
-* small, so a rough guess is OK here.
+* Now that we have done our final memory allocation (and free)
+* we can get the memory map key needed for exit_boot_services().
 */
-   new_fdt_size = fdt_size + EFI_PAGE_SIZE;
-   while (1) {
-   status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
-   new_fdt_addr, max_addr);
-   if (status != EFI_SUCCESS) {
-   pr_efi_err(sys_table, "Unable to allocate memory for 
new device tree.\n");
-   goto fail;
-   }
-
-   status = update_fdt(sys_table,
-   (void *)fdt_addr, fdt_size,
-   (void *)*new_fdt_addr, new_fdt_size,
-   cmdline_ptr, initrd_addr, initrd_size);
+   status = efi_get_memory_map(sys_table, );
+   if (status != EFI_SUCCESS)
+   goto fail_free_new_fdt;
 
-   /* Succeeding the first time is the expected case. */
-   if (status == EFI_SUCCESS)
-   break;
+   status = update_fdt(sys_table, (void *)fdt_addr, fdt_size,
+   (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
+   initrd_addr, initrd_size);
 
-   if (status == EFI_BUFFER_TOO_SMALL) {
-   /*
-* We need to allocate more space for the new
-

[tip:efi/core] efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b27aef2499e8c5af11aee9c239029ca4dbe162ed
Gitweb: http://git.kernel.org/tip/b27aef2499e8c5af11aee9c239029ca4dbe162ed
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:09 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:55 +0200

efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

The EFI stub currently prints a number of diagnostic messages that do
not carry a lot of information. Since these prints are not controlled
by 'loglevel' or other command line parameters, and since they appear on
the EFI framebuffer as well (if enabled), it would be nice if we could
turn them off.

So let's add support for the 'quiet' command line parameter in the stub,
and disable the non-error prints if it is passed.

Signed-off-by: Ard Biesheuvel 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 20 ++--
 drivers/firmware/efi/libstub/arm32-stub.c  |  2 ++
 drivers/firmware/efi/libstub/efi-stub-helper.c |  9 +
 drivers/firmware/efi/libstub/efistub.h |  7 +++
 drivers/firmware/efi/libstub/secureboot.c  |  2 ++
 include/linux/efi.h|  3 ---
 6 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index ac3222f..657bb72 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -116,8 +116,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
 
-   pr_efi(sys_table, "Booting Linux Kernel...\n");
-
status = check_platform_features(sys_table);
if (status != EFI_SUCCESS)
goto fail;
@@ -151,6 +149,16 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
+
+   pr_efi(sys_table, "Booting Linux Kernel...\n");
+
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, _size,
@@ -162,14 +170,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
-   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
-   cmdline_size == 0)
-   efi_parse_options(CONFIG_CMDLINE);
-
-   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
-   efi_parse_options(cmdline_ptr);
-
secure_boot = efi_get_secureboot(sys_table);
 
/*
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index 18a8b5e..becbda4 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -9,6 +9,8 @@
 #include 
 #include 
 
+#include "efistub.h"
+
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
int block;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 2e17d2b..b018436 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -33,11 +33,16 @@
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
 static int __section(.data) __nokaslr;
+static int __section(.data) __quiet;
 
 int __pure nokaslr(void)
 {
return __nokaslr;
 }
+int __pure is_quiet(void)
+{
+   return __quiet;
+}
 
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
@@ -424,6 +429,10 @@ efi_status_t efi_parse_options(char const *cmdline)
if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
__nokaslr = 1;
 
+   str = strstr(cmdline, "quiet");
+   if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
+   __quiet = 1;
+
/*
 * If no EFI parameters were specified on the cmdline we've got
 * nothing to do.
diff --git 

[tip:efi/core] ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  170bd898f1ae1ad717d56053846f8bbd2e526045
Gitweb: http://git.kernel.org/tip/170bd898f1ae1ad717d56053846f8bbd2e526045
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:10 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:55 +0200

ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

Update the allocation logic for the virtual mapping of the UEFI runtime
services to start from a randomized base address if KASLR is in effect,
and if the UEFI firmware exposes an implementation of EFI_RNG_PROTOCOL.

This makes it more difficult to predict the location of exploitable
data structures in the runtime UEFI firmware, which increases robustness
against attacks. Note that these regions are only mapped during the
time a runtime service call is in progress, and only on a single CPU
at a time, bit given the lack of a downside, let's enable it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 49 -
 1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 657bb72..1e45ec5 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,6 +18,22 @@
 
 #include "efistub.h"
 
+/*
+ * This is the base address at which to start allocating virtual memory ranges
+ * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
+ * any allocation we choose, and eliminate the risk of a conflict after kexec.
+ * The value chosen is the largest non-zero power of 2 suitable for this 
purpose
+ * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
+ * be mapped efficiently.
+ * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
+ * map everything below 1 GB. (512 MB is a reasonable upper bound for the
+ * entire footprint of the UEFI runtime services memory regions)
+ */
+#define EFI_RT_VIRTUAL_BASESZ_512M
+#define EFI_RT_VIRTUAL_SIZESZ_512M
+
+static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
+
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -213,6 +229,25 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 
efi_random_get_seed(sys_table);
 
+   if (!nokaslr()) {
+   /*
+* Randomize the base of the UEFI runtime services region.
+* Preserve the 2 MB alignment of the region by taking a
+* shift of 21 bit positions into account when scaling
+* the headroom value using a 32-bit random value.
+*/
+   u64 headroom = TASK_SIZE - EFI_RT_VIRTUAL_BASE -
+  EFI_RT_VIRTUAL_SIZE;
+   u32 rnd;
+
+   status = efi_get_random_bytes(sys_table, sizeof(rnd),
+ (u8 *));
+   if (status == EFI_SUCCESS) {
+   virtmap_base = EFI_RT_VIRTUAL_BASE +
+  (((headroom >> 21) * rnd) >> (32 - 21));
+   }
+   }
+
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
_fdt_addr, efi_get_max_fdt_addr(dram_base),
@@ -242,18 +277,6 @@ fail:
return EFI_ERROR;
 }
 
-/*
- * This is the base address at which to start allocating virtual memory ranges
- * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
- * any allocation we choose, and eliminate the risk of a conflict after kexec.
- * The value chosen is the largest non-zero power of 2 suitable for this 
purpose
- * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
- * be mapped efficiently.
- * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
- * map everything below 1 GB.
- */
-#define EFI_RT_VIRTUAL_BASESZ_512M
-
 static int cmp_mem_desc(const void *l, const void *r)
 {
const efi_memory_desc_t *left = l, *right = r;
@@ -303,7 +326,7 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, 
unsigned long map_size,
 unsigned long desc_size, efi_memory_desc_t 

[tip:efi/core] efi/libstub: Unify command line param parsing

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  794e5ecb8c444bcc7e42b82e3ae7a457987949d3
Gitweb: http://git.kernel.org/tip/794e5ecb8c444bcc7e42b82e3ae7a457987949d3
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:08 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:54 +0200

efi/libstub: Unify command line param parsing

Merge the parsing of the command line carried out in arm-stub.c with
the handling in efi_parse_options(). Note that this also fixes the
missing handling of CONFIG_CMDLINE_FORCE=y, in which case the builtin
command line should supersede the one passed by the firmware.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-1-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 24 +++-
 drivers/firmware/efi/libstub/arm64-stub.c  |  4 +---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 19 +++
 drivers/firmware/efi/libstub/efistub.h |  2 ++
 include/linux/efi.h|  2 +-
 5 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 02049ff..ac3222f 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,8 +18,6 @@
 
 #include "efistub.h"
 
-bool __nokaslr;
-
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -153,18 +151,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
-   /* check whether 'nokaslr' was passed on the command line */
-   if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   static const u8 default_cmdline[] = CONFIG_CMDLINE;
-   const u8 *str, *cmdline = cmdline_ptr;
-
-   if (IS_ENABLED(CONFIG_CMDLINE_FORCE))
-   cmdline = default_cmdline;
-   str = strstr(cmdline, "nokaslr");
-   if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
-   __nokaslr = true;
-   }
-
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, _size,
@@ -176,9 +162,13 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   status = efi_parse_options(cmdline_ptr);
-   if (status != EFI_SUCCESS)
-   pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
 
secure_boot = efi_get_secureboot(sys_table);
 
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index eae693e..b4c2589 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -16,8 +16,6 @@
 
 #include "efistub.h"
 
-extern bool __nokaslr;
-
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
u64 tg;
@@ -52,7 +50,7 @@ efi_status_t handle_kernel_image(efi_system_table_t 
*sys_table_arg,
u64 phys_seed = 0;
 
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   if (!__nokaslr) {
+   if (!nokaslr()) {
status = efi_get_random_bytes(sys_table_arg,
  sizeof(phys_seed),
  (u8 *)_seed);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 3290fae..2e17d2b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,6 +32,13 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
+static int __section(.data) __nokaslr;
+
+int __pure nokaslr(void)
+{
+   return __nokaslr;
+}
+
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
 struct file_info {
@@ -409,17 +416,13 @@ static efi_status_t efi_file_close(void *handle)
  * environments, first in the early boot environment of the EFI boot
  * stub, and subsequently during the kernel boot.
  */

[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Gitweb: http://git.kernel.org/tip/0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:52 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= _map,
+   .map_size   = _size,
+   .desc_size  = _size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = _size,
+   };
+
+   /*
+* Reserve memory for the uncompressed kernel image. This is
+* all that prevents any future allocations from conflicting
+* with the kernel. Since we can't tell from the compressed
+* image how much DRAM the kernel actually uses (due to BSS
+* size uncertainty) we allocate the maximum possible size.
+* Do this very early, as prints can cause memory allocations
+* that may conflict with this.
+*/
+   alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, _addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, );
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 

[tip:efi/core] efi/libstub: Fix harmless command line parsing bug

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  935061e3a7de5eae398327de9f7b92588bfcf7fc
Gitweb: http://git.kernel.org/tip/935061e3a7de5eae398327de9f7b92588bfcf7fc
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:45 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:53 +0200

efi/libstub: Fix harmless command line parsing bug

When we parse the 'efi=' command line parameter in the stub, we
fail to take spaces into account. Currently, the only way this
could result in unexpected behavior is when the string 'nochunk'
appears as a separate command line argument after 'efi=xxx,yyy,zzz ',
so this is harmless in practice. But let's fix it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-12-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 919822b..3290fae 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -436,14 +436,14 @@ efi_status_t efi_parse_options(char *cmdline)
 * Remember, because efi= is also used by the kernel we need to
 * skip over arguments we don't understand.
 */
-   while (*str) {
+   while (*str && *str != ' ') {
if (!strncmp(str, "nochunk", 7)) {
str += strlen("nochunk");
__chunk_size = -1UL;
}
 
/* Group words together, delimited by "," */
-   while (*str && *str != ',')
+   while (*str && *str != ' ' && *str != ',')
str++;
 
if (*str == ',')


[tip:efi/urgent] efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  55d728a40d368ba80443be85c02e641fc9082a3f
Gitweb: http://git.kernel.org/tip/55d728a40d368ba80443be85c02e641fc9082a3f
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 16:27:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:25:53 +0200

efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

On UEFI systems, the PCI subsystem is enumerated by the firmware,
and if a graphical framebuffer is exposed via a PCI device, its base
address and size are exposed to the OS via the Graphics Output
Protocol (GOP).

On arm64 PCI systems, the entire PCI hierarchy is reconfigured from
scratch at boot. This may result in the GOP framebuffer address to
become stale, if the BAR covering the framebuffer is modified. This
will cause the framebuffer to become unresponsive, and may in some
cases result in unpredictable behavior if the range is reassigned to
another device.

So add a non-x86 quirk to the EFI fb driver to find the BAR associated
with the GOP base address, and claim the BAR resource so that the PCI
core will not move it.

Signed-off-by: Ard Biesheuvel 
Cc:  # v4.7+
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: lorenzo.pieral...@arm.com
Fixes: 9822504c1fa5 ("efifb: Enable the efi-framebuffer platform driver ...")
Link: http://lkml.kernel.org/r/20170404152744.26687-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 66 -
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 8c4dc1e..b827a81 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -143,6 +144,8 @@ static struct attribute *efifb_attrs[] = {
 };
 ATTRIBUTE_GROUPS(efifb);
 
+static bool pci_dev_disabled;  /* FB base matches BAR of a disabled device */
+
 static int efifb_probe(struct platform_device *dev)
 {
struct fb_info *info;
@@ -152,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
unsigned int size_total;
char *option = NULL;
 
-   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
 
if (fb_get_options("efifb", ))
@@ -360,3 +363,64 @@ static struct platform_driver efifb_driver = {
 };
 
 builtin_platform_driver(efifb_driver);
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_X86)
+
+static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+
+static void claim_efifb_bar(struct pci_dev *dev, int idx)
+{
+   u16 word;
+
+   pci_bar_found = true;
+
+   pci_read_config_word(dev, PCI_COMMAND, );
+   if (!(word & PCI_COMMAND_MEMORY)) {
+   pci_dev_disabled = true;
+   dev_err(>dev,
+   "BAR %d: assigned to efifb but device is disabled!\n",
+   idx);
+   return;
+   }
+
+   if (pci_claim_resource(dev, idx)) {
+   pci_dev_disabled = true;
+   dev_err(>dev,
+   "BAR %d: failed to claim resource for efifb!\n", idx);
+   return;
+   }
+
+   dev_info(>dev, "BAR %d: assigned to efifb\n", idx);
+}
+
+static void efifb_fixup_resources(struct pci_dev *dev)
+{
+   u64 base = screen_info.lfb_base;
+   u64 size = screen_info.lfb_size;
+   int i;
+
+   if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   return;
+
+   if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+   base |= (u64)screen_info.ext_lfb_base << 32;
+
+   if (!base)
+   return;
+
+   for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
+   struct resource *res = >resource[i];
+
+   if (!(res->flags & IORESOURCE_MEM))
+   continue;
+
+   if (res->start <= base && res->end >= base + size - 1) {
+   claim_efifb_bar(dev, i);
+   break;
+   }
+   }
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
+  16, efifb_fixup_resources);
+
+#endif


[tip:efi/core] efi/arm-stub: Correct FDT and initrd allocation rules for arm64

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  138728dd4ee30d3f35587c269c46cc829ec4d58b
Gitweb: http://git.kernel.org/tip/138728dd4ee30d3f35587c269c46cc829ec4d58b
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:37 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:23 +0200

efi/arm-stub: Correct FDT and initrd allocation rules for arm64

On arm64, we have made some changes over the past year to the way the
kernel itself is allocated and to how it deals with the initrd and FDT.
This patch brings the allocation logic in the EFI stub in line with that,
which is necessary because the introduction of KASLR has created the
possibility for the initrd to be allocated in a place where the kernel
may not be able to map it. (This is mostly a theoretical scenario, since
it only affects systems where the physical memory footprint exceeds the
size of the linear mapping.)

Since we know the kernel itself will be covered by the linear mapping,
choose a suitably sized window (i.e., based on the size of the linear
region) covering the kernel when allocating memory for the initrd.

The FDT may be anywhere in memory on arm64 now that we map it via the
fixmap, so we can lift the address restriction there completely.

Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Jeffrey Hugo 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/include/asm/efi.h  | 14 +-
 arch/arm64/include/asm/efi.h| 23 ++-
 drivers/firmware/efi/libstub/arm-stub.c |  7 ---
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index e4e6a9d6..17f1f1a 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info 
*si, const char *opt)
  */
 #define ZIMAGE_OFFSET_LIMITSZ_128M
 #define MIN_ZIMAGE_OFFSET  MAX_UNCOMP_KERNEL_SIZE
-#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT
+
+/* on ARM, the FDT should be located in the first 128 MB of RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return dram_base + ZIMAGE_OFFSET_LIMIT;
+}
+
+/* on ARM, the initrd should be loaded in a lowmem region */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return dram_base + SZ_512M;
+}
 
 #endif /* _ASM_ARM_EFI_H */
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index e744528..083a52d3 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -46,7 +46,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, 
efi_memory_desc_t *md);
  * 2MiB so we know it won't cross a 2MiB boundary.
  */
 #define EFI_FDT_ALIGN  SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
-#define MAX_FDT_OFFSET SZ_512M
+
+/* on arm64, the FDT may be located anywhere in system RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return ULONG_MAX;
+}
+
+/*
+ * On arm64, we have to ensure that the initrd ends up in the linear region,
+ * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is
+ * guaranteed to cover the kernel Image.
+ *
+ * Since the EFI stub is part of the kernel Image, we can relax the
+ * usual requirements in Documentation/arm64/booting.txt, which still
+ * apply to other bootloaders, and are required for some kernel
+ * configurations.
+ */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1));
+}
 
 #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
 #define __efi_call_early(f, ...)   f(__VA_ARGS__)
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index d4056c6..02049ff 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -213,8 +213,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (!fdt_addr)
pr_efi(sys_table, "Generating empty DTB\n");
 
-   status = handle_cmdline_files(sys_table, image, cmdline_ptr,
- "initrd=", dram_base + SZ_512M,
+   status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
+ 

[tip:efi/core] efi/arm-stub: Round up FDT allocation to mapping size

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  24d7c494ce46d5bb6c8fd03e88a48ae249ec1492
Gitweb: http://git.kernel.org/tip/24d7c494ce46d5bb6c8fd03e88a48ae249ec1492
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:39 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:24 +0200

efi/arm-stub: Round up FDT allocation to mapping size

The FDT is mapped via a fixmap entry that is at least 2 MB in size and
2 MB aligned on 4 KB page size kernels.

On UEFI systems, the FDT allocation may share this 2 MB mapping with a
reserved region (or another memory region that we should never map),
unless we account for this in the size of the allocation (the alignment
is already 2 MB)

So instead of taking guesses at the needed space, simply allocate 2 MB
immediately. The allocation will be recorded as EFI_LOADER_DATA, and the
kernel only memblock_reserve()'s the actual size of the FDT, so the
unused space will be released back to the kernel.

Reviewed-By: Jeffrey Hugo 
Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h   |  1 +
 drivers/firmware/efi/libstub/fdt.c | 57 --
 2 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 083a52d3..8f3043a 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_EFI_H
 #define _ASM_EFI_H
 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 260c4b4..41f457b 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -206,6 +206,10 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
+#ifndef MAX_FDT_SIZE
+#define MAX_FDT_SIZE   SZ_2M
+#endif
+
 /*
  * Allocate memory for a new FDT, then add EFI, commandline, and
  * initrd related fields to the FDT.  This routine increases the
@@ -233,7 +237,6 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
u32 desc_ver;
unsigned long mmap_key;
efi_memory_desc_t *memory_map, *runtime_map;
-   unsigned long new_fdt_size;
efi_status_t status;
int runtime_entry_count = 0;
struct efi_boot_memmap map;
@@ -262,41 +265,29 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
   "Exiting boot services and installing virtual address map...\n");
 
map.map = _map;
+   status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
+   new_fdt_addr, max_addr);
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table,
+  "Unable to allocate memory for new device tree.\n");
+   goto fail;
+   }
+
/*
-* Estimate size of new FDT, and allocate memory for it. We
-* will allocate a bigger buffer if this ends up being too
-* small, so a rough guess is OK here.
+* Now that we have done our final memory allocation (and free)
+* we can get the memory map key needed for exit_boot_services().
 */
-   new_fdt_size = fdt_size + EFI_PAGE_SIZE;
-   while (1) {
-   status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
-   new_fdt_addr, max_addr);
-   if (status != EFI_SUCCESS) {
-   pr_efi_err(sys_table, "Unable to allocate memory for 
new device tree.\n");
-   goto fail;
-   }
-
-   status = update_fdt(sys_table,
-   (void *)fdt_addr, fdt_size,
-   (void *)*new_fdt_addr, new_fdt_size,
-   cmdline_ptr, initrd_addr, initrd_size);
+   status = efi_get_memory_map(sys_table, );
+   if (status != EFI_SUCCESS)
+   goto fail_free_new_fdt;
 
-   /* Succeeding the first time is the expected case. */
-   if (status == EFI_SUCCESS)
-   break;
+   status = update_fdt(sys_table, (void *)fdt_addr, fdt_size,
+   (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
+   initrd_addr, initrd_size);
 
-   if (status == EFI_BUFFER_TOO_SMALL) {
-   /*
-* We need to allocate more space for the new
-

[tip:efi/core] efi/libstub: Fix harmless command line parsing bug

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  4c3f14bb87b683a2e5bbc6d6660b41893ecacfd0
Gitweb: http://git.kernel.org/tip/4c3f14bb87b683a2e5bbc6d6660b41893ecacfd0
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:45 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:27 +0200

efi/libstub: Fix harmless command line parsing bug

When we parse the 'efi=' command line parameter in the stub, we
fail to take spaces into account. Currently, the only way this
could result in unexpected behavior is when the string 'nochunk'
appears as a separate command line argument after 'efi=xxx,yyy,zzz ',
so this is harmless in practice. But let's fix it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-12-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 919822b..3290fae 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -436,14 +436,14 @@ efi_status_t efi_parse_options(char *cmdline)
 * Remember, because efi= is also used by the kernel we need to
 * skip over arguments we don't understand.
 */
-   while (*str) {
+   while (*str && *str != ' ') {
if (!strncmp(str, "nochunk", 7)) {
str += strlen("nochunk");
__chunk_size = -1UL;
}
 
/* Group words together, delimited by "," */
-   while (*str && *str != ',')
+   while (*str && *str != ' ' && *str != ',')
str++;
 
if (*str == ',')


[tip:efi/core] efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  eeff7d634f4750306785be709ca444140c29b043
Gitweb: http://git.kernel.org/tip/eeff7d634f4750306785be709ca444140c29b043
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:09 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:28 +0200

efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

The EFI stub currently prints a number of diagnostic messages that do
not carry a lot of information. Since these prints are not controlled
by 'loglevel' or other command line parameters, and since they appear on
the EFI framebuffer as well (if enabled), it would be nice if we could
turn them off.

So let's add support for the 'quiet' command line parameter in the stub,
and disable the non-error prints if it is passed.

Signed-off-by: Ard Biesheuvel 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 20 ++--
 drivers/firmware/efi/libstub/arm32-stub.c  |  2 ++
 drivers/firmware/efi/libstub/efi-stub-helper.c |  9 +
 drivers/firmware/efi/libstub/efistub.h |  7 +++
 drivers/firmware/efi/libstub/secureboot.c  |  2 ++
 include/linux/efi.h|  3 ---
 6 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index ac3222f..657bb72 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -116,8 +116,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
 
-   pr_efi(sys_table, "Booting Linux Kernel...\n");
-
status = check_platform_features(sys_table);
if (status != EFI_SUCCESS)
goto fail;
@@ -151,6 +149,16 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
+
+   pr_efi(sys_table, "Booting Linux Kernel...\n");
+
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, _size,
@@ -162,14 +170,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
-   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
-   cmdline_size == 0)
-   efi_parse_options(CONFIG_CMDLINE);
-
-   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
-   efi_parse_options(cmdline_ptr);
-
secure_boot = efi_get_secureboot(sys_table);
 
/*
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index 18a8b5e..becbda4 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -9,6 +9,8 @@
 #include 
 #include 
 
+#include "efistub.h"
+
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
int block;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 2e17d2b..b018436 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -33,11 +33,16 @@
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
 static int __section(.data) __nokaslr;
+static int __section(.data) __quiet;
 
 int __pure nokaslr(void)
 {
return __nokaslr;
 }
+int __pure is_quiet(void)
+{
+   return __quiet;
+}
 
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
@@ -424,6 +429,10 @@ efi_status_t efi_parse_options(char const *cmdline)
if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
__nokaslr = 1;
 
+   str = strstr(cmdline, "quiet");
+   if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
+   __quiet = 1;
+
/*
 * If no EFI parameters were specified on the cmdline we've got
 * nothing to do.
diff --git 

[tip:efi/core] ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e69176d68d26d63d9214797c191ce65358ea1ecf
Gitweb: http://git.kernel.org/tip/e69176d68d26d63d9214797c191ce65358ea1ecf
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:10 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:29 +0200

ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

Update the allocation logic for the virtual mapping of the UEFI runtime
services to start from a randomized base address if KASLR is in effect,
and if the UEFI firmware exposes an implementation of EFI_RNG_PROTOCOL.

This makes it more difficult to predict the location of exploitable
data structures in the runtime UEFI firmware, which increases robustness
against attacks. Note that these regions are only mapped during the
time a runtime service call is in progress, and only on a single CPU
at a time, bit given the lack of a downside, let's enable it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 49 -
 1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 657bb72..1e45ec5 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,6 +18,22 @@
 
 #include "efistub.h"
 
+/*
+ * This is the base address at which to start allocating virtual memory ranges
+ * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
+ * any allocation we choose, and eliminate the risk of a conflict after kexec.
+ * The value chosen is the largest non-zero power of 2 suitable for this 
purpose
+ * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
+ * be mapped efficiently.
+ * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
+ * map everything below 1 GB. (512 MB is a reasonable upper bound for the
+ * entire footprint of the UEFI runtime services memory regions)
+ */
+#define EFI_RT_VIRTUAL_BASESZ_512M
+#define EFI_RT_VIRTUAL_SIZESZ_512M
+
+static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
+
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -213,6 +229,25 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 
efi_random_get_seed(sys_table);
 
+   if (!nokaslr()) {
+   /*
+* Randomize the base of the UEFI runtime services region.
+* Preserve the 2 MB alignment of the region by taking a
+* shift of 21 bit positions into account when scaling
+* the headroom value using a 32-bit random value.
+*/
+   u64 headroom = TASK_SIZE - EFI_RT_VIRTUAL_BASE -
+  EFI_RT_VIRTUAL_SIZE;
+   u32 rnd;
+
+   status = efi_get_random_bytes(sys_table, sizeof(rnd),
+ (u8 *));
+   if (status == EFI_SUCCESS) {
+   virtmap_base = EFI_RT_VIRTUAL_BASE +
+  (((headroom >> 21) * rnd) >> (32 - 21));
+   }
+   }
+
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
_fdt_addr, efi_get_max_fdt_addr(dram_base),
@@ -242,18 +277,6 @@ fail:
return EFI_ERROR;
 }
 
-/*
- * This is the base address at which to start allocating virtual memory ranges
- * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
- * any allocation we choose, and eliminate the risk of a conflict after kexec.
- * The value chosen is the largest non-zero power of 2 suitable for this 
purpose
- * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
- * be mapped efficiently.
- * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
- * map everything below 1 GB.
- */
-#define EFI_RT_VIRTUAL_BASESZ_512M
-
 static int cmp_mem_desc(const void *l, const void *r)
 {
const efi_memory_desc_t *left = l, *right = r;
@@ -303,7 +326,7 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, 
unsigned long map_size,
 unsigned long desc_size, efi_memory_desc_t 

[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  318532bf63cfab779d763527d8b93e48c4a96dba
Gitweb: http://git.kernel.org/tip/318532bf63cfab779d763527d8b93e48c4a96dba
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:26 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= _map,
+   .map_size   = _size,
+   .desc_size  = _size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = _size,
+   };
+
+   /*
+* Reserve memory for the uncompressed kernel image. This is
+* all that prevents any future allocations from conflicting
+* with the kernel. Since we can't tell from the compressed
+* image how much DRAM the kernel actually uses (due to BSS
+* size uncertainty) we allocate the maximum possible size.
+* Do this very early, as prints can cause memory allocations
+* that may conflict with this.
+*/
+   alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, _addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, );
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 

[tip:efi/core] efi/libstub: Unify command line param parsing

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  60f38de7a8d4e816100ceafd1b382df52527bd50
Gitweb: http://git.kernel.org/tip/60f38de7a8d4e816100ceafd1b382df52527bd50
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:08 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:28 +0200

efi/libstub: Unify command line param parsing

Merge the parsing of the command line carried out in arm-stub.c with
the handling in efi_parse_options(). Note that this also fixes the
missing handling of CONFIG_CMDLINE_FORCE=y, in which case the builtin
command line should supersede the one passed by the firmware.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-1-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 24 +++-
 drivers/firmware/efi/libstub/arm64-stub.c  |  4 +---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 19 +++
 drivers/firmware/efi/libstub/efistub.h |  2 ++
 include/linux/efi.h|  2 +-
 5 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 02049ff..ac3222f 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,8 +18,6 @@
 
 #include "efistub.h"
 
-bool __nokaslr;
-
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -153,18 +151,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
-   /* check whether 'nokaslr' was passed on the command line */
-   if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   static const u8 default_cmdline[] = CONFIG_CMDLINE;
-   const u8 *str, *cmdline = cmdline_ptr;
-
-   if (IS_ENABLED(CONFIG_CMDLINE_FORCE))
-   cmdline = default_cmdline;
-   str = strstr(cmdline, "nokaslr");
-   if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
-   __nokaslr = true;
-   }
-
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, _size,
@@ -176,9 +162,13 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   status = efi_parse_options(cmdline_ptr);
-   if (status != EFI_SUCCESS)
-   pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
 
secure_boot = efi_get_secureboot(sys_table);
 
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index eae693e..b4c2589 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -16,8 +16,6 @@
 
 #include "efistub.h"
 
-extern bool __nokaslr;
-
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
u64 tg;
@@ -52,7 +50,7 @@ efi_status_t handle_kernel_image(efi_system_table_t 
*sys_table_arg,
u64 phys_seed = 0;
 
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   if (!__nokaslr) {
+   if (!nokaslr()) {
status = efi_get_random_bytes(sys_table_arg,
  sizeof(phys_seed),
  (u8 *)_seed);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 3290fae..2e17d2b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,6 +32,13 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
+static int __section(.data) __nokaslr;
+
+int __pure nokaslr(void)
+{
+   return __nokaslr;
+}
+
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
 struct file_info {
@@ -409,17 +416,13 @@ static efi_status_t efi_file_close(void *handle)
  * environments, first in the early boot environment of the EFI boot
  * stub, and subsequently during the kernel boot.
  */

[tip:efi/core] efi/libstub/arm: Don't use TASK_SIZE when randomizing the RT space

2017-04-18 Thread tip-bot for Ard Biesheuvel
Commit-ID:  197decefdb79d6f1350ba0316ce26ba737372d0c
Gitweb: http://git.kernel.org/tip/197decefdb79d6f1350ba0316ce26ba737372d0c
Author: Ard Biesheuvel 
AuthorDate: Mon, 17 Apr 2017 10:32:01 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 17 Apr 2017 12:35:33 +0200

efi/libstub/arm: Don't use TASK_SIZE when randomizing the RT space

As reported by James, Catalin and Mark, commit:

  e69176d68d26 ("ef/libstub/arm/arm64: Randomize the base of the UEFI rt 
services region")

... results in a crash in the firmware, regardless of whether KASLR
is in effect or not and whether the firmware implements EFI_RNG_PROTOCOL
or not.

Mark has identified the root cause to be the inappropriate use of
TASK_SIZE in the stub, which arm64 defines as:

  #define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
TASK_SIZE_32 : TASK_SIZE_64)

and testing thread flags at this point results in the dereference of
pointers in uninitialized structures.

So instead, introduce a preprocessor symbol EFI_RT_VIRTUAL_LIMIT and
define it to TASK_SIZE_64 on arm64 and TASK_SIZE on ARM, both of which
are compile time constants. Also, change the 'headroom' variable to
static const to force an error if this might change in the future.

Tested-by: Mark Rutland 
Tested-by: James Morse 
Tested-by: Catalin Marinas 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170417093201.10181-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 1e45ec5..8181ac1 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -32,6 +32,12 @@
 #define EFI_RT_VIRTUAL_BASESZ_512M
 #define EFI_RT_VIRTUAL_SIZESZ_512M
 
+#ifdef CONFIG_ARM64
+# define EFI_RT_VIRTUAL_LIMIT  TASK_SIZE_64
+#else
+# define EFI_RT_VIRTUAL_LIMIT  TASK_SIZE
+#endif
+
 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
@@ -236,8 +242,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 * shift of 21 bit positions into account when scaling
 * the headroom value using a 32-bit random value.
 */
-   u64 headroom = TASK_SIZE - EFI_RT_VIRTUAL_BASE -
-  EFI_RT_VIRTUAL_SIZE;
+   static const u64 headroom = EFI_RT_VIRTUAL_LIMIT -
+   EFI_RT_VIRTUAL_BASE -
+   EFI_RT_VIRTUAL_SIZE;
u32 rnd;
 
status = efi_get_random_bytes(sys_table, sizeof(rnd),


[tip:efi/core] efi/capsule-loader: Use a cached copy of the capsule header

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  82c3768b8d68c40ecde92338899c838b7c674ffb
Gitweb: http://git.kernel.org/tip/82c3768b8d68c40ecde92338899c838b7c674ffb
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:00 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:40 +0200

efi/capsule-loader: Use a cached copy of the capsule header

Instead of kmapping the capsule data twice, copy the capsule header
into the capsule info struct we keep locally. This is an improvement
by itself, but will also enable handling of non-standard header formats
more easily.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-7-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/capsule-loader.c | 41 +++
 1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index 37d3f6e..5b012a4 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -21,13 +21,13 @@
 #define NO_FURTHER_WRITE_ACTION -1
 
 struct capsule_info {
-   boolheader_obtained;
-   int reset_type;
-   longindex;
-   size_t  count;
-   size_t  total_size;
-   struct page **pages;
-   size_t  page_bytes_remain;
+   efi_capsule_header_theader;
+   int reset_type;
+   longindex;
+   size_t  count;
+   size_t  total_size;
+   struct page **pages;
+   size_t  page_bytes_remain;
 };
 
 /**
@@ -56,7 +56,6 @@ static void efi_free_all_buff_pages(struct capsule_info 
*cap_info)
 static int efi_capsule_setup_info(struct capsule_info *cap_info,
  void *kbuff, size_t hdr_bytes)
 {
-   efi_capsule_header_t *cap_hdr;
size_t pages_needed;
int ret;
void *temp_page;
@@ -66,8 +65,9 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
return 0;
 
/* Reset back to the correct offset of header */
-   cap_hdr = kbuff - cap_info->count;
-   pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT;
+   kbuff -= cap_info->count;
+   memcpy(_info->header, kbuff, sizeof(cap_info->header));
+   pages_needed = ALIGN(cap_info->header.imagesize, PAGE_SIZE) / PAGE_SIZE;
 
if (pages_needed == 0) {
pr_err("invalid capsule size");
@@ -75,15 +75,16 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
}
 
/* Check if the capsule binary supported */
-   ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags,
-   cap_hdr->imagesize,
+   ret = efi_capsule_supported(cap_info->header.guid,
+   cap_info->header.flags,
+   cap_info->header.imagesize,
_info->reset_type);
if (ret) {
pr_err("capsule not supported\n");
return ret;
}
 
-   cap_info->total_size = cap_hdr->imagesize;
+   cap_info->total_size = cap_info->header.imagesize;
temp_page = krealloc(cap_info->pages,
 pages_needed * sizeof(void *),
 GFP_KERNEL | __GFP_ZERO);
@@ -91,7 +92,6 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
return -ENOMEM;
 
cap_info->pages = temp_page;
-   cap_info->header_obtained = true;
 
return 0;
 }
@@ -104,15 +104,8 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
 static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
 {
int ret;
-   void *cap_hdr_temp;
 
-   cap_hdr_temp = vmap(cap_info->pages, cap_info->index,
-   VM_MAP, PAGE_KERNEL);
-   if (!cap_hdr_temp)
-   return -ENOMEM;
-
-   ret = efi_capsule_update(cap_hdr_temp, cap_info->pages);
-   vunmap(cap_hdr_temp);
+   ret = efi_capsule_update(_info->header, cap_info->pages);
if (ret) {
pr_err("capsule update failed\n");
return ret;
@@ -192,7 +185,7 @@ static ssize_t efi_capsule_write(struct file *file, const 
char __user *buff,
cap_info->page_bytes_remain -= write_byte;
 
/* Setup capsule binary info structure */
-   if (!cap_info->header_obtained) {
+   if (cap_info->header.headersize == 0) {
ret = efi_capsule_setup_info(cap_info, kbuff,
   

[tip:efi/core] efi/capsule-loader: Use page addresses rather than struct page pointers

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  2a457fb31df62c6b482f78e4f74aaed99271f44d
Gitweb: http://git.kernel.org/tip/2a457fb31df62c6b482f78e4f74aaed99271f44d
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:03 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:41 +0200

efi/capsule-loader: Use page addresses rather than struct page pointers

To give some leeway to code that handles non-standard capsule headers,
let's keep an array of page addresses rather than struct page pointers.

This gives special implementations of efi_capsule_setup_info() the
opportunity to mangle the payload a bit before it is presented to the
firmware, without putting any knowledge of the nature of such quirks
into the generic code.

Tested-by: Bryan O'Donoghue 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-10-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/capsule-loader.c | 12 
 drivers/firmware/efi/capsule.c|  7 ---
 include/linux/efi.h   |  4 ++--
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index cbc35269..ec8ac5c 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -20,6 +20,10 @@
 
 #define NO_FURTHER_WRITE_ACTION -1
 
+#ifndef phys_to_page
+#define phys_to_page(x)pfn_to_page((x) >> PAGE_SHIFT)
+#endif
+
 /**
  * efi_free_all_buff_pages - free all previous allocated buffer pages
  * @cap_info: pointer to current instance of capsule_info structure
@@ -31,7 +35,7 @@
 static void efi_free_all_buff_pages(struct capsule_info *cap_info)
 {
while (cap_info->index > 0)
-   __free_page(cap_info->pages[--cap_info->index]);
+   __free_page(phys_to_page(cap_info->pages[--cap_info->index]));
 
cap_info->index = NO_FURTHER_WRITE_ACTION;
 }
@@ -161,12 +165,12 @@ static ssize_t efi_capsule_write(struct file *file, const 
char __user *buff,
goto failed;
}
 
-   cap_info->pages[cap_info->index++] = page;
+   cap_info->pages[cap_info->index++] = page_to_phys(page);
cap_info->page_bytes_remain = PAGE_SIZE;
+   } else {
+   page = phys_to_page(cap_info->pages[cap_info->index - 1]);
}
 
-   page = cap_info->pages[cap_info->index - 1];
-
kbuff = kmap(page);
kbuff += PAGE_SIZE - cap_info->page_bytes_remain;
 
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c
index e603ccf..901b930 100644
--- a/drivers/firmware/efi/capsule.c
+++ b/drivers/firmware/efi/capsule.c
@@ -214,7 +214,7 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule,
  *
  * Return 0 on success, a converted EFI status code on failure.
  */
-int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
+int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
 {
u32 imagesize = capsule->imagesize;
efi_guid_t guid = capsule->guid;
@@ -249,10 +249,11 @@ int efi_capsule_update(efi_capsule_header_t *capsule, 
struct page **pages)
sglist = kmap(sg_pages[i]);
 
for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) {
-   u64 sz = min_t(u64, imagesize, PAGE_SIZE);
+   u64 sz = min_t(u64, imagesize,
+  PAGE_SIZE - (u64)*pages % PAGE_SIZE);
 
sglist[j].length = sz;
-   sglist[j].data = page_to_phys(*pages++);
+   sglist[j].data = *pages++;
 
imagesize -= sz;
count--;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index a7379a2..8269bcb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -143,7 +143,7 @@ struct capsule_info {
longindex;
size_t  count;
size_t  total_size;
-   struct page **pages;
+   phys_addr_t *pages;
size_t  page_bytes_remain;
 };
 
@@ -1415,7 +1415,7 @@ 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);
+ phys_addr_t *pages);
 
 #ifdef CONFIG_EFI_RUNTIME_MAP
 int efi_runtime_map_init(struct kobject *);


[tip:efi/core] efi/capsule-loader: Redirect calls to efi_capsule_setup_info() via weak alias

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  3fabd628d5ea24b02ddb1230ffca1df0f779f84e
Gitweb: http://git.kernel.org/tip/3fabd628d5ea24b02ddb1230ffca1df0f779f84e
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:02 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:41 +0200

efi/capsule-loader: Redirect calls to efi_capsule_setup_info() via weak alias

To allow platform specific code to hook into the capsule loading
routines, indirect calls to efi_capsule_setup_info() via a weak alias
of __efi_capsule_setup_info(), allowing platforms to redefine the former
but still use the latter.

Tested-by: Bryan O'Donoghue 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-9-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/capsule-loader.c | 56 +--
 include/linux/efi.h   | 12 
 2 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index 2357bcd..cbc35269 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -20,16 +20,6 @@
 
 #define NO_FURTHER_WRITE_ACTION -1
 
-struct capsule_info {
-   efi_capsule_header_theader;
-   int reset_type;
-   longindex;
-   size_t  count;
-   size_t  total_size;
-   struct page **pages;
-   size_t  page_bytes_remain;
-};
-
 /**
  * efi_free_all_buff_pages - free all previous allocated buffer pages
  * @cap_info: pointer to current instance of capsule_info structure
@@ -46,28 +36,13 @@ static void efi_free_all_buff_pages(struct capsule_info 
*cap_info)
cap_info->index = NO_FURTHER_WRITE_ACTION;
 }
 
-/**
- * efi_capsule_setup_info - obtain the efi capsule header in the binary and
- * setup capsule_info structure
- * @cap_info: pointer to current instance of capsule_info structure
- * @kbuff: a mapped first page buffer pointer
- * @hdr_bytes: the total received number of bytes for efi header
- **/
-static int efi_capsule_setup_info(struct capsule_info *cap_info,
- void *kbuff, size_t hdr_bytes)
+int __efi_capsule_setup_info(struct capsule_info *cap_info)
 {
size_t pages_needed;
int ret;
void *temp_page;
 
-   /* Only process data block that is larger than efi header size */
-   if (hdr_bytes < sizeof(efi_capsule_header_t))
-   return 0;
-
-   /* Reset back to the correct offset of header */
-   kbuff -= cap_info->count;
-   memcpy(_info->header, kbuff, sizeof(cap_info->header));
-   pages_needed = ALIGN(cap_info->header.imagesize, PAGE_SIZE) / PAGE_SIZE;
+   pages_needed = ALIGN(cap_info->total_size, PAGE_SIZE) / PAGE_SIZE;
 
if (pages_needed == 0) {
pr_err("invalid capsule size");
@@ -84,7 +59,6 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
return ret;
}
 
-   cap_info->total_size = cap_info->header.imagesize;
temp_page = krealloc(cap_info->pages,
 pages_needed * sizeof(void *),
 GFP_KERNEL | __GFP_ZERO);
@@ -97,6 +71,30 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
 }
 
 /**
+ * efi_capsule_setup_info - obtain the efi capsule header in the binary and
+ * setup capsule_info structure
+ * @cap_info: pointer to current instance of capsule_info structure
+ * @kbuff: a mapped first page buffer pointer
+ * @hdr_bytes: the total received number of bytes for efi header
+ *
+ * Platforms with non-standard capsule update mechanisms can override
+ * this __weak function so they can perform any required capsule
+ * image munging. See quark_quirk_function() for an example.
+ **/
+int __weak efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff,
+ size_t hdr_bytes)
+{
+   /* Only process data block that is larger than efi header size */
+   if (hdr_bytes < sizeof(efi_capsule_header_t))
+   return 0;
+
+   memcpy(_info->header, kbuff, sizeof(cap_info->header));
+   cap_info->total_size = cap_info->header.imagesize;
+
+   return __efi_capsule_setup_info(cap_info);
+}
+
+/**
  * efi_capsule_submit_update - invoke the efi_capsule_update API once binary
  *upload done
  * @cap_info: pointer to current instance of capsule_info structure
@@ -182,7 +180,7 @@ static ssize_t efi_capsule_write(struct file 

[tip:efi/core] efi/arm: Enable DMI/SMBIOS

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  bb817bef3b1989a9cdb40362cfb8d2aa224ac1bc
Gitweb: http://git.kernel.org/tip/bb817bef3b1989a9cdb40362cfb8d2aa224ac1bc
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:07 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:44 +0200

efi/arm: Enable DMI/SMBIOS

Wire up the existing arm64 support for SMBIOS tables (aka DMI) for ARM as
well, by moving the arm64 init code to drivers/firmware/efi/arm-runtime.c
(which is shared between ARM and arm64), and adding a asm/dmi.h header to
ARM that defines the mapping routines for the firmware tables.

This allows userspace to access these tables to discover system information
exposed by the firmware. It also sets the hardware name used in crash
dumps, e.g.:

  Unable to handle kernel NULL pointer dereference at virtual address 
  pgd = ed3c
  [] *pgd=bf1f3835
  Internal error: Oops: 817 [#1] SMP THUMB2
  Modules linked in:
  CPU: 0 PID: 759 Comm: bash Not tainted 4.10.0-09601-g0e8f38792120-dirty #112
  Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
  ^^^

NOTE: This does *NOT* enable or encourage the use of DMI quirks, i.e., the
  the practice of identifying the platform via DMI to decide whether
  certain workarounds for buggy hardware and/or firmware need to be
  enabled. This would require the DMI subsystem to be enabled much
  earlier than we do on ARM, which is non-trivial.

Signed-off-by: Ard Biesheuvel 
Acked-by: Russell King 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-14-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/Kconfig   | 17 +
 arch/arm/include/asm/dmi.h | 19 +++
 arch/arm64/kernel/efi.c| 15 ---
 drivers/firmware/efi/arm-runtime.c | 16 
 4 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4c1a35f..dabcaeb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2061,6 +2061,23 @@ config EFI
  is only useful for kernels that may run on systems that have
  UEFI firmware.
 
+config DMI
+   bool "Enable support for SMBIOS (DMI) tables"
+   depends on EFI
+   default y
+   help
+ This enables SMBIOS/DMI feature for systems.
+
+ This option is only useful on systems that have UEFI firmware.
+ However, even with this option, the resultant kernel should
+ continue to boot on existing non-UEFI platforms.
+
+ NOTE: This does *NOT* enable or encourage the use of DMI quirks,
+ i.e., the the practice of identifying the platform via DMI to
+ decide whether certain workarounds for buggy hardware and/or
+ firmware need to be enabled. This would require the DMI subsystem
+ to be enabled much earlier than we do on ARM, which is non-trivial.
+
 endmenu
 
 menu "CPU Power Management"
diff --git a/arch/arm/include/asm/dmi.h b/arch/arm/include/asm/dmi.h
new file mode 100644
index 000..df2d2ff
--- /dev/null
+++ b/arch/arm/include/asm/dmi.h
@@ -0,0 +1,19 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_DMI_H
+#define __ASM_DMI_H
+
+#include 
+#include 
+
+#define dmi_early_remap(x, l)  memremap(x, l, MEMREMAP_WB)
+#define dmi_early_unmap(x, l)  memunmap(x)
+#define dmi_remap(x, l)memremap(x, l, MEMREMAP_WB)
+#define dmi_unmap(x)   memunmap(x)
+#define dmi_alloc(l)   kzalloc(l, GFP_KERNEL)
+
+#endif
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 5d17f37..82cd075 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -11,7 +11,6 @@
  *
  */
 
-#include 
 #include 
 #include 
 
@@ -117,20 +116,6 @@ int __init efi_set_mapping_permissions(struct mm_struct 
*mm,
   set_permissions, md);
 }
 
-static int __init arm64_dmi_init(void)
-{
-   /*
-* On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to
-* be called early because dmi_id_init(), which is an arch_initcall
-* itself, depends on dmi_scan_machine() having been called already.
-*/
-   dmi_scan_machine();
-   if (dmi_available)
-   dmi_set_dump_stack_arch_desc();
-   return 0;
-}
-core_initcall(arm64_dmi_init);
-
 /*
  * UpdateCapsule() depends on the system being shutdown via
  * ResetSystem().
diff --git a/drivers/firmware/efi/arm-runtime.c 

[tip:efi/core] efi/arm/arm64: Add missing assignment of efi.config_table

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9a9de5c044be14c3337ef45174ac8baa568a0f93
Gitweb: http://git.kernel.org/tip/9a9de5c044be14c3337ef45174ac8baa568a0f93
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:38 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/arm/arm64: Add missing assignment of efi.config_table

The ARM EFI init code never assigns the config_table member of the
efi struct, which means the sysfs device node is missing, and other
in-kernel users will not work correctly. So add the missing assignment.

Note that, for now, the runtime and fw_vendor members are still
omitted. This is deliberate: exposing physical addresses via sysfs nodes
encourages behavior that we would like to avoid on ARM (given how it is
more finicky about using correct memory attributes when mapping memory
in userland that may be mapped by the kernel already as well).

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 0aa4ce7..80d1a88 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -145,6 +145,9 @@ static int __init uefi_init(void)
 sizeof(efi_config_table_t),
 arch_tables);
 
+   if (!retval)
+   efi.config_table = (unsigned long)efi.systab->tables;
+
early_memunmap(config_tables, table_size);
 out:
early_memunmap(efi.systab,  sizeof(efi_system_table_t));


[tip:efi/core] efi/libstub/arm64: Use hidden attribute for struct screen_info reference

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  760b61d76da6d6a99eb245ab61abf71ca5415cea
Gitweb: http://git.kernel.org/tip/760b61d76da6d6a99eb245ab61abf71ca5415cea
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:35 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/libstub/arm64: Use hidden attribute for struct screen_info reference

To prevent the compiler from emitting absolute references to screen_info
when building position independent code, redeclare the symbol with hidden
visibility.

Tested-by: Matthias Kaehlcke 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 8f3043a..464ac85 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -81,6 +81,9 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned 
long dram_base,
 #define alloc_screen_info(x...)_info
 #define free_screen_info(x...)
 
+/* redeclare as 'hidden' so the compiler will generate relative references */
+extern struct screen_info screen_info 
__attribute__((__visibility__("hidden")));
+
 static inline void efifb_setup_from_dmi(struct screen_info *si, const char 
*opt)
 {
 }


[tip:efi/core] efi/libstub/arm64: Force 'hidden' visibility for section markers

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0426a4e68f18d75515414361de9e3e1445d2644e
Gitweb: http://git.kernel.org/tip/0426a4e68f18d75515414361de9e3e1445d2644e
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:36 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/libstub/arm64: Force 'hidden' visibility for section markers

To prevent the compiler from emitting absolute references to the section
markers when running in PIC mode, override the visibility to 'hidden' for
all contents of asm/sections.h

Tested-by: Matthias Kaehlcke 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm64-stub.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index b4c2589..f7a6970 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -9,9 +9,17 @@
  * published by the Free Software Foundation.
  *
  */
+
+/*
+ * To prevent the compiler from emitting GOT-indirected (and thus absolute)
+ * references to the section markers, override their visibility as 'hidden'
+ */
+#pragma GCC visibility push(hidden)
+#include 
+#pragma GCC visibility pop
+
 #include 
 #include 
-#include 
 #include 
 
 #include "efistub.h"


[tip:efi/core] efi/libstub/arm64: Set -fpie when building the EFI stub

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  91ee5b21ee026c49e4e7483de69b55b8b47042be
Gitweb: http://git.kernel.org/tip/91ee5b21ee026c49e4e7483de69b55b8b47042be
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:37 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/libstub/arm64: Set -fpie when building the EFI stub

Clang may emit absolute symbol references when building in non-PIC mode,
even when using the default 'small' code model, which is already mostly
position independent to begin with, due to its use of adrp/add pairs
that have a relative range of +/- 4 GB. The remedy is to pass the -fpie
flag, which can be done safely now that the code has been updated to avoid
GOT indirections (which may be emitted due to the compiler assuming that
the PIC/PIE code may end up in a shared library that is subject to ELF
symbol preemption)

Passing -fpie when building code that needs to execute at an a priori
unknown offset is arguably an improvement in any case, and given that
the recent visibility changes allow the PIC build to pass with GCC as
well, let's add -fpie for all arm64 builds rather than only for Clang.

Tested-by: Matthias Kaehlcke 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index 37e24f5..cf81e6c 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -10,7 +10,7 @@ cflags-$(CONFIG_X86)  += -m$(BITS) -D__KERNEL__ -O2 \
   -fPIC -fno-strict-aliasing -mno-red-zone \
   -mno-mmx -mno-sse
 
-cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
+cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie
 cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
   -fno-builtin -fpic -mno-single-pic-base
 


[tip:efi/core] arm/efi: Replace open coded constants with symbolic ones

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  609eaf0748a5b9dccf3810a2b822a0559f33c0b2
Gitweb: http://git.kernel.org/tip/609eaf0748a5b9dccf3810a2b822a0559f33c0b2
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:43 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

arm/efi: Replace open coded constants with symbolic ones

Replace the various open coded constants in the EFI PE/COFF header with
definitions from pe.h, or expressions based on local symbols.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S | 128 ++
 1 file changed, 67 insertions(+), 61 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index 309d619..542e1ad 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Linaro Ltd
+ * Copyright (C) 2013-2017 Linaro Ltd
  * Authors: Roy Franz 
  *  Ard Biesheuvel 
  *
@@ -8,6 +8,9 @@
  * published by the Free Software Foundation.
  */
 
+#include 
+#include 
+
.macro  __nop
 #ifdef CONFIG_EFI_STUB
@ This is almost but not quite a NOP, since it does clobber the
@@ -15,7 +18,7 @@
@ PE/COFF expects the magic string "MZ" at offset 0, while the
@ ARM/Linux boot protocol expects an executable instruction
@ there.
-   .inst   'M' | ('Z' << 8) | (0x1310 << 16)   @ tstne r0, #0x4d000
+   .inst   MZ_MAGIC | (0x1310 << 16)   @ tstne r0, #0x4d000
 #else
  AR_CLASS( mov r0, r0  )
   M_CLASS( nop.w   )
@@ -34,78 +37,81 @@
@ The only 2 fields of the MSDOS header that are used are this
@ PE/COFF offset, and the "MZ" bytes at offset 0x0.
@
-   .long   pe_header - start   @ Offset to the PE header.
+   .long   pe_header - start   @ Offset to the PE 
header.
 
 pe_header:
-   .ascii  "PE\0\0"
+   .long   PE_MAGIC
 
 coff_header:
-   .short  0x01c2  @ ARM or Thumb
-   .short  1   @ nr_sections
-   .long   0   @ TimeDateStamp
-   .long   0   @ PointerToSymbolTable
-   .long   0   @ NumberOfSymbols
-   .short  section_table - optional_header
-   @ SizeOfOptionalHeader
-   .short  0x306   @ Characteristics.
-   @ IMAGE_FILE_32BIT_MACHINE |
-   @ IMAGE_FILE_DEBUG_STRIPPED |
-   @ IMAGE_FILE_EXECUTABLE_IMAGE |
-   @ IMAGE_FILE_LINE_NUMS_STRIPPED
+   .short  IMAGE_FILE_MACHINE_THUMB@ Machine
+   .short  section_count   @ NumberOfSections
+   .long   0   @ TimeDateStamp
+   .long   0   @ PointerToSymbolTable
+   .long   0   @ NumberOfSymbols
+   .short  section_table - optional_header @ SizeOfOptionalHeader
+   .short  IMAGE_FILE_32BIT_MACHINE | \
+   IMAGE_FILE_DEBUG_STRIPPED | \
+   IMAGE_FILE_EXECUTABLE_IMAGE | \
+   IMAGE_FILE_LINE_NUMS_STRIPPED   @ Characteristics
 
 optional_header:
-   .short  0x10b   @ PE32 format
-   .byte   0x02@ MajorLinkerVersion
-   .byte   0x14@ MinorLinkerVersion
-   .long   _end - __efi_start  @ SizeOfCode
-   .long   0   @ SizeOfInitializedData
-   .long   0   @ SizeOfUninitializedData
-   .long   efi_stub_entry - start  @ AddressOfEntryPoint
-   .long   start_offset@ BaseOfCode
-   .long   0   @ data
+   .short  PE_OPT_MAGIC_PE32   @ PE32 format
+   .byte   0x02@ MajorLinkerVersion
+   .byte   0x14@ MinorLinkerVersion
+   .long   _end - __efi_start  @ SizeOfCode
+ 

[tip:efi/core] arm/efi: Remove forbidden values from the PE/COFF header

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  4415f9f4a6e5c6a4228098fc8289f21f3dda515c
Gitweb: http://git.kernel.org/tip/4415f9f4a6e5c6a4228098fc8289f21f3dda515c
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:41 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

arm/efi: Remove forbidden values from the PE/COFF header

Bring the PE/COFF header in line with the PE/COFF spec, by setting
NumberOfSymbols to 0, and removing the section alignment flags.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-9-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index a17ca8d..4169b90 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -44,7 +44,7 @@ coff_header:
.short  2   @ nr_sections
.long   0   @ TimeDateStamp
.long   0   @ PointerToSymbolTable
-   .long   1   @ NumberOfSymbols
+   .long   0   @ NumberOfSymbols
.short  section_table - optional_header
@ SizeOfOptionalHeader
.short  0x306   @ Characteristics.
@@ -110,7 +110,7 @@ section_table:
.long   0   @ PointerToLineNumbers
.short  0   @ NumberOfRelocations
.short  0   @ NumberOfLineNumbers
-   .long   0x42100040  @ Characteristics
+   .long   0x4240  @ Characteristics
 
.ascii  ".text\0\0\0"
.long   _end - __efi_start  @ VirtualSize
@@ -121,7 +121,7 @@ section_table:
.long   0   @ PointerToLineNumbers
.short  0   @ NumberOfRelocations
.short  0   @ NumberOfLineNumbers
-   .long   0xe0500020  @ Characteristics
+   .long   0xe020  @ Characteristics
 
.align  9
 __efi_start:


[tip:efi/core] drivers/fbdev/efifb: Allow BAR to be moved instead of claiming it

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  dcf8f5ce31656534efada252f6a563c09b295983
Gitweb: http://git.kernel.org/tip/dcf8f5ce31656534efada252f6a563c09b295983
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:40 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

drivers/fbdev/efifb: Allow BAR to be moved instead of claiming it

On UEFI systems, the firmware may expose a Graphics Output Protocol (GOP)
instance to which the efifb driver attempts to attach in order to provide
a minimal, unaccelerated framebuffer. The GOP protocol itself is not very
sophisticated, and only describes the offset and size of the framebuffer
in memory, and the pixel format.

If the GOP framebuffer is provided by a PCI device, it will have been
configured and enabled by the UEFI firmware, and the GOP protocol will
simply point into a live BAR region. However, the GOP protocol itself does
not describe this relation, and so we have to take care not to reconfigure
the BAR without taking efifb's dependency on it into account.

Commit:

  55d728a40d36 ("efi/fb: Avoid reconfiguration of BAR that covers the 
framebuffer")

attempted to do so by claiming the BAR resource early on, which prevents the
PCI resource allocation routines from changing it.  However, it turns out
that this only works if the PCI device is not behind any bridges, since
the bridge resources need to be claimed first.

So instead, allow the BAR to be moved, but make the efifb driver deal
with that gracefully. So record the resource that covers the BAR early
on, and if it turns out to have moved by the time we probe the efifb
driver, update the framebuffer address accordingly.

While this is less likely to occur on x86, given that the firmware's
PCI resource allocation is more likely to be preserved, this is a
worthwhile sanity check to have in place, and so let's remove the
preprocessor conditional that makes it !X86 only.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Peter Jones 
Acked-by: Bartlomiej Zolnierkiewicz 
Acked-by: Bjorn Helgaas 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-8-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 31 ++-
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 1e784ad..3a01064 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -149,6 +149,10 @@ ATTRIBUTE_GROUPS(efifb);
 
 static bool pci_dev_disabled;  /* FB base matches BAR of a disabled device */
 
+static struct pci_dev *efifb_pci_dev;  /* dev with BAR covering the efifb */
+static struct resource *bar_resource;
+static u64 bar_offset;
+
 static int efifb_probe(struct platform_device *dev)
 {
struct fb_info *info;
@@ -203,6 +207,13 @@ static int efifb_probe(struct platform_device *dev)
efifb_fix.smem_start |= ext_lfb_base;
}
 
+   if (bar_resource &&
+   bar_resource->start + bar_offset != efifb_fix.smem_start) {
+   dev_info(_pci_dev->dev,
+"BAR has moved, updating efifb address\n");
+   efifb_fix.smem_start = bar_resource->start + bar_offset;
+   }
+
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
efifb_defined.xres = screen_info.lfb_width;
efifb_defined.yres = screen_info.lfb_height;
@@ -370,15 +381,13 @@ static struct platform_driver efifb_driver = {
 
 builtin_platform_driver(efifb_driver);
 
-#if defined(CONFIG_PCI) && !defined(CONFIG_X86)
-
-static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+#if defined(CONFIG_PCI)
 
-static void claim_efifb_bar(struct pci_dev *dev, int idx)
+static void record_efifb_bar_resource(struct pci_dev *dev, int idx, u64 offset)
 {
u16 word;
 
-   pci_bar_found = true;
+   efifb_pci_dev = dev;
 
pci_read_config_word(dev, PCI_COMMAND, );
if (!(word & PCI_COMMAND_MEMORY)) {
@@ -389,12 +398,8 @@ static void claim_efifb_bar(struct pci_dev *dev, int idx)
return;
}
 
-   if (pci_claim_resource(dev, idx)) {
-   pci_dev_disabled = true;
-   dev_err(>dev,
-   "BAR %d: failed to claim resource for efifb!\n", idx);
-   return;
-   }
+   bar_resource = >resource[idx];
+   bar_offset = offset;
 
dev_info(>dev, "BAR %d: assigned to efifb\n", idx);
 }
@@ -405,7 +410,7 @@ static void efifb_fixup_resources(struct pci_dev *dev)
u64 size = screen_info.lfb_size;
int i;
 
-   if (pci_bar_found || 

[tip:efi/core] arm/efi: Remove pointless dummy .reloc section

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  574cea724cd81f4063491ed1c0534d81a094a913
Gitweb: http://git.kernel.org/tip/574cea724cd81f4063491ed1c0534d81a094a913
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:42 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

arm/efi: Remove pointless dummy .reloc section

The kernel's EFI PE/COFF header contains a dummy .reloc section, and
an explanatory comment that claims that this is required for the EFI
application loader to accept the Image as a relocatable image (i.e.,
one that can be loaded at any offset and fixed up in place)

This was inherited from the x86 implementation, which has elaborate host
tooling to mangle the PE/COFF header post-link time, and which populates
the .reloc section with a single dummy base relocation. On ARM, no such
tooling exists, and the .reloc section remains empty, and is never even
exposed via the BaseRelocationTable directory entry, which is where the
PE/COFF loader looks for it.

The PE/COFF spec is unclear about relocatable images that do not require
any fixups, but the EDK2 implementation, which is the de facto reference
for PE/COFF in the UEFI space, clearly does not care, and explicitly
mentions (in a comment) that relocatable images with no base relocations
are perfectly fine, as long as they don't have the RELOCS_STRIPPED
attribute set (which is not the case for our PE/COFF image)

So simply remove the .reloc section altogether.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-10-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S | 18 +-
 1 file changed, 1 insertion(+), 17 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index 4169b90..309d619 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -41,7 +41,7 @@ pe_header:
 
 coff_header:
.short  0x01c2  @ ARM or Thumb
-   .short  2   @ nr_sections
+   .short  1   @ nr_sections
.long   0   @ TimeDateStamp
.long   0   @ PointerToSymbolTable
.long   0   @ NumberOfSymbols
@@ -96,22 +96,6 @@ extra_header_fields:
.quad   0   @ BaseRelocationTable
 
 section_table:
-   @
-   @ The EFI application loader requires a relocation section
-   @ because EFI applications must be relocatable. This is a
-   @ dummy section as far as we are concerned.
-   @
-   .ascii  ".reloc\0\0"
-   .long   0   @ VirtualSize
-   .long   0   @ VirtualAddress
-   .long   0   @ SizeOfRawData
-   .long   0   @ PointerToRawData
-   .long   0   @ PointerToRelocations
-   .long   0   @ PointerToLineNumbers
-   .short  0   @ NumberOfRelocations
-   .short  0   @ NumberOfLineNumbers
-   .long   0x4240  @ Characteristics
-
.ascii  ".text\0\0\0"
.long   _end - __efi_start  @ VirtualSize
.long   __efi_start @ VirtualAddress


[tip:efi/core] efi/arm: Don't mark ACPI reclaim memory as MEMBLOCK_NOMAP

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f56ab9a5b73ca2aee777ccdf2d355ae2dd31db5a
Gitweb: http://git.kernel.org/tip/f56ab9a5b73ca2aee777ccdf2d355ae2dd31db5a
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:34 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/arm: Don't mark ACPI reclaim memory as MEMBLOCK_NOMAP

On ARM, regions of memory that are described by UEFI as having special
significance to the firmware itself are omitted from the linear mapping.
This is necessary since we cannot guarantee that alternate mappings of
the same physical region will use attributes that are compatible with
the ones we use for the linear mapping, and aliases with mismatched
attributes are prohibited by the architecture.

The above does not apply to ACPI reclaim regions: such regions have no
special significance to the firmware, and it is up to the OS to decide
whether or not to preserve them after it has consumed their contents,
and for how long, after which time the OS can use the memory in any way
it likes. In the Linux case, such regions are preserved indefinitely,
and are simply treated the same way as other 'reserved' memory types.

Punching holes into the linear mapping causes page table fragmentation,
which increases TLB pressure, and so we should avoid doing so if we can.
So add a special case for regions of type EFI_ACPI_RECLAIM_MEMORY, and
memblock_reserve() them instead of marking them MEMBLOCK_NOMAP.

Signed-off-by: Ard Biesheuvel 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 1027d7b4..0aa4ce7 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -159,6 +159,7 @@ static __init int is_usable_memory(efi_memory_desc_t *md)
switch (md->type) {
case EFI_LOADER_CODE:
case EFI_LOADER_DATA:
+   case EFI_ACPI_RECLAIM_MEMORY:
case EFI_BOOT_SERVICES_CODE:
case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY:
@@ -211,6 +212,10 @@ static __init void reserve_regions(void)
 
if (!is_usable_memory(md))
memblock_mark_nomap(paddr, size);
+
+   /* keep ACPI reclaim memory intact for kexec etc. */
+   if (md->type == EFI_ACPI_RECLAIM_MEMORY)
+   memblock_reserve(paddr, size);
}
}
 }


[tip:efi/core] arm/efi: Split zImage code and data into separate PE/COFF sections

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e4bae4d0b5f368dda5bbf1374dca74c1b542d841
Gitweb: http://git.kernel.org/tip/e4bae4d0b5f368dda5bbf1374dca74c1b542d841
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:44 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:51 +0200

arm/efi: Split zImage code and data into separate PE/COFF sections

To prevent unintended modifications to the kernel text (malicious or
otherwise) while running the EFI stub, describe the kernel image as
two separate sections: a .text section with read-execute permissions,
covering .text, .rodata, .piggytext and the GOT sections (which the
stub does not care about anyway), and a .data section with read-write
permissions, covering .data and .bss.

This relies on the firmware to actually take the section permission
flags into account, but this is something that is currently being
implemented in EDK2, which means we will likely start seeing it in
the wild between one and two years from now.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Russell King 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-12-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S  | 32 +++-
 arch/arm/boot/compressed/vmlinux.lds.S | 30 +++---
 2 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index 542e1ad..c94a88a 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -54,20 +54,22 @@ coff_header:
IMAGE_FILE_EXECUTABLE_IMAGE | \
IMAGE_FILE_LINE_NUMS_STRIPPED   @ Characteristics
 
+#define __pecoff_code_size (__pecoff_data_start - __efi_start)
+
 optional_header:
.short  PE_OPT_MAGIC_PE32   @ PE32 format
.byte   0x02@ MajorLinkerVersion
.byte   0x14@ MinorLinkerVersion
-   .long   _end - __efi_start  @ SizeOfCode
-   .long   0   @ SizeOfInitializedData
+   .long   __pecoff_code_size  @ SizeOfCode
+   .long   __pecoff_data_size  @ SizeOfInitializedData
.long   0   @ 
SizeOfUninitializedData
.long   efi_stub_entry - start  @ AddressOfEntryPoint
.long   start_offset@ BaseOfCode
-   .long   0   @ BaseOfData
+   .long   __pecoff_data_start - start @ BaseOfData
 
 extra_header_fields:
.long   0   @ ImageBase
-   .long   SZ_512  @ SectionAlignment
+   .long   SZ_4K   @ SectionAlignment
.long   SZ_512  @ FileAlignment
.short  0   @ MajorOsVersion
.short  0   @ MinorOsVersion
@@ -77,7 +79,7 @@ extra_header_fields:
.short  0   @ MinorSubsystemVersion
.long   0   @ Win32VersionValue
 
-   .long   _end - start@ SizeOfImage
+   .long   __pecoff_end - start@ SizeOfImage
.long   start_offset@ SizeOfHeaders
.long   0   @ CheckSum
.short  IMAGE_SUBSYSTEM_EFI_APPLICATION @ Subsystem
@@ -98,9 +100,9 @@ extra_header_fields:
 
 section_table:
.ascii  ".text\0\0\0"
-   .long   _end - __efi_start  @ VirtualSize
+   .long   __pecoff_code_size  @ VirtualSize
.long   __efi_start @ VirtualAddress
-   .long   _edata - __efi_start@ SizeOfRawData
+   .long   __pecoff_code_size  @ SizeOfRawData
.long   __efi_start @ PointerToRawData
.long   0   @ PointerToRelocations
.long   0   @ PointerToLineNumbers
@@ -108,12 +110,24 @@ section_table:
.short  0   @ NumberOfLineNumbers
.long   IMAGE_SCN_CNT_CODE | \
IMAGE_SCN_MEM_READ | \
-   IMAGE_SCN_MEM_WRITE | \

[tip:efi/core] efi/random: Increase size of firmware supplied randomness

2017-08-26 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c2ceb5fd4e921506e86208b82fca716a2c3aad59
Gitweb: http://git.kernel.org/tip/c2ceb5fd4e921506e86208b82fca716a2c3aad59
Author: Ard Biesheuvel 
AuthorDate: Fri, 25 Aug 2017 16:50:16 +0100
Committer:  Ingo Molnar 
CommitDate: Sat, 26 Aug 2017 09:20:33 +0200

efi/random: Increase size of firmware supplied randomness

The crng code requires at least 64 bytes (2 * CHACHA20_BLOCK_SIZE)
to complete the fast boot-time init, so provide that many bytes
when invoking UEFI protocols to seed the entropy pool. Also, add
a notice so we can tell from the boot log when the seeding actually
took place.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170825155019.6740-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c|  3 ++-
 drivers/firmware/efi/libstub/random.c | 10 --
 include/linux/efi.h   |  2 ++
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a32e146..c8a27a2 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -541,6 +541,7 @@ int __init efi_config_parse_tables(void *config_tables, int 
count, int sz,
if (seed != NULL) {
add_device_randomness(seed->bits, seed->size);
early_memunmap(seed, sizeof(*seed) + size);
+   pr_notice("seeding entropy pool\n");
} else {
pr_err("Could not map UEFI random seed!\n");
}
@@ -900,7 +901,7 @@ static int update_efi_random_seed(struct notifier_block *nb,
 
seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
if (seed != NULL) {
-   size = min(seed->size, 32U);
+   size = min(seed->size, EFI_RANDOM_SEED_SIZE);
memunmap(seed);
} else {
pr_err("Could not map UEFI random seed!\n");
diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index 7e72954..e0e603a 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -145,8 +145,6 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
return status;
 }
 
-#define RANDOM_SEED_SIZE   32
-
 efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
 {
efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
@@ -162,25 +160,25 @@ efi_status_t efi_random_get_seed(efi_system_table_t 
*sys_table_arg)
return status;
 
status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
-   sizeof(*seed) + RANDOM_SEED_SIZE,
+   sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
(void **));
if (status != EFI_SUCCESS)
return status;
 
-   status = rng->get_rng(rng, _algo_raw, RANDOM_SEED_SIZE,
+   status = rng->get_rng(rng, _algo_raw, EFI_RANDOM_SEED_SIZE,
  seed->bits);
if (status == EFI_UNSUPPORTED)
/*
 * Use whatever algorithm we have available if the raw algorithm
 * is not implemented.
 */
-   status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+   status = rng->get_rng(rng, NULL, EFI_RANDOM_SEED_SIZE,
  seed->bits);
 
if (status != EFI_SUCCESS)
goto err_freepool;
 
-   seed->size = RANDOM_SEED_SIZE;
+   seed->size = EFI_RANDOM_SEED_SIZE;
status = efi_call_early(install_configuration_table, _table_guid,
seed);
if (status != EFI_SUCCESS)
diff --git a/include/linux/efi.h b/include/linux/efi.h
index c241acc..33d41df 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1571,6 +1571,8 @@ efi_status_t efi_exit_boot_services(efi_system_table_t 
*sys_table,
void *priv,
efi_exit_boot_map_processing priv_func);
 
+#define EFI_RANDOM_SEED_SIZE   64U
+
 struct linux_efi_random_seed {
u32 size;
u8  bits[];


[tip:efi/urgent] efi/libstub/arm: Don't randomize runtime regions when CONFIG_HIBERNATION=y

2017-10-25 Thread tip-bot for Ard Biesheuvel
Commit-ID:  38fb6652229c2149e8694d57db442878fdf8a1bd
Gitweb: https://git.kernel.org/tip/38fb6652229c2149e8694d57db442878fdf8a1bd
Author: Ard Biesheuvel 
AuthorDate: Wed, 25 Oct 2017 11:04:48 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 25 Oct 2017 12:10:59 +0200

efi/libstub/arm: Don't randomize runtime regions when CONFIG_HIBERNATION=y

Commit:

  e69176d68d26 ("ef/libstub/arm/arm64: Randomize the base of the UEFI rt 
services region")

implemented randomization of the virtual mapping that the OS chooses for
the UEFI runtime services. This was motivated by the fact that UEFI usually
does not bother to specify any permission restrictions for those regions,
making them prime real estate for exploitation now that the OS is getting
more and more careful not to leave any R+W+X mapped regions lying around.

However, this randomization breaks assumptions in the resume from
hibernation code, which expects all memory regions populated by UEFI to
remain in the same place, including their virtual mapping into the OS
memory space. While this assumption may not be entirely reasonable in the
first place, breaking it deliberately does not make a lot of sense either.
So let's refrain from this randomization pass if CONFIG_HIBERNATION=y.

Signed-off-by: Ard Biesheuvel 
Cc: James Morse 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20171025100448.26056-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 1cb2d1c..a94601d 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -238,7 +238,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 
efi_random_get_seed(sys_table);
 
-   if (!nokaslr()) {
+   /* hibernation expects the runtime regions to stay in the same place */
+   if (!IS_ENABLED(CONFIG_HIBERNATION) && !nokaslr()) {
/*
 * Randomize the base of the UEFI runtime services region.
 * Preserve the 2 MB alignment of the region by taking a


[tip:efi/core] efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() into one function

2018-05-14 Thread tip-bot for Ard Biesheuvel
Commit-ID:  2c3625cb9fa2c477d5877a1819e29d6a902e5fef
Gitweb: https://git.kernel.org/tip/2c3625cb9fa2c477d5877a1819e29d6a902e5fef
Author: Ard Biesheuvel 
AuthorDate: Fri, 4 May 2018 08:00:00 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 08:57:49 +0200

efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() into one function

As suggested by Lukas, use his efi_call_proto() and efi_table_attr()
macros to merge __setup_efi_pci32() and __setup_efi_pci64() into a
single function, removing the need to duplicate changes made in
subsequent patches across both.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180504060003.19618-15-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 107 +--
 1 file changed, 25 insertions(+), 82 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 3994f48c4043..dadf32312082 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -109,23 +109,27 @@ void efi_char16_printk(efi_system_table_t *table, 
efi_char16_t *str)
 }
 
 static efi_status_t
-__setup_efi_pci32(efi_pci_io_protocol_32_t *pci, struct pci_setup_rom **__rom)
+__setup_efi_pci(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 {
struct pci_setup_rom *rom = NULL;
efi_status_t status;
unsigned long size;
-   uint64_t attributes;
+   uint64_t attributes, romsize;
+   void *romimage;
 
-   status = efi_early->call(pci->attributes, pci,
-EfiPciIoAttributeOperationGet, 0, 0,
-);
+   status = efi_call_proto(efi_pci_io_protocol, attributes, pci,
+   EfiPciIoAttributeOperationGet, 0, 0,
+   );
if (status != EFI_SUCCESS)
return status;
 
-   if (!pci->romimage || !pci->romsize)
+   romimage = (void *)(unsigned long)efi_table_attr(efi_pci_io_protocol,
+romimage, pci);
+   romsize = efi_table_attr(efi_pci_io_protocol, romsize, pci);
+   if (!romimage || !romsize)
return EFI_INVALID_PARAMETER;
 
-   size = pci->romsize + sizeof(*rom);
+   size = romsize + sizeof(*rom);
 
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, );
if (status != EFI_SUCCESS) {
@@ -141,30 +145,32 @@ __setup_efi_pci32(efi_pci_io_protocol_32_t *pci, struct 
pci_setup_rom **__rom)
rom->pcilen = pci->romsize;
*__rom = rom;
 
-   status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
-PCI_VENDOR_ID, 1, &(rom->vendor));
+   status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
+   EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
+   >vendor);
 
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to read rom->vendor\n");
goto free_struct;
}
 
-   status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
-PCI_DEVICE_ID, 1, &(rom->devid));
+   status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
+   EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
+   >devid);
 
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to read rom->devid\n");
goto free_struct;
}
 
-   status = efi_early->call(pci->get_location, pci, &(rom->segment),
-&(rom->bus), &(rom->device), &(rom->function));
+   status = efi_call_proto(efi_pci_io_protocol, get_location, pci,
+   >segment, >bus, >device,
+   >function);
 
if (status != EFI_SUCCESS)
goto free_struct;
 
-   memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
-  pci->romsize);
+   memcpy(rom->romdata, romimage, romsize);
return status;
 
 free_struct:
@@ -176,7 +182,7 @@ static void
 setup_efi_pci32(struct boot_params *params, void **pci_handle,
unsigned long size)
 {
-   efi_pci_io_protocol_32_t *pci = NULL;
+   efi_pci_io_protocol_t *pci = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
u32 *handles = (u32 *)(unsigned long)pci_handle;
efi_status_t status;
@@ -203,7 +209,7 @@ setup_efi_pci32(struct boot_params *params, void 

[tip:efi/core] efi: Align efi_pci_io_protocol typedefs to type naming convention

2018-05-14 Thread tip-bot for Ard Biesheuvel
Commit-ID:  cb0ba793525788e40e7a9ee82de8f3b017ca4459
Gitweb: https://git.kernel.org/tip/cb0ba793525788e40e7a9ee82de8f3b017ca4459
Author: Ard Biesheuvel 
AuthorDate: Fri, 4 May 2018 07:59:59 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 08:57:48 +0200

efi: Align efi_pci_io_protocol typedefs to type naming convention

In order to use the helper macros that perform type mangling with the
EFI PCI I/O protocol struct typedefs, align their Linux typenames with
the convention we use for definitionns that originate in the UEFI spec,
and add the trailing _t to each.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180504060003.19618-14-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 8 
 include/linux/efi.h  | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 09f36c0d9d4f..3994f48c4043 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -109,7 +109,7 @@ void efi_char16_printk(efi_system_table_t *table, 
efi_char16_t *str)
 }
 
 static efi_status_t
-__setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
+__setup_efi_pci32(efi_pci_io_protocol_32_t *pci, struct pci_setup_rom **__rom)
 {
struct pci_setup_rom *rom = NULL;
efi_status_t status;
@@ -176,7 +176,7 @@ static void
 setup_efi_pci32(struct boot_params *params, void **pci_handle,
unsigned long size)
 {
-   efi_pci_io_protocol_32 *pci = NULL;
+   efi_pci_io_protocol_32_t *pci = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
u32 *handles = (u32 *)(unsigned long)pci_handle;
efi_status_t status;
@@ -218,7 +218,7 @@ setup_efi_pci32(struct boot_params *params, void 
**pci_handle,
 }
 
 static efi_status_t
-__setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
+__setup_efi_pci64(efi_pci_io_protocol_64_t *pci, struct pci_setup_rom **__rom)
 {
struct pci_setup_rom *rom;
efi_status_t status;
@@ -284,7 +284,7 @@ static void
 setup_efi_pci64(struct boot_params *params, void **pci_handle,
unsigned long size)
 {
-   efi_pci_io_protocol_64 *pci = NULL;
+   efi_pci_io_protocol_64_t *pci = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
u64 *handles = (u64 *)(unsigned long)pci_handle;
efi_status_t status;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 3016d8c456bc..56add823f190 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -397,7 +397,7 @@ typedef struct {
u32 set_bar_attributes;
u64 romsize;
u32 romimage;
-} efi_pci_io_protocol_32;
+} efi_pci_io_protocol_32_t;
 
 typedef struct {
u64 poll_mem;
@@ -417,7 +417,7 @@ typedef struct {
u64 set_bar_attributes;
u64 romsize;
u64 romimage;
-} efi_pci_io_protocol_64;
+} efi_pci_io_protocol_64_t;
 
 typedef struct {
void *poll_mem;
@@ -437,7 +437,7 @@ typedef struct {
void *set_bar_attributes;
uint64_t romsize;
void *romimage;
-} efi_pci_io_protocol;
+} efi_pci_io_protocol_t;
 
 #define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
 #define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002


[tip:efi/core] efi: Avoid potential crashes, fix the 'struct efi_pci_io_protocol_32' definition for mixed mode

2018-05-14 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0b3225ab9407f557a8e20f23f37aa7236c10a9b1
Gitweb: https://git.kernel.org/tip/0b3225ab9407f557a8e20f23f37aa7236c10a9b1
Author: Ard Biesheuvel 
AuthorDate: Fri, 4 May 2018 07:59:58 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 08:56:29 +0200

efi: Avoid potential crashes, fix the 'struct efi_pci_io_protocol_32' 
definition for mixed mode

Mixed mode allows a kernel built for x86_64 to interact with 32-bit
EFI firmware, but requires us to define all struct definitions carefully
when it comes to pointer sizes.

'struct efi_pci_io_protocol_32' currently uses a 'void *' for the
'romimage' field, which will be interpreted as a 64-bit field
on such kernels, potentially resulting in bogus memory references
and subsequent crashes.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180504060003.19618-13-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 6 --
 include/linux/efi.h  | 8 
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 47d3efff6805..09f36c0d9d4f 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -163,7 +163,8 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
goto free_struct;
 
-   memcpy(rom->romdata, pci->romimage, pci->romsize);
+   memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
+  pci->romsize);
return status;
 
 free_struct:
@@ -269,7 +270,8 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
goto free_struct;
 
-   memcpy(rom->romdata, pci->romimage, pci->romsize);
+   memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
+  pci->romsize);
return status;
 
 free_struct:
diff --git a/include/linux/efi.h b/include/linux/efi.h
index f1b7d68ac460..3016d8c456bc 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -395,8 +395,8 @@ typedef struct {
u32 attributes;
u32 get_bar_attributes;
u32 set_bar_attributes;
-   uint64_t romsize;
-   void *romimage;
+   u64 romsize;
+   u32 romimage;
 } efi_pci_io_protocol_32;
 
 typedef struct {
@@ -415,8 +415,8 @@ typedef struct {
u64 attributes;
u64 get_bar_attributes;
u64 set_bar_attributes;
-   uint64_t romsize;
-   void *romimage;
+   u64 romsize;
+   u64 romimage;
 } efi_pci_io_protocol_64;
 
 typedef struct {


[tip:efi/core] arm64/efi: Ignore EFI_MEMORY_XP attribute if RP and/or WP are set

2018-01-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  1e9de1d2207d67b97bb0b62e38454b663d6542fa
Gitweb: https://git.kernel.org/tip/1e9de1d2207d67b97bb0b62e38454b663d6542fa
Author: Ard Biesheuvel 
AuthorDate: Tue, 2 Jan 2018 18:10:39 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Jan 2018 14:03:48 +0100

arm64/efi: Ignore EFI_MEMORY_XP attribute if RP and/or WP are set

The UEFI memory map is a bit vague about how to interpret the
EFI_MEMORY_XP attribute when it is combined with EFI_MEMORY_RP and/or
EFI_MEMORY_WP, which have retroactively been redefined as cacheability
attributes rather than permission attributes.

So let's ignore EFI_MEMORY_XP if _RP and/or _WP are also set. In this
case, it is likely that they are being used to describe the capability
of the region (i.e., whether it has the controls to reconfigure it as
non-executable) rather than the nature of the contents of the region
(i.e., whether it contains data that we will never attempt to execute)

Reported-by: Stephen Boyd 
Tested-by: Stephen Boyd 
Signed-off-by: Ard Biesheuvel 
Cc: Arvind Yadav 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Tyler Baicar 
Cc: Vasyl Gomonovych 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180102181042.19074-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/efi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 82cd075..f85ac58 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -48,7 +48,9 @@ static __init pteval_t 
create_mapping_protection(efi_memory_desc_t *md)
return pgprot_val(PAGE_KERNEL_ROX);
 
/* RW- */
-   if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
+   if (((attr & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP)) ==
+EFI_MEMORY_XP) ||
+   type != EFI_RUNTIME_SERVICES_CODE)
return pgprot_val(PAGE_KERNEL);
 
/* RWX */


[tip:efi/core] efi/capsule-loader: Reinstate virtual capsule mapping

2018-01-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f24c4d478013d82bd1b943df566fff3561d52864
Gitweb: https://git.kernel.org/tip/f24c4d478013d82bd1b943df566fff3561d52864
Author: Ard Biesheuvel 
AuthorDate: Tue, 2 Jan 2018 17:21:10 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Jan 2018 13:54:31 +0100

efi/capsule-loader: Reinstate virtual capsule mapping

Commit:

  82c3768b8d68 ("efi/capsule-loader: Use a cached copy of the capsule header")

... refactored the capsule loading code that maps the capsule header,
to avoid having to map it several times.

However, as it turns out, the vmap() call we ended up removing did not
just map the header, but the entire capsule image, and dropping this
virtual mapping breaks capsules that are processed by the firmware
immediately (i.e., without a reboot).

Unfortunately, that change was part of a larger refactor that allowed
a quirk to be implemented for Quark, which has a non-standard memory
layout for capsules, and we have slightly painted ourselves into a
corner by allowing quirk code to mangle the capsule header and memory
layout.

So we need to fix this without breaking Quark. Fortunately, Quark does
not appear to care about the virtual mapping, and so we can simply
do a partial revert of commit:

  2a457fb31df6 ("efi/capsule-loader: Use page addresses rather than struct page 
pointers")

... and create a vmap() mapping of the entire capsule (including header)
based on the reinstated struct page array, unless running on Quark, in
which case we pass the capsule header copy as before.

Reported-by: Ge Song 
Tested-by: Bryan O'Donoghue 
Tested-by: Ge Song 
Signed-off-by: Ard Biesheuvel 
Cc: 
Cc: Dave Young 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 82c3768b8d68 ("efi/capsule-loader: Use a cached copy of the capsule 
header")
Link: http://lkml.kernel.org/r/20180102172110.17018-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/quirks.c| 13 +-
 drivers/firmware/efi/capsule-loader.c | 45 ---
 include/linux/efi.h   |  4 +++-
 3 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 8a99a2e..5b513cc 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -592,7 +592,18 @@ static int qrk_capsule_setup_info(struct capsule_info 
*cap_info, void **pkbuff,
/*
 * Update the first page pointer to skip over the CSH header.
 */
-   cap_info->pages[0] += csh->headersize;
+   cap_info->phys[0] += csh->headersize;
+
+   /*
+* cap_info->capsule should point at a virtual mapping of the entire
+* capsule, starting at the capsule header. Our image has the Quark
+* security header prepended, so we cannot rely on the default vmap()
+* mapping created by the generic capsule code.
+* Given that the Quark firmware does not appear to care about the
+* virtual mapping, let's just point cap_info->capsule at our copy
+* of the capsule header.
+*/
+   cap_info->capsule = _info->header;
 
return 1;
 }
diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index ec8ac5c..055e2e8 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -20,10 +20,6 @@
 
 #define NO_FURTHER_WRITE_ACTION -1
 
-#ifndef phys_to_page
-#define phys_to_page(x)pfn_to_page((x) >> PAGE_SHIFT)
-#endif
-
 /**
  * efi_free_all_buff_pages - free all previous allocated buffer pages
  * @cap_info: pointer to current instance of capsule_info structure
@@ -35,7 +31,7 @@
 static void efi_free_all_buff_pages(struct capsule_info *cap_info)
 {
while (cap_info->index > 0)
-   __free_page(phys_to_page(cap_info->pages[--cap_info->index]));
+   __free_page(cap_info->pages[--cap_info->index]);
 
cap_info->index = NO_FURTHER_WRITE_ACTION;
 }
@@ -71,6 +67,14 @@ int __efi_capsule_setup_info(struct capsule_info *cap_info)
 
cap_info->pages = temp_page;
 
+   temp_page = krealloc(cap_info->phys,
+pages_needed * sizeof(phys_addr_t *),
+GFP_KERNEL | __GFP_ZERO);
+   if (!temp_page)
+   return -ENOMEM;
+
+   cap_info->phys = temp_page;
+
return 0;
 }
 
@@ -105,9 +109,24 @@ int __weak efi_capsule_setup_info(struct capsule_info 
*cap_info, void *kbuff,
  **/
 static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
 {
+   bool do_vunmap = false;

[tip:efi/core] efi/libstub/arm: Add opt-in Kconfig option for the DTB loader

2018-07-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  3d7ee348aa4127a7893c11261da9b76371a970e6
Gitweb: https://git.kernel.org/tip/3d7ee348aa4127a7893c11261da9b76371a970e6
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:40:38 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 16 Jul 2018 00:43:12 +0200

efi/libstub/arm: Add opt-in Kconfig option for the DTB loader

There are various ways a platform can provide a device tree binary
to the kernel, with different levels of sophistication:

- ideally, the UEFI firmware, which is tightly coupled with the
  platform, provides a device tree image directly as a UEFI
  configuration table, and typically permits the contents to be
  manipulated either via menu options or via UEFI environment
  variables that specify a replacement image,

- GRUB for ARM has a 'devicetree' directive which allows a device
  tree image to be loaded from any location accessible to GRUB, and
  supersede the one provided by the firmware,

- the EFI stub implements a dtb= command line option that allows a
  device tree image to be loaded from a file residing in the same
  file system as the one the kernel image was loaded from.

The dtb= command line option was never intended to be more than a
development feature, to allow the other options to be implemented
in parallel. So let's make it an opt-in feature that is disabled
by default, but can be re-enabled at will.

Note that we already disable the dtb= command line option when we
detect that we are running with UEFI Secure Boot enabled.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Alexander Graf 
Acked-by: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711094040.12506-7-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/Kconfig| 12 
 drivers/firmware/efi/libstub/arm-stub.c |  7 ---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 781a4a337557..d8e159feb573 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -87,6 +87,18 @@ config EFI_RUNTIME_WRAPPERS
 config EFI_ARMSTUB
bool
 
+config EFI_ARMSTUB_DTB_LOADER
+   bool "Enable the DTB loader"
+   depends on EFI_ARMSTUB
+   help
+ Select this config option to add support for the dtb= command
+ line parameter, allowing a device tree blob to be loaded into
+ memory from the EFI System Partition by the stub.
+
+ The device tree is typically provided by the platform or by
+ the bootloader, so this option is mostly for development
+ purposes only.
+
 config EFI_BOOTLOADER_CONTROL
tristate "EFI Bootloader Control"
depends on EFI_VARS
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 01a9d78ee415..c98b1856fc3d 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -202,9 +202,10 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 * 'dtb=' unless UEFI Secure Boot is disabled.  We assume that secure
 * boot is enabled if we can't determine its state.
 */
-   if (secure_boot != efi_secureboot_mode_disabled &&
-   strstr(cmdline_ptr, "dtb=")) {
-   pr_efi(sys_table, "Ignoring DTB from command line.\n");
+   if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
+secure_boot != efi_secureboot_mode_disabled) {
+   if (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=",


[tip:efi/core] efi: Drop type and attribute checks in efi_mem_desc_lookup()

2018-07-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  7e1550b8f2081cccdfa9f1cf1e54cbc4d720af7f
Gitweb: https://git.kernel.org/tip/7e1550b8f2081cccdfa9f1cf1e54cbc4d720af7f
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:40:39 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 16 Jul 2018 00:43:12 +0200

efi: Drop type and attribute checks in efi_mem_desc_lookup()

The current implementation of efi_mem_desc_lookup() includes the
following check on the memory descriptor it returns:

if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
md->type != EFI_BOOT_SERVICES_DATA &&
md->type != EFI_RUNTIME_SERVICES_DATA) {
continue;
}

This means that only EfiBootServicesData or EfiRuntimeServicesData
regions are considered, or any other region type provided that it
has the EFI_MEMORY_RUNTIME attribute set.

Given what the name of the function implies, and the fact that any
physical address can be described in the UEFI memory map only a single
time, it does not make sense to impose this condition in the body of the
loop, but instead, should be imposed by the caller depending on the value
that is returned to it.

Two such callers exist at the moment:

- The BGRT code when running on x86, via efi_mem_reserve() and
  efi_arch_mem_reserve(). In this case, the region is already known to
  be EfiBootServicesData, and so the check is redundant.

- The ESRT handling code which introduced this function, which calls it
  both directly from efi_esrt_init() and again via efi_mem_reserve() and
  efi_arch_mem_reserve() [on x86].

So let's move this check into the callers instead. This preserves the
current behavior both for BGRT and ESRT handling, and allows the lookup
routine to be reused by other [upcoming] users that don't have this
limitation.

In the ESRT case, keep the entire condition, so that platforms that
deviate from the UEFI spec and use something other than
EfiBootServicesData for the ESRT table will keep working as before.

For x86's efi_arch_mem_reserve() implementation, limit the type to
EfiBootServicesData, since it is the only type the reservation code
expects to operate on in the first place.

While we're at it, drop the __init annotation so that drivers can use it
as well.

Tested-by: Laszlo Ersek 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711094040.12506-8-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/quirks.c | 3 ++-
 drivers/firmware/efi/efi.c | 8 +---
 drivers/firmware/efi/esrt.c| 5 -
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 6af39dc40325..844d31cb8a0c 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -248,7 +248,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
int num_entries;
void *new;
 
-   if (efi_mem_desc_lookup(addr, )) {
+   if (efi_mem_desc_lookup(addr, ) ||
+   md.type != EFI_BOOT_SERVICES_DATA) {
pr_err("Failed to lookup EFI memory descriptor for %pa\n", 
);
return;
}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 1379a375dfa8..d8a33a781a57 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -402,7 +402,7 @@ subsys_initcall(efisubsys_init);
  * and if so, populate the supplied memory descriptor with the appropriate
  * data.
  */
-int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
+int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
 {
efi_memory_desc_t *md;
 
@@ -420,12 +420,6 @@ int __init efi_mem_desc_lookup(u64 phys_addr, 
efi_memory_desc_t *out_md)
u64 size;
u64 end;
 
-   if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
-   md->type != EFI_BOOT_SERVICES_DATA &&
-   md->type != EFI_RUNTIME_SERVICES_DATA) {
-   continue;
-   }
-
size = md->num_pages << EFI_PAGE_SHIFT;
end = md->phys_addr + size;
if (phys_addr >= md->phys_addr && phys_addr < end) {
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 1ab80e06e7c5..375a77c1c6e5 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -250,7 +250,10 @@ void __init efi_esrt_init(void)
return;
 
rc = efi_mem_desc_lookup(efi.esrt, );
-   if (rc < 0) {
+   if (rc < 0 ||
+   (!(md.attribute & EFI_MEMORY_RUNTIME) &&
+md.type != EFI_BOOT_SERVICES_DATA &&
+md.type != EFI_RUNTIME_SERVICES_DATA)) {
pr_warn("ESRT header is not in the memory map.\n");
return;
}


[tip:efi/core] fbdev/efifb: Honour UEFI memory map attributes when mapping the FB

2018-07-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  38ac0287b7f4f3922e25fd8f81db67f2c13d16bb
Gitweb: https://git.kernel.org/tip/38ac0287b7f4f3922e25fd8f81db67f2c13d16bb
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:40:40 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 16 Jul 2018 00:43:12 +0200

fbdev/efifb: Honour UEFI memory map attributes when mapping the FB

If the framebuffer address provided by the Graphics Output Protocol
(GOP) is covered by the UEFI memory map, it will tell us which memory
attributes are permitted when mapping this region. In some cases,
(KVM guest on ARM), violating this will result in loss of coherency,
which means that updates sent to the framebuffer by the guest will
not be observeable by the host, and the emulated display simply does
not work.

So if the memory map contains such a description, take the attributes
field into account, and add support for creating WT or WB mappings of
the framebuffer region.

Tested-by: Laszlo Ersek 
Signed-off-by: Ard Biesheuvel 
Acked-by: Bartlomiej Zolnierkiewicz 
Cc: Linus Torvalds 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711094040.12506-9-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 51 -
 1 file changed, 41 insertions(+), 10 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 46a4484e3da7..c6f78d27947b 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -20,7 +20,7 @@
 #include   /* For DRM_MODE_PANEL_ORIENTATION_* */
 
 static bool request_mem_succeeded = false;
-static bool nowc = false;
+static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC;
 
 static struct fb_var_screeninfo efifb_defined = {
.activate   = FB_ACTIVATE_NOW,
@@ -68,8 +68,12 @@ static int efifb_setcolreg(unsigned regno, unsigned red, 
unsigned green,
 
 static void efifb_destroy(struct fb_info *info)
 {
-   if (info->screen_base)
-   iounmap(info->screen_base);
+   if (info->screen_base) {
+   if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
+   iounmap(info->screen_base);
+   else
+   memunmap(info->screen_base);
+   }
if (request_mem_succeeded)
release_mem_region(info->apertures->ranges[0].base,
   info->apertures->ranges[0].size);
@@ -104,7 +108,7 @@ static int efifb_setup(char *options)
else if (!strncmp(this_opt, "width:", 6))
screen_info.lfb_width = 
simple_strtoul(this_opt+6, NULL, 0);
else if (!strcmp(this_opt, "nowc"))
-   nowc = true;
+   mem_flags &= ~EFI_MEMORY_WC;
}
}
 
@@ -164,6 +168,7 @@ static int efifb_probe(struct platform_device *dev)
unsigned int size_remap;
unsigned int size_total;
char *option = NULL;
+   efi_memory_desc_t md;
 
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
@@ -272,12 +277,35 @@ static int efifb_probe(struct platform_device *dev)
info->apertures->ranges[0].base = efifb_fix.smem_start;
info->apertures->ranges[0].size = size_remap;
 
-   if (nowc)
-   info->screen_base = ioremap(efifb_fix.smem_start, 
efifb_fix.smem_len);
-   else
-   info->screen_base = ioremap_wc(efifb_fix.smem_start, 
efifb_fix.smem_len);
+   if (!efi_mem_desc_lookup(efifb_fix.smem_start, )) {
+   if ((efifb_fix.smem_start + efifb_fix.smem_len) >
+   (md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT))) {
+   pr_err("efifb: video memory @ 0x%lx spans multiple EFI 
memory regions\n",
+  efifb_fix.smem_start);
+   err = -EIO;
+   goto err_release_fb;
+   }
+   /*
+* If the UEFI memory map covers the efifb region, we may only
+* remap it using the attributes the memory map prescribes.
+*/
+   mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB;
+   mem_flags &= md.attribute;
+   }
+   if (mem_flags & EFI_MEMORY_WC)
+   info->screen_base = ioremap_wc(efifb_fix.smem_start,
+  efifb_fix.smem_len);
+   else if (mem_flags & EFI_MEMORY_UC)
+   info->screen_base = ioremap(efifb_fix.smem_start,
+   efifb_fix.smem_len);
+   else if (mem_flags & EFI_MEMORY_WT)
+   info->screen_base = memremap(efifb_fix.smem_start,
+efifb_fix.smem_len, MEMREMAP_WT);
+   else if (mem_flags & EFI_MEMORY_WB)
+   info->screen_base = 

[tip:efi/core] efi/x86: Replace references to efi_early->is64 with efi_is_64bit()

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  aab9593c0cb4454f9d261a8c87a3361f3186c4ec
Gitweb: https://git.kernel.org/tip/aab9593c0cb4454f9d261a8c87a3361f3186c4ec
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:24 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:43 +0200

efi/x86: Replace references to efi_early->is64 with efi_is_64bit()

There are a couple of places in the x86 EFI stub code where we select
between 32-bit and 64-bit versions of the support routines based on
the value of efi_early->is64. Referencing that field directly is a
bad idea, since it prevents the compiler from inferring that this
field can never be true on a 32-bit build, and can only become false
on a 64-bit build if support for mixed mode is compiled in. This
results in dead code to be retained in the uncompressed part of the
kernel image, which is wasteful.

So switch to the efi_is_64bit() helper, which will resolve to a
constant boolean unless building for 64-bit with mixed mode support.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-8-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 915c64edbe8e..1458b1700fc7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -404,7 +404,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
return NULL;
 
-   if (efi_early->is64)
+   if (efi_is_64bit())
setup_boot_services64(efi_early);
else
setup_boot_services32(efi_early);
@@ -639,7 +639,6 @@ struct exit_boot_struct {
struct efi_info *efi;
struct setup_data   *e820ext;
__u32   e820ext_size;
-   boolis64;
 };
 
 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -666,7 +665,8 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
first = false;
}
 
-   signature = p->is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
+   signature = efi_is_64bit() ? EFI64_LOADER_SIGNATURE
+  : EFI32_LOADER_SIGNATURE;
memcpy(>efi->efi_loader_signature, signature, sizeof(__u32));
 
p->efi->efi_systab  = (unsigned long)sys_table_arg;
@@ -683,8 +683,7 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
return EFI_SUCCESS;
 }
 
-static efi_status_t exit_boot(struct boot_params *boot_params,
- void *handle, bool is64)
+static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
 {
unsigned long map_sz, key, desc_size, buff_size;
efi_memory_desc_t *mem_map;
@@ -705,7 +704,6 @@ static efi_status_t exit_boot(struct boot_params 
*boot_params,
priv.efi= _params->efi_info;
priv.e820ext= NULL;
priv.e820ext_size   = 0;
-   priv.is64   = is64;
 
/* Might as well exit boot services now */
status = efi_exit_boot_services(sys_table, handle, , ,
@@ -740,13 +738,11 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
struct desc_struct *desc;
void *handle;
efi_system_table_t *_table;
-   bool is64;
 
efi_early = c;
 
_table = (efi_system_table_t *)(unsigned long)efi_early->table;
handle = (void *)(unsigned long)efi_early->image_handle;
-   is64 = efi_early->is64;
 
sys_table = _table;
 
@@ -754,7 +750,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
 
-   if (is64)
+   if (efi_is_64bit())
setup_boot_services64(efi_early);
else
setup_boot_services32(efi_early);
@@ -810,7 +806,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
hdr->code32_start = bzimage_addr;
}
 
-   status = exit_boot(boot_params, handle, is64);
+   status = exit_boot(boot_params, handle);
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "exit_boot() failed!\n");
goto fail;


[tip:efi/core] efi/x86: Merge the setup_efi_pci32() and setup_efi_pci64() routines

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  75c5a713ab4b774c7d990ec748dddba714034436
Gitweb: https://git.kernel.org/tip/75c5a713ab4b774c7d990ec748dddba714034436
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:19 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:42 +0200

efi/x86: Merge the setup_efi_pci32() and setup_efi_pci64() routines

After merging the 32-bit and 64-bit versions of the code that invokes
the PCI I/O protocol methods to preserve PCI ROM images in commit:

  2c3625cb9fa2 ("efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() ...")

there are still separate code paths for 32-bit and 64-bit, where the only
difference is the size of a EFI_HANDLE. So let's parameterize a single
implementation for that difference only, and get rid of the two copies of
the code.

While at it, rename __setup_efi_pci() to preserve_pci_rom_image() to
better reflect its purpose.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 123 ++-
 1 file changed, 32 insertions(+), 91 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 9f6813493945..c72550783c16 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -111,7 +111,7 @@ void efi_char16_printk(efi_system_table_t *table, 
efi_char16_t *str)
 }
 
 static efi_status_t
-__setup_efi_pci(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
+preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom 
**__rom)
 {
struct pci_setup_rom *rom = NULL;
efi_status_t status;
@@ -181,92 +181,6 @@ free_struct:
return status;
 }
 
-static void
-setup_efi_pci32(struct boot_params *params, void **pci_handle, unsigned long 
size)
-{
-   efi_pci_io_protocol_t *pci = NULL;
-   efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
-   u32 *handles = (u32 *)(unsigned long)pci_handle;
-   efi_status_t status;
-   unsigned long nr_pci;
-   struct setup_data *data;
-   int i;
-
-   data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
-
-   while (data && data->next)
-   data = (struct setup_data *)(unsigned long)data->next;
-
-   nr_pci = size / sizeof(u32);
-   for (i = 0; i < nr_pci; i++) {
-   struct pci_setup_rom *rom = NULL;
-   u32 h = handles[i];
-
-   status = efi_call_early(handle_protocol, h,
-   _proto, (void **));
-
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (!pci)
-   continue;
-
-   status = __setup_efi_pci(pci, );
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (data)
-   data->next = (unsigned long)rom;
-   else
-   params->hdr.setup_data = (unsigned long)rom;
-
-   data = (struct setup_data *)rom;
-   }
-}
-
-static void
-setup_efi_pci64(struct boot_params *params, void **pci_handle, unsigned long 
size)
-{
-   efi_pci_io_protocol_t *pci = NULL;
-   efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
-   u64 *handles = (u64 *)(unsigned long)pci_handle;
-   efi_status_t status;
-   unsigned long nr_pci;
-   struct setup_data *data;
-   int i;
-
-   data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
-
-   while (data && data->next)
-   data = (struct setup_data *)(unsigned long)data->next;
-
-   nr_pci = size / sizeof(u64);
-   for (i = 0; i < nr_pci; i++) {
-   struct pci_setup_rom *rom = NULL;
-   u64 h = handles[i];
-
-   status = efi_call_early(handle_protocol, h,
-   _proto, (void **));
-
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (!pci)
-   continue;
-
-   status = __setup_efi_pci(pci, );
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (data)
-   data->next = (unsigned long)rom;
-   else
-   params->hdr.setup_data = (unsigned long)rom;
-
-   data = (struct setup_data *)rom;
-   }
-}
-
 /*
  * There's no way to return an informative status from this function,
  * because any analysis (and printing of error messages) needs to be
@@ -282,6 +196,9 @@ static void setup_efi_pci(struct boot_params *params)
void **pci_handle = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
unsigned long size = 0;
+   unsigned long nr_pci;
+  

[tip:efi/core] efi/x86: Prevent reentrant firmware calls in mixed mode

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  83a0a2ea0b991927e42984be220329e776ce7137
Gitweb: https://git.kernel.org/tip/83a0a2ea0b991927e42984be220329e776ce7137
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:18 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:42 +0200

efi/x86: Prevent reentrant firmware calls in mixed mode

The UEFI spec does not permit runtime services to be called
reentrantly, and so it is up to the OS to provide proper locking
around such calls.

For the native case, this was fixed a long time ago, but for the
mixed mode case, no locking is done whatsoever. Note that the calls
are made with preemption and interrupts disabled, so only SMP
configurations are affected by this issue.

So add a spinlock and grab it when invoking a UEFI runtime service
in mixed mode. We will also need to provide non-blocking versions
of SetVariable() and QueryVariableInfo(), so add those as well.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/efi_64.c | 101 +++--
 1 file changed, 98 insertions(+), 3 deletions(-)

diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 77873ce700ae..448267f1c073 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -636,6 +636,8 @@ void efi_switch_mm(struct mm_struct *mm)
 #ifdef CONFIG_EFI_MIXED
 extern efi_status_t efi64_thunk(u32, ...);
 
+static DEFINE_SPINLOCK(efi_runtime_lock);
+
 #define runtime_service32(func)
 \
 ({  \
u32 table = (u32)(unsigned long)efi.systab;  \
@@ -657,17 +659,14 @@ extern efi_status_t efi64_thunk(u32, ...);
 #define efi_thunk(f, ...)  \
 ({ \
efi_status_t __s;   \
-   unsigned long __flags;  \
u32 __func; \
\
-   local_irq_save(__flags);\
arch_efi_call_virt_setup(); \
\
__func = runtime_service32(f);  \
__s = efi64_thunk(__func, __VA_ARGS__); \
\
arch_efi_call_virt_teardown();  \
-   local_irq_restore(__flags); \
\
__s;\
 })
@@ -702,14 +701,17 @@ static efi_status_t efi_thunk_get_time(efi_time_t *tm, 
efi_time_cap_t *tc)
 {
efi_status_t status;
u32 phys_tm, phys_tc;
+   unsigned long flags;
 
spin_lock(_lock);
+   spin_lock_irqsave(_runtime_lock, flags);
 
phys_tm = virt_to_phys_or_null(tm);
phys_tc = virt_to_phys_or_null(tc);
 
status = efi_thunk(get_time, phys_tm, phys_tc);
 
+   spin_unlock_irqrestore(_runtime_lock, flags);
spin_unlock(_lock);
 
return status;
@@ -719,13 +721,16 @@ static efi_status_t efi_thunk_set_time(efi_time_t *tm)
 {
efi_status_t status;
u32 phys_tm;
+   unsigned long flags;
 
spin_lock(_lock);
+   spin_lock_irqsave(_runtime_lock, flags);
 
phys_tm = virt_to_phys_or_null(tm);
 
status = efi_thunk(set_time, phys_tm);
 
+   spin_unlock_irqrestore(_runtime_lock, flags);
spin_unlock(_lock);
 
return status;
@@ -737,8 +742,10 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t 
*pending,
 {
efi_status_t status;
u32 phys_enabled, phys_pending, phys_tm;
+   unsigned long flags;
 
spin_lock(_lock);
+   spin_lock_irqsave(_runtime_lock, flags);
 
phys_enabled = virt_to_phys_or_null(enabled);
phys_pending = virt_to_phys_or_null(pending);
@@ -747,6 +754,7 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t 
*pending,
status = efi_thunk(get_wakeup_time, phys_enabled,
 phys_pending, phys_tm);
 
+   spin_unlock_irqrestore(_runtime_lock, flags);
spin_unlock(_lock);
 
return status;
@@ -757,13 +765,16 @@ efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t 
*tm)
 {
efi_status_t status;
u32 phys_tm;
+  

[tip:efi/core] efi/x86: Merge 32-bit and 64-bit UGA draw protocol setup routines

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  290084c2fa13e9aaa7f856ed1ab30760327dd9f8
Gitweb: https://git.kernel.org/tip/290084c2fa13e9aaa7f856ed1ab30760327dd9f8
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:21 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:43 +0200

efi/x86: Merge 32-bit and 64-bit UGA draw protocol setup routines

The two versions of setup_uga##() are mostly identical, with the
exception of the size of EFI_HANDLE. So let's merge the two, and
pull the implementation into the calling function setup_uga().

Note that the 32-bit version was only mixed-mode safe by accident:
it only calls the get_mode() method of the UGA draw protocol, which
happens to be the first member, and so truncating the 64-bit void* at
offset 0 to 32 bits happens to produce the correct value. But let's
not rely on that, and use the proper API instead.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 111 +--
 1 file changed, 26 insertions(+), 85 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 011d5c289449..ac8e442db71f 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -318,81 +318,54 @@ static void setup_quirks(struct boot_params *boot_params)
}
 }
 
+/*
+ * See if we have Universal Graphics Adapter (UGA) protocol
+ */
 static efi_status_t
-setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
+setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
 {
+   efi_status_t status;
+   u32 width, height;
+   void **uga_handle = NULL;
efi_uga_draw_protocol_t *uga = NULL, *first_uga;
-   efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
unsigned long nr_ugas;
-   u32 *handles = (u32 *)uga_handle;
-   efi_status_t status = EFI_INVALID_PARAMETER;
int i;
 
-   first_uga = NULL;
-   nr_ugas = size / sizeof(u32);
-   for (i = 0; i < nr_ugas; i++) {
-   efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
-   u32 w, h, depth, refresh;
-   void *pciio;
-   u32 handle = handles[i];
-
-   status = efi_call_early(handle_protocol, handle,
-   _proto, (void **));
-   if (status != EFI_SUCCESS)
-   continue;
-
-   efi_call_early(handle_protocol, handle, _proto, );
-
-   status = efi_early->call((unsigned long)uga->get_mode, uga,
-, , , );
-   if (status == EFI_SUCCESS && (!first_uga || pciio)) {
-   *width = w;
-   *height = h;
-
-   /*
-* Once we've found a UGA supporting PCIIO,
-* don't bother looking any further.
-*/
-   if (pciio)
-   break;
-
-   first_uga = uga;
-   }
-   }
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   size, (void **)_handle);
+   if (status != EFI_SUCCESS)
+   return status;
 
-   return status;
-}
+   status = efi_call_early(locate_handle,
+   EFI_LOCATE_BY_PROTOCOL,
+   uga_proto, NULL, , uga_handle);
+   if (status != EFI_SUCCESS)
+   goto free_handle;
 
-static efi_status_t
-setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
-{
-   efi_uga_draw_protocol_t *uga = NULL, *first_uga;
-   efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
-   unsigned long nr_ugas;
-   u64 *handles = (u64 *)uga_handle;
-   efi_status_t status = EFI_INVALID_PARAMETER;
-   int i;
+   height = 0;
+   width = 0;
 
first_uga = NULL;
-   nr_ugas = size / sizeof(u64);
+   nr_ugas = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32));
for (i = 0; i < nr_ugas; i++) {
efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
u32 w, h, depth, refresh;
void *pciio;
-   u64 handle = handles[i];
+   unsigned long handle = efi_is_64bit() ? ((u64 *)uga_handle)[i]
+ : ((u32 *)uga_handle)[i];
 
status = efi_call_early(handle_protocol, handle,
-   _proto, (void **));
+   uga_proto, (void **));
if (status != EFI_SUCCESS)
continue;
 

[tip:efi/core] efi/x86: Add missing NULL initialization in UGA draw protocol discovery

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  093174f52553532b9eb0e63cbbb254f6990d46d5
Gitweb: https://git.kernel.org/tip/093174f52553532b9eb0e63cbbb254f6990d46d5
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:22 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:43 +0200

efi/x86: Add missing NULL initialization in UGA draw protocol discovery

The UGA draw protocol discovery routine looks for a EFI handle that has
both the UGA draw protocol and the PCI I/O protocol installed. It checks
for the latter by calling handle_protocol() and pass it a PCI I/O
protocol pointer variable by reference, but fails to initialize it to
NULL, which means the non-NULL check later on in the code could produce
false positives, given that the return code of the handle_protocol() call
is ignored entirely. So add the missing initialization.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index ac8e442db71f..92b573fd239c 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -359,6 +359,7 @@ setup_uga(struct screen_info *si, efi_guid_t *uga_proto, 
unsigned long size)
if (status != EFI_SUCCESS)
continue;
 
+   pciio = NULL;
efi_call_early(handle_protocol, handle, _proto, );
 
status = efi_call_proto(efi_uga_draw_protocol, get_mode, uga,


[tip:efi/core] efi/x86: Align efi_uga_draw_protocol typedef names to convention

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0b767b16d7b634dd62667f224425cef3c78e031c
Gitweb: https://git.kernel.org/tip/0b767b16d7b634dd62667f224425cef3c78e031c
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:20 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:42 +0200

efi/x86: Align efi_uga_draw_protocol typedef names to convention

The linux-efi subsystem uses typedefs with the _t suffix to declare
data structures that originate in the UEFI spec. Our type mangling
for mixed mode depends on this convention, so rename the UGA drawing
protocols to allow efi_call_proto() to be used with them in a
subsequent patch.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c |  4 ++--
 arch/x86/boot/compressed/eboot.h | 12 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index c72550783c16..011d5c289449 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -321,7 +321,7 @@ static void setup_quirks(struct boot_params *boot_params)
 static efi_status_t
 setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
 {
-   struct efi_uga_draw_protocol *uga = NULL, *first_uga;
+   efi_uga_draw_protocol_t *uga = NULL, *first_uga;
efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
unsigned long nr_ugas;
u32 *handles = (u32 *)uga_handle;
@@ -366,7 +366,7 @@ setup_uga32(void **uga_handle, unsigned long size, u32 
*width, u32 *height)
 static efi_status_t
 setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
 {
-   struct efi_uga_draw_protocol *uga = NULL, *first_uga;
+   efi_uga_draw_protocol_t *uga = NULL, *first_uga;
efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
unsigned long nr_ugas;
u64 *handles = (u64 *)uga_handle;
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index e799dc5c6448..8297387c4676 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -12,22 +12,22 @@
 
 #define DESC_TYPE_CODE_DATA(1 << 0)
 
-struct efi_uga_draw_protocol_32 {
+typedef struct {
u32 get_mode;
u32 set_mode;
u32 blt;
-};
+} efi_uga_draw_protocol_32_t;
 
-struct efi_uga_draw_protocol_64 {
+typedef struct {
u64 get_mode;
u64 set_mode;
u64 blt;
-};
+} efi_uga_draw_protocol_64_t;
 
-struct efi_uga_draw_protocol {
+typedef struct {
void *get_mode;
void *set_mode;
void *blt;
-};
+} efi_uga_draw_protocol_t;
 
 #endif /* BOOT_COMPRESSED_EBOOT_H */


[tip:efi/urgent] efi/x86: Fix mixed mode reboot loop by removing pointless call to PciIo->Attributes()

2018-07-11 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e296701800f30d260a66f8aa1971b5b1bc3d2f81
Gitweb: https://git.kernel.org/tip/e296701800f30d260a66f8aa1971b5b1bc3d2f81
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:02:35 +0200
Committer:  Ingo Molnar 
CommitDate: Wed, 11 Jul 2018 13:15:21 +0200

efi/x86: Fix mixed mode reboot loop by removing pointless call to 
PciIo->Attributes()

Hans de Goede reported that his mixed EFI mode Bay Trail tablet
would not boot at all any more, but enter a reboot loop without
any logs printed by the kernel.

Unbreak 64-bit Linux/x86 on 32-bit UEFI:

When it was first introduced, the EFI stub code that copies the
contents of PCI option ROMs originally only intended to do so if
the EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM attribute was *not* set.

The reason was that the UEFI spec permits PCI option ROM images
to be provided by the platform directly, rather than via the ROM
BAR, and in this case, the OS can only access them at runtime if
they are preserved at boot time by copying them from the areas
described by PciIo->RomImage and PciIo->RomSize.

However, it implemented this check erroneously, as can be seen in
commit:

  dd5fc854de5fd ("EFI: Stash ROMs if they're not in the PCI BAR")

which introduced:

if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
continue;

and given that the numeric value of EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
is 0x4000, this condition never becomes true, and so the option ROMs
were copied unconditionally.

This was spotted and 'fixed' by commit:

  886d751a2ea99a160 ("x86, efi: correct precedence of operators in 
setup_efi_pci")

but inadvertently inverted the logic at the same time, defeating
the purpose of the code, since it now only preserves option ROM
images that can be read from the ROM BAR as well.

Unsurprisingly, this broke some systems, and so the check was removed
entirely in the following commit:

  739701888f5d ("x86, efi: remove attribute check from setup_efi_pci")

It is debatable whether this check should have been included in the
first place, since the option ROM image provided to the UEFI driver by
the firmware may be different from the one that is actually present in
the card's flash ROM, and so whatever PciIo->RomImage points at should
be preferred regardless of whether the attribute is set.

As this was the only use of the attributes field, we can remove
the call to PciIo->Attributes() entirely, which is especially
nice because its prototype involves uint64_t type by-value
arguments which the EFI mixed mode has trouble dealing with.

Any mixed mode system with PCI is likely to be affected.

Tested-by: Wilfried Klaebe 
Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711090235.9327-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 12 +++-
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index e57665b4ba1c..e98522ea6f09 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -114,18 +114,12 @@ __setup_efi_pci(efi_pci_io_protocol_t *pci, struct 
pci_setup_rom **__rom)
struct pci_setup_rom *rom = NULL;
efi_status_t status;
unsigned long size;
-   uint64_t attributes, romsize;
+   uint64_t romsize;
void *romimage;
 
-   status = efi_call_proto(efi_pci_io_protocol, attributes, pci,
-   EfiPciIoAttributeOperationGet, 0ULL,
-   );
-   if (status != EFI_SUCCESS)
-   return status;
-
/*
-* Some firmware images contain EFI function pointers at the place 
where the
-* romimage and romsize fields are supposed to be. Typically the EFI
+* Some firmware images contain EFI function pointers at the place where
+* the romimage and romsize fields are supposed to be. Typically the EFI
 * code is mapped at high addresses, translating to an unrealistically
 * large romsize. The UEFI spec limits the size of option ROMs to 16
 * MiB so we reject any ROMs over 16 MiB in size to catch this.


[tip:efi/core] efi/esrt: Fix handling of early ESRT table mapping

2018-03-12 Thread tip-bot for Ard Biesheuvel
Commit-ID:  136d5d57e35cc6985c57d23d0c823133e3508bed
Gitweb: https://git.kernel.org/tip/136d5d57e35cc6985c57d23d0c823133e3508bed
Author: Ard Biesheuvel 
AuthorDate: Mon, 12 Mar 2018 08:44:59 +
Committer:  Ingo Molnar 
CommitDate: Mon, 12 Mar 2018 10:05:01 +0100

efi/esrt: Fix handling of early ESRT table mapping

As reported by Tyler, efi_esrt_init() will return without releasing the
ESRT table header mapping if it encounters a table with an unexpected
version. Replacing the 'return' with 'goto err_memunmap' would fix this
particular occurrence, but, as it turns out, the code is rather peculiar
to begin with:

 - it never uses the header mapping after memcpy()'ing out its contents,
 - it maps and unmaps the entire table without ever looking at the
   contents.

So let's refactor this code to unmap the table header right after the
memcpy() so we can get rid of the error handling path altogether, and
drop the second mapping entirely.

Reported-by: Tyler Baicar 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180312084500.10764-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/esrt.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index c47e0c6ec00f..1ab80e06e7c5 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -279,6 +279,7 @@ void __init efi_esrt_init(void)
}
 
memcpy(, va, sizeof(tmpesrt));
+   early_memunmap(va, size);
 
if (tmpesrt.fw_resource_version == 1) {
entry_size = sizeof (*v1_entries);
@@ -291,7 +292,7 @@ void __init efi_esrt_init(void)
if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) {
pr_err("ESRT memory map entry can only hold the header. (max: 
%zu size: %zu)\n",
   max - size, entry_size);
-   goto err_memunmap;
+   return;
}
 
/*
@@ -304,7 +305,7 @@ void __init efi_esrt_init(void)
if (tmpesrt.fw_resource_count > 128) {
pr_err("ESRT says fw_resource_count has very large value %d.\n",
   tmpesrt.fw_resource_count);
-   goto err_memunmap;
+   return;
}
 
/*
@@ -315,18 +316,10 @@ void __init efi_esrt_init(void)
if (max < size + entries_size) {
pr_err("ESRT does not fit on single memory map entry (size: %zu 
max: %zu)\n",
   size, max);
-   goto err_memunmap;
+   return;
}
 
-   /* remap it with our (plausible) new pages */
-   early_memunmap(va, size);
size += entries_size;
-   va = early_memremap(efi.esrt, size);
-   if (!va) {
-   pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
-  size);
-   return;
-   }
 
esrt_data = (phys_addr_t)efi.esrt;
esrt_data_size = size;
@@ -336,8 +329,6 @@ void __init efi_esrt_init(void)
efi_mem_reserve(esrt_data, esrt_data_size);
 
pr_debug("esrt-init: loaded.\n");
-err_memunmap:
-   early_memunmap(va, size);
 }
 
 static int __init register_entries(void)


[tip:efi/core] efi: Use string literals for efi_char16_t variable initializers

2018-03-12 Thread tip-bot for Ard Biesheuvel
Commit-ID:  36b649760e94968e0495b73284aaf07eed0a328f
Gitweb: https://git.kernel.org/tip/36b649760e94968e0495b73284aaf07eed0a328f
Author: Ard Biesheuvel 
AuthorDate: Mon, 12 Mar 2018 08:45:00 +
Committer:  Ingo Molnar 
CommitDate: Mon, 12 Mar 2018 10:05:02 +0100

efi: Use string literals for efi_char16_t variable initializers

Now that we unambiguously build the entire kernel with -fshort-wchar,
it is no longer necessary to open code efi_char16_t[] initializers as
arrays of characters, and we can move to the L"xxx" notation instead.

Signed-off-by: Ard Biesheuvel 
Cc: Arnd Bergmann 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180312084500.10764-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c  |  3 ++-
 arch/x86/platform/efi/quirks.c|  8 +---
 drivers/firmware/efi/libstub/Makefile |  2 +-
 drivers/firmware/efi/libstub/secureboot.c | 12 +++-
 drivers/firmware/efi/libstub/tpm.c|  7 ++-
 5 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index f2251c1c9853..47d3efff6805 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -421,9 +421,10 @@ static void retrieve_apple_device_properties(struct 
boot_params *boot_params)
}
 }
 
+static const efi_char16_t apple[] = L"Apple";
+
 static void setup_quirks(struct boot_params *boot_params)
 {
-   static efi_char16_t const apple[] = { 'A', 'p', 'p', 'l', 'e', 0 };
efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
efi_table_attr(efi_system_table, fw_vendor, sys_table);
 
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 1ef11c26f79b..36c1f8b9f7e0 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -75,7 +75,7 @@ struct quark_security_header {
u32 rsvd[2];
 };
 
-static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
+static const efi_char16_t efi_dummy_name[] = L"DUMMY";
 
 static bool efi_no_storage_paranoia;
 
@@ -105,7 +105,8 @@ early_param("efi_no_storage_paranoia", 
setup_storage_paranoia);
 */
 void efi_delete_dummy_variable(void)
 {
-   efi.set_variable(efi_dummy_name, _DUMMY_GUID,
+   efi.set_variable((efi_char16_t *)efi_dummy_name,
+_DUMMY_GUID,
 EFI_VARIABLE_NON_VOLATILE |
 EFI_VARIABLE_BOOTSERVICE_ACCESS |
 EFI_VARIABLE_RUNTIME_ACCESS,
@@ -182,7 +183,8 @@ efi_status_t efi_query_variable_store(u32 attributes, 
unsigned long size,
if (!dummy)
return EFI_OUT_OF_RESOURCES;
 
-   status = efi.set_variable(efi_dummy_name, _DUMMY_GUID,
+   status = efi.set_variable((efi_char16_t *)efi_dummy_name,
+ _DUMMY_GUID,
  EFI_VARIABLE_NON_VOLATILE |
  EFI_VARIABLE_BOOTSERVICE_ACCESS |
  EFI_VARIABLE_RUNTIME_ACCESS,
diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index 7b3ba40f0745..a34e9290a699 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -9,7 +9,7 @@ cflags-$(CONFIG_X86_32) := -march=i386
 cflags-$(CONFIG_X86_64):= -mcmodel=small
 cflags-$(CONFIG_X86)   += -m$(BITS) -D__KERNEL__ -O2 \
   -fPIC -fno-strict-aliasing -mno-red-zone \
-  -mno-mmx -mno-sse
+  -mno-mmx -mno-sse -fshort-wchar
 
 cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie
 cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
diff --git a/drivers/firmware/efi/libstub/secureboot.c 
b/drivers/firmware/efi/libstub/secureboot.c
index 959777ec8a77..8f07eb414c00 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -16,18 +16,12 @@
 
 /* BIOS variables */
 static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
-static const efi_char16_t efi_SecureBoot_name[] = {
-   'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0
-};
-static const efi_char16_t efi_SetupMode_name[] = {
-   'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0
-};
+static const efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
+static const efi_char16_t efi_SetupMode_name[] = L"SetupMode";
 
 /* SHIM variables */
 static 

  1   2   3   >