Skip to content

Commit

Permalink
x86/boot: Search for RSDP in the EFI tables
Browse files Browse the repository at this point in the history
The immovable memory ranges information in the SRAT table is necessary
to fix the issue of KASLR not paying attention to movable memory regions
when selecting the offset. Therefore, SRAT needs to be parsed.

Depending on the boot: KEXEC/EFI/BIOS, the methods to compute RSDP are
different. When booting from EFI, the EFI table points to the RSDP. So
iterate over the EFI system tables in order to find the RSDP.

 [ bp:
   - Heavily massage commit message
   - Trim comments
   - Move the CONFIG_ACPI ifdeffery into the Makefile.
 ]

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: bhe@redhat.com
Cc: caoj.fnst@cn.fujitsu.com
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: indou.takao@jp.fujitsu.com
Cc: Ingo Molnar <mingo@redhat.com>
Cc: kasong@redhat.com
Cc: Kees Cook <keescook@chromium.org>
Cc: msys.mizuma@gmail.com
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86-ml <x86@kernel.org>
Link: https://lkml.kernel.org/r/20190123110850.12433-4-fanc.fnst@cn.fujitsu.com
  • Loading branch information
Chao Fan authored and Borislav Petkov committed Feb 1, 2019
1 parent 3c98e71 commit 33f0df8
Showing 1 changed file with 79 additions and 2 deletions.
81 changes: 79 additions & 2 deletions arch/x86/boot/compressed/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include "error.h"
#include "../string.h"

#ifdef CONFIG_ACPI
#include <linux/efi.h>
#include <asm/efi.h>

/*
* Max length of 64-bit hex address string is 19, prefix "0x" + 16 hex
Expand All @@ -29,4 +30,80 @@ static acpi_physical_address get_acpi_rsdp(void)
#endif
return addr;
}
#endif /* CONFIG_ACPI */

/* Search EFI system tables for RSDP. */
static acpi_physical_address efi_get_rsdp_addr(void)
{
acpi_physical_address rsdp_addr = 0;

#ifdef CONFIG_EFI
efi_system_table_t *systab;
struct efi_info *ei;
bool efi_64;
int size, i;
char *sig;

ei = &boot_params->efi_info;
sig = (char *)&ei->efi_loader_signature;

if (!strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) {
efi_64 = true;
} else if (!strncmp(sig, EFI32_LOADER_SIGNATURE, 4)) {
efi_64 = false;
} else {
debug_putstr("Wrong EFI loader signature.\n");
return 0;
}

/* Get systab from boot params. */
#ifdef CONFIG_X86_64
systab = (efi_system_table_t *)(ei->efi_systab | ((__u64)ei->efi_systab_hi<<32));
#else
if (ei->efi_systab_hi || ei->efi_memmap_hi) {
debug_putstr("Error getting RSDP address: EFI system table located above 4GB.\n");
return 0;
}
systab = (efi_system_table_t *)ei->efi_systab;
#endif
if (!systab)
error("EFI system table not found.");

/*
* Get EFI tables from systab.
*/
size = efi_64 ? sizeof(efi_config_table_64_t) :
sizeof(efi_config_table_32_t);

for (i = 0; i < systab->nr_tables; i++) {
acpi_physical_address table;
void *config_tables;
efi_guid_t guid;

config_tables = (void *)(systab->tables + size * i);
if (efi_64) {
efi_config_table_64_t *tmp_table;

tmp_table = config_tables;
guid = tmp_table->guid;
table = tmp_table->table;

if (!IS_ENABLED(CONFIG_X86_64) && table >> 32) {
debug_putstr("Error getting RSDP address: EFI config table located above 4GB.\n");
return 0;
}
} else {
efi_config_table_32_t *tmp_table;

tmp_table = config_tables;
guid = tmp_table->guid;
table = tmp_table->table;
}

if (!(efi_guidcmp(guid, ACPI_TABLE_GUID)))
rsdp_addr = table;
else if (!(efi_guidcmp(guid, ACPI_20_TABLE_GUID)))
return table;
}
#endif
return rsdp_addr;
}

0 comments on commit 33f0df8

Please sign in to comment.