* [PATCH 1/2] efi/libstub: Skip GOP with PIXEL_BLT_ONLY format
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2017-04-04 16:02 ` Ard Biesheuvel
2017-04-04 16:02 ` [PATCH 02/12] efi: arm-stub: Correct FDT and initrd allocation rules for arm64 Ard Biesheuvel
` (6 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:02 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: Cohen, Eugene, Ard Biesheuvel, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: "Cohen, Eugene" <eugene-VXdhtT5mjnY@public.gmane.org>
The UEFI Specification permits Graphics Output Protocol (GOP) instances
without direct framebuffer access. This is indicated in the Mode structure
with a PixelFormat enumeration value of PIXEL_BLT_ONLY. Given that the
kernel does not know how to drive a Blt() only framebuffer (which is only
permitted before ExitBootServices() anyway), we should disregard such
framebuffers when looking for a GOP instance that is suitable for use as
the boot console.
So modify the EFI GOP initialization to not use a PIXEL_BLT_ONLY instance,
preventing attempts later in boot to use an invalid screen_info.lfb_base
address.
Fixes: 9822504c1fa5 ("efifb: Enable the efi-framebuffer platform driver ...")
Signed-off-by: Eugene Cohen <eugene-VXdhtT5mjnY@public.gmane.org>
[ardb: - move Blt() only check into the loop
- clarify that Blt() only GOPs are unusable by the kernel]
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Cc: <stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org> # v4.7+
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
drivers/firmware/efi/libstub/gop.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 932742e4cf23..24c461dea7af 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -149,7 +149,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
status = __gop_query32(sys_table_arg, gop32, &info, &size,
¤t_fb_base);
- if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+ if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+ info->pixel_format != PIXEL_BLT_ONLY) {
/*
* Systems that use the UEFI Console Splitter may
* provide multiple GOP devices, not all of which are
@@ -266,7 +267,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
status = __gop_query64(sys_table_arg, gop64, &info, &size,
¤t_fb_base);
- if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+ if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+ info->pixel_format != PIXEL_BLT_ONLY) {
/*
* Systems that use the UEFI Console Splitter may
* provide multiple GOP devices, not all of which are
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 02/12] efi: arm-stub: Correct FDT and initrd allocation rules for arm64
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2017-04-04 16:02 ` [PATCH 1/2] efi/libstub: Skip GOP with PIXEL_BLT_ONLY format Ard Biesheuvel
@ 2017-04-04 16:02 ` Ard Biesheuvel
2017-04-04 16:02 ` [PATCH 2/2] efifb: Avoid reconfiguration of BAR that covers the framebuffer Ard Biesheuvel
` (5 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:02 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: Ard Biesheuvel, linux-kernel-u79uwXL29TY76Z2rM5mHXA
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.
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Tested-by: Richard Ruigrok <rruigrok-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Reviewed-by: Jeffrey Hugo <jhugo-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
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 e4e6a9d6a825..17f1f1a814ff 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_LIMIT SZ_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 e7445281e534..083a52d3b59f 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 d4056c6be1ec..02049ff25c6b 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=",
+ efi_get_max_initrd_addr(dram_base,
+ *image_addr),
(unsigned long *)&initrd_addr,
(unsigned long *)&initrd_size);
if (status != EFI_SUCCESS)
@@ -224,7 +225,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
- &new_fdt_addr, dram_base + MAX_FDT_OFFSET,
+ &new_fdt_addr, efi_get_max_fdt_addr(dram_base),
initrd_addr, initrd_size, cmdline_ptr,
fdt_addr, fdt_size);
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 2/2] efifb: Avoid reconfiguration of BAR that covers the framebuffer
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2017-04-04 16:02 ` [PATCH 1/2] efi/libstub: Skip GOP with PIXEL_BLT_ONLY format Ard Biesheuvel
2017-04-04 16:02 ` [PATCH 02/12] efi: arm-stub: Correct FDT and initrd allocation rules for arm64 Ard Biesheuvel
@ 2017-04-04 16:02 ` Ard Biesheuvel
2017-04-04 16:02 ` [PATCH 04/12] x86/efi-bgrt: Move efi-bgrt handling out of arch/x86 Ard Biesheuvel
` (4 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:02 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: Ard Biesheuvel, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On UEFI systems, the PCI subsystem is enumerated by the firmware,
and if a graphical framebuffer is exposed by 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.
Fixes: 9822504c1fa5 ("efifb: Enable the efi-framebuffer platform driver ...")
Cc: <stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org> # v4.7+
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Cc: Peter Jones <pjones-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
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 8c4dc1e1f94f..758960b6aec9 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -10,6 +10,7 @@
#include <linux/efi.h>
#include <linux/errno.h>
#include <linux/fb.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
#include <video/vga.h>
@@ -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", &option))
@@ -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, &word);
+ if (!(word & PCI_COMMAND_MEMORY)) {
+ pci_dev_disabled = true;
+ dev_err(&dev->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->dev,
+ "BAR %d: failed to claim resource for efifb!\n", idx);
+ return;
+ }
+
+ dev_info(&dev->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 = &dev->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
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 04/12] x86/efi-bgrt: Move efi-bgrt handling out of arch/x86
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
` (2 preceding siblings ...)
2017-04-04 16:02 ` [PATCH 2/2] efifb: Avoid reconfiguration of BAR that covers the framebuffer Ard Biesheuvel
@ 2017-04-04 16:02 ` Ard Biesheuvel
2017-04-04 16:02 ` [PATCH 07/12] x86/efi: Clean up a minor mistake in code comment Ard Biesheuvel
` (3 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:02 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: Bhupesh Sharma, Ard Biesheuvel, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Bhupesh Sharma <bhsharma-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Now with open-source boot firmware (EDK2) supporting ACPI BGRT table
addition even for architectures like AARCH64, it makes sense to move
out the 'efi-bgrt.c' file and supporting infrastructure from 'arch/x86'
directory and house it inside 'drivers/firmware/efi', so that this common
code can be used across architectures.
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Signed-off-by: Bhupesh Sharma <bhsharma-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
arch/x86/platform/efi/Makefile | 1 -
drivers/firmware/efi/Makefile | 1 +
{arch/x86/platform => drivers/firmware}/efi/efi-bgrt.c | 0
3 files changed, 1 insertion(+), 1 deletion(-)
rename {arch/x86/platform => drivers/firmware}/efi/efi-bgrt.c (100%)
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index 066619b0700c..f1d83b34c329 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,6 +1,5 @@
OBJECT_FILES_NON_STANDARD_efi_thunk_$(BITS).o := y
obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
-obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index ad67342313ed..0329d319d89a 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -9,6 +9,7 @@
#
KASAN_SANITIZE_runtime-wrappers.o := n
+obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o
obj-$(CONFIG_EFI) += capsule.o memmap.o
obj-$(CONFIG_EFI_VARS) += efivars.o
diff --git a/arch/x86/platform/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
similarity index 100%
rename from arch/x86/platform/efi/efi-bgrt.c
rename to drivers/firmware/efi/efi-bgrt.c
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 07/12] x86/efi: Clean up a minor mistake in code comment
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
` (3 preceding siblings ...)
2017-04-04 16:02 ` [PATCH 04/12] x86/efi-bgrt: Move efi-bgrt handling out of arch/x86 Ard Biesheuvel
@ 2017-04-04 16:02 ` Ard Biesheuvel
2017-04-04 16:02 ` [PATCH 08/12] efi/arm32-stub: Allow boottime allocations in the vmlinux region Ard Biesheuvel
` (2 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:02 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: Baoquan He, Ard Biesheuvel, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Baoquan He <bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
EFI allocate runtime services regions from EFI_VA_START, -4G, down
to -68G, EFI_VA_END, 64G altogether. The mechanism was introduced in
commit d2f7cbe7b26a7 ("x86/efi: Runtime services virtual mapping").
Clean it up to avoid confusion.
Signed-off-by: Baoquan He <bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
arch/x86/platform/efi/efi_64.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index d56dd864fb1c..4e043a8c8556 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -47,7 +47,7 @@
#include <asm/pgalloc.h>
/*
- * We allocate runtime services regions bottom-up, starting from -4G, i.e.
+ * We allocate runtime services regions top-down, starting from -4G, i.e.
* 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G.
*/
static u64 efi_va = EFI_VA_START;
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 08/12] efi/arm32-stub: Allow boottime allocations in the vmlinux region
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
` (4 preceding siblings ...)
2017-04-04 16:02 ` [PATCH 07/12] x86/efi: Clean up a minor mistake in code comment Ard Biesheuvel
@ 2017-04-04 16:02 ` Ard Biesheuvel
2017-04-04 16:02 ` [PATCH 09/12] efi/libstub: Fix harmless command line parsing bug Ard Biesheuvel
2017-04-04 16:09 ` [PATCH 10/12] efi/libstub: Unify command line param parsing Ard Biesheuvel
7 siblings, 0 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:02 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: Ard Biesheuvel, linux-kernel-u79uwXL29TY76Z2rM5mHXA
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.
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Reviewed-by: Leif Lindholm <leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Reviewed-by: Eugene Cohen <eugene-VXdhtT5mjnY@public.gmane.org>
Reviewed-by: Roy Franz <roy.franz-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
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 e1f0b28e1dcb..18a8b5eb55e7 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 = &memory_map,
+ .map_size = &map_size,
+ .desc_size = &desc_size,
+ .desc_ver = NULL,
+ .key_ptr = NULL,
+ .buff_size = &buff_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, &alloc_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, &map);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table_arg,
+ "reserve_kernel_base(): Unable to retrieve memory map.\n");
+ return status;
+ }
+
+ for (l = 0; l < map_size; l += desc_size) {
+ efi_memory_desc_t *desc;
+ u64 start, end;
+
+ desc = (void *)memory_map + l;
+ start = desc->phys_addr;
+ end = start + desc->num_pages * EFI_PAGE_SIZE;
+
+ /* Skip if entry does not intersect with region */
+ if (start >= dram_base + MAX_UNCOMP_KERNEL_SIZE ||
+ end <= dram_base)
+ continue;
+
+ switch (desc->type) {
+ case EFI_BOOT_SERVICES_CODE:
+ case EFI_BOOT_SERVICES_DATA:
+ /* Ignore types that are released to the OS anyway */
+ continue;
+
+ case EFI_CONVENTIONAL_MEMORY:
+ /*
+ * Reserve the intersection between this entry and the
+ * region.
+ */
+ start = max(start, (u64)dram_base);
+ end = min(end, (u64)dram_base + MAX_UNCOMP_KERNEL_SIZE);
+
+ status = efi_call_early(allocate_pages,
+ EFI_ALLOCATE_ADDRESS,
+ EFI_LOADER_DATA,
+ (end - start) / EFI_PAGE_SIZE,
+ &start);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table_arg,
+ "reserve_kernel_base(): alloc failed.\n");
+ goto out;
+ }
+ break;
+
+ case EFI_LOADER_CODE:
+ case EFI_LOADER_DATA:
+ /*
+ * These regions may be released and reallocated for
+ * another purpose (including EFI_RUNTIME_SERVICE_DATA)
+ * at any time during the execution of the OS loader,
+ * so we cannot consider them as safe.
+ */
+ default:
+ /*
+ * Treat any other allocation in the region as unsafe */
+ status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+ }
+
+ status = EFI_SUCCESS;
+out:
+ efi_call_early(free_pool, memory_map);
+ return status;
+}
+
efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
unsigned long *image_addr,
unsigned long *image_size,
@@ -71,10 +197,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
unsigned long dram_base,
efi_loaded_image_t *image)
{
- unsigned long nr_pages;
efi_status_t status;
- /* Use alloc_addr to tranlsate between types */
- efi_physical_addr_t alloc_addr;
/*
* Verify that the DRAM base address is compatible with the ARM
@@ -85,27 +208,12 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
*/
dram_base = round_up(dram_base, SZ_128M);
- /*
- * 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;
- *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
- nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
- status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS,
- EFI_LOADER_DATA,
- nr_pages, &alloc_addr);
+ status = reserve_kernel_base(sys_table, dram_base, reserve_addr,
+ reserve_size);
if (status != EFI_SUCCESS) {
- *reserve_size = 0;
pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
return status;
}
- *reserve_addr = alloc_addr;
/*
* Relocate the zImage, so that it appears in the lowest 128 MB
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 09/12] efi/libstub: Fix harmless command line parsing bug
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
` (5 preceding siblings ...)
2017-04-04 16:02 ` [PATCH 08/12] efi/arm32-stub: Allow boottime allocations in the vmlinux region Ard Biesheuvel
@ 2017-04-04 16:02 ` Ard Biesheuvel
2017-04-04 16:09 ` [PATCH 10/12] efi/libstub: Unify command line param parsing Ard Biesheuvel
7 siblings, 0 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:02 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: Ard Biesheuvel, linux-kernel-u79uwXL29TY76Z2rM5mHXA
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.
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
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 919822b7773d..3290fae0b38f 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 == ',')
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 10/12] efi/libstub: Unify command line param parsing
[not found] ` <20170404160245.27812-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
` (6 preceding siblings ...)
2017-04-04 16:02 ` [PATCH 09/12] efi/libstub: Fix harmless command line parsing bug Ard Biesheuvel
@ 2017-04-04 16:09 ` Ard Biesheuvel
2017-04-04 16:09 ` [PATCH 11/12] efi/libstub: arm/arm64: Disable debug prints on 'quiet' cmdline arg Ard Biesheuvel
[not found] ` <20170404160910.28115-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
7 siblings, 2 replies; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:09 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: matt-mF/unelCI9GS6iBeEJttW/XRex20P6io, mark.rutland-5wv7dgnIgG8,
roy.franz-YGCgFSpz5w/QT0dZR+AlfA,
rruigrok-sgV2jX0FEOL9JmXXK+q4OQ,
leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
jhugo-sgV2jX0FEOL9JmXXK+q4OQ,
evgeny.kalugin-ral2JQCrhuEAvxtiuMwx3w, eugene-VXdhtT5mjnY,
bp-Gina5bIWoIWzQB+pC5nmwQ, bhsharma-H+wXaHxf7aLQT0dZR+AlfA,
bhe-H+wXaHxf7aLQT0dZR+AlfA, Ard Biesheuvel,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
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.
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
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 02049ff25c6b..ac3222f6f805 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, &image_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 eae693eb3e91..b4c2589d7c91 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 *)&phys_seed);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 3290fae0b38f..2e17d2b8787c 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_SLOTS 8
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.
*/
-efi_status_t efi_parse_options(char *cmdline)
+efi_status_t efi_parse_options(char const *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;
+ str = strstr(cmdline, "nokaslr");
+ if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
+ __nokaslr = 1;
/*
* If no EFI parameters were specified on the cmdline we've got
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 71c4d0e3c4ed..a7a2a2c3f199 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -24,6 +24,8 @@
#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
#endif
+extern int __pure nokaslr(void);
+
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/include/linux/efi.h b/include/linux/efi.h
index 94d34e0be24f..e485e87615d1 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1471,7 +1471,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
unsigned long *load_addr,
unsigned long *load_size);
-efi_status_t efi_parse_options(char *cmdline);
+efi_status_t efi_parse_options(char const *cmdline);
efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
struct screen_info *si, efi_guid_t *proto,
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 11/12] efi/libstub: arm/arm64: Disable debug prints on 'quiet' cmdline arg
2017-04-04 16:09 ` [PATCH 10/12] efi/libstub: Unify command line param parsing Ard Biesheuvel
@ 2017-04-04 16:09 ` Ard Biesheuvel
2017-04-11 4:08 ` Jon Masters
[not found] ` <20170404160910.28115-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
1 sibling, 1 reply; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:09 UTC (permalink / raw)
To: linux-efi, Ingo Molnar, Thomas Gleixner, H . Peter Anvin
Cc: matt, mark.rutland, roy.franz, rruigrok, leif.lindholm, jhugo,
evgeny.kalugin, eugene, bp, bhsharma, bhe, Ard Biesheuvel,
linux-kernel
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.
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
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 ac3222f6f805..657bb72c9e0b 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, &image_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 18a8b5eb55e7..becbda445913 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -9,6 +9,8 @@
#include <linux/efi.h>
#include <asm/efi.h>
+#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 2e17d2b8787c..b0184360efc6 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_SLOTS 8
@@ -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 a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index a7a2a2c3f199..83f268c05007 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -25,6 +25,13 @@
#endif
extern int __pure nokaslr(void);
+extern int __pure is_quiet(void);
+
+#define pr_efi(sys_table, msg) do { \
+ if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \
+} while (0)
+
+#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c
index 5da36e56b36a..8c34d50a4d80 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -12,6 +12,8 @@
#include <linux/efi.h>
#include <asm/efi.h>
+#include "efistub.h"
+
/* BIOS variables */
static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
static const efi_char16_t const efi_SecureBoot_name[] = {
diff --git a/include/linux/efi.h b/include/linux/efi.h
index e485e87615d1..ec36f42a2add 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1435,9 +1435,6 @@ static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
/* prototypes shared between arch specific and generic stub code */
-#define pr_efi(sys_table, msg) efi_printk(sys_table, "EFI stub: "msg)
-#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
-
void efi_printk(efi_system_table_t *sys_table_arg, char *str);
void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 11/12] efi/libstub: arm/arm64: Disable debug prints on 'quiet' cmdline arg
2017-04-04 16:09 ` [PATCH 11/12] efi/libstub: arm/arm64: Disable debug prints on 'quiet' cmdline arg Ard Biesheuvel
@ 2017-04-11 4:08 ` Jon Masters
0 siblings, 0 replies; 20+ messages in thread
From: Jon Masters @ 2017-04-11 4:08 UTC (permalink / raw)
To: Ard Biesheuvel, linux-efi, Ingo Molnar, Thomas Gleixner, H . Peter Anvin
Cc: matt, mark.rutland, roy.franz, rruigrok, leif.lindholm, jhugo,
evgeny.kalugin, eugene, bp, bhsharma, bhe, linux-kernel
On 04/04/2017 12:09 PM, Ard Biesheuvel wrote:
> 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.
> +extern int __pure is_quiet(void);
> +
> +#define pr_efi(sys_table, msg) do { \
> + if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \
> +} while (0)
> +
> +#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
Thanks for this one :)
Jon.
^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <20170404160910.28115-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>]
* [PATCH 12/12] ef/libstub: arm/arm64: Randomize the base of the UEFI rt services region
[not found] ` <20170404160910.28115-1-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2017-04-04 16:09 ` Ard Biesheuvel
[not found] ` <20170404160910.28115-3-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
0 siblings, 1 reply; 20+ messages in thread
From: Ard Biesheuvel @ 2017-04-04 16:09 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ingo Molnar, Thomas Gleixner,
H . Peter Anvin
Cc: matt-mF/unelCI9GS6iBeEJttW/XRex20P6io, mark.rutland-5wv7dgnIgG8,
roy.franz-YGCgFSpz5w/QT0dZR+AlfA,
rruigrok-sgV2jX0FEOL9JmXXK+q4OQ,
leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
jhugo-sgV2jX0FEOL9JmXXK+q4OQ,
evgeny.kalugin-ral2JQCrhuEAvxtiuMwx3w, eugene-VXdhtT5mjnY,
bp-Gina5bIWoIWzQB+pC5nmwQ, bhsharma-H+wXaHxf7aLQT0dZR+AlfA,
bhe-H+wXaHxf7aLQT0dZR+AlfA, Ard Biesheuvel,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
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 give the lack of a downside, let's enable it nonetheless.
Cc: Ingo Molnar <mingo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Borislav Petkov <bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org>
Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
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 657bb72c9e0b..1e45ec51b094 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_BASE SZ_512M
+#define EFI_RT_VIRTUAL_SIZE SZ_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 *)&rnd);
+ 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,
&new_fdt_addr, efi_get_max_fdt_addr(dram_base),
@@ -242,18 +277,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
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_BASE SZ_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 *runtime_map,
int *count)
{
- u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
+ u64 efi_virt_base = virtmap_base;
efi_memory_desc_t *in, *prev = NULL, *out = runtime_map;
int l;
--
2.9.3
^ permalink raw reply related [flat|nested] 20+ messages in thread