[PATCH] x86/boot/compressed/64: Do not read legacy ROM on EFI system

From: Kirill A. Shutemov
Date: Tue Feb 19 2019 - 02:52:43 EST


EFI systems may not provide legacy ROM. The memory may not be mapped
at all.

Trying to dereference values in legacy ROM leads to crash on Macbook
Pro.

Only look for values in the legacy ROM for non-EFI system.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202351
Fixes: 3548e131ec6a ("x86/boot/compressed/64: Find a place for 32-bit trampoline")
Reported-by: Pitam Mitra <pitamm@xxxxxxxxx>
Tested-by: Bockjoo Kim <bockjoo@xxxxxxxxxxxx>
---
arch/x86/boot/compressed/pgtable_64.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 9e2157371491..f8debf7aeb4c 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -1,5 +1,7 @@
+#include <linux/efi.h>
#include <asm/e820/types.h>
#include <asm/processor.h>
+#include <asm/efi.h>
#include "pgtable.h"
#include "../string.h"

@@ -37,9 +39,10 @@ int cmdline_find_option_bool(const char *option);

static unsigned long find_trampoline_placement(void)
{
- unsigned long bios_start, ebda_start;
+ unsigned long bios_start = 0, ebda_start = 0;
unsigned long trampoline_start;
struct boot_e820_entry *entry;
+ char *signature;
int i;

/*
@@ -47,8 +50,18 @@ static unsigned long find_trampoline_placement(void)
* This code is based on reserve_bios_regions().
*/

- ebda_start = *(unsigned short *)0x40e << 4;
- bios_start = *(unsigned short *)0x413 << 10;
+ /*
+ * EFI systems may not provide legacy ROM. The memory may not be mapped
+ * at all.
+ *
+ * Only look for values in the legacy ROM for non-EFI system.
+ */
+ signature = (char *)&boot_params->efi_info.efi_loader_signature;
+ if (strncmp(signature, EFI32_LOADER_SIGNATURE, 4) &&
+ strncmp(signature, EFI64_LOADER_SIGNATURE, 4)) {
+ ebda_start = *(unsigned short *)0x40e << 4;
+ bios_start = *(unsigned short *)0x413 << 10;
+ }

if (bios_start < BIOS_START_MIN || bios_start > BIOS_START_MAX)
bios_start = BIOS_START_MAX;
--
2.20.1