mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 00:34:52 +00:00

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
109 lines
2.4 KiB
C
109 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#define BOOT_CTYPE_H
|
|
#include "misc.h"
|
|
#include "error.h"
|
|
#include "../string.h"
|
|
|
|
#include <linux/efi.h>
|
|
#include <asm/efi.h>
|
|
|
|
/*
|
|
* Max length of 64-bit hex address string is 19, prefix "0x" + 16 hex
|
|
* digits, and '\0' for termination.
|
|
*/
|
|
#define MAX_ADDR_LEN 19
|
|
|
|
static acpi_physical_address get_acpi_rsdp(void)
|
|
{
|
|
acpi_physical_address addr = 0;
|
|
|
|
#ifdef CONFIG_KEXEC
|
|
char val[MAX_ADDR_LEN] = { };
|
|
int ret;
|
|
|
|
ret = cmdline_find_option("acpi_rsdp", val, MAX_ADDR_LEN);
|
|
if (ret < 0)
|
|
return 0;
|
|
|
|
if (kstrtoull(val, 16, &addr))
|
|
return 0;
|
|
#endif
|
|
return addr;
|
|
}
|
|
|
|
/* 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;
|
|
}
|