diff options
author | Michael Roth <michael.roth@amd.com> | 2022-02-24 17:56:08 +0100 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2022-04-06 17:07:24 +0200 |
commit | 824f37783189a48db914488fb41eba36ec57ebb7 (patch) | |
tree | a4429fed17dab41d3650a86e1865f8d335074a3e /arch/x86/boot/compressed/efi.c | |
parent | x86/compressed/acpi: Move EFI vendor table lookup to helper (diff) | |
download | linux-824f37783189a48db914488fb41eba36ec57ebb7.tar.xz linux-824f37783189a48db914488fb41eba36ec57ebb7.zip |
x86/compressed/acpi: Move EFI kexec handling into common code
Future patches for SEV-SNP-validated CPUID will also require early
parsing of the EFI configuration. Incrementally move the related code
into a set of helpers that can be re-used for that purpose.
In this instance, the current acpi.c kexec handling is mainly used to
get the alternative EFI config table address provided by kexec via a
setup_data entry of type SETUP_EFI. If not present, the code then falls
back to normal EFI config table address provided by EFI system table.
This would need to be done by all call-sites attempting to access the
EFI config table, so just have efi_get_conf_table() handle that
automatically.
Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220307213356.2797205-29-brijesh.singh@amd.com
Diffstat (limited to 'arch/x86/boot/compressed/efi.c')
-rw-r--r-- | arch/x86/boot/compressed/efi.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/arch/x86/boot/compressed/efi.c b/arch/x86/boot/compressed/efi.c index 4d363dfc2b33..09fa3b5d70b8 100644 --- a/arch/x86/boot/compressed/efi.c +++ b/arch/x86/boot/compressed/efi.c @@ -78,6 +78,46 @@ unsigned long efi_get_system_table(struct boot_params *bp) return sys_tbl_pa; } +/* + * EFI config table address changes to virtual address after boot, which may + * not be accessible for the kexec'd kernel. To address this, kexec provides + * the initial physical address via a struct setup_data entry, which is + * checked for here, along with some sanity checks. + */ +static struct efi_setup_data *get_kexec_setup_data(struct boot_params *bp, + enum efi_type et) +{ +#ifdef CONFIG_X86_64 + struct efi_setup_data *esd = NULL; + struct setup_data *data; + u64 pa_data; + + pa_data = bp->hdr.setup_data; + while (pa_data) { + data = (struct setup_data *)pa_data; + if (data->type == SETUP_EFI) { + esd = (struct efi_setup_data *)(pa_data + sizeof(struct setup_data)); + break; + } + + pa_data = data->next; + } + + /* + * Original ACPI code falls back to attempting normal EFI boot in these + * cases, so maintain existing behavior by indicating non-kexec + * environment to the caller, but print them for debugging. + */ + if (esd && !esd->tables) { + debug_putstr("kexec EFI environment missing valid configuration table.\n"); + return NULL; + } + + return esd; +#endif + return NULL; +} + /** * efi_get_conf_table - Given a pointer to boot_params, locate and return the physical * address of EFI configuration table. @@ -106,8 +146,12 @@ int efi_get_conf_table(struct boot_params *bp, unsigned long *cfg_tbl_pa, et = efi_get_type(bp); if (et == EFI_TYPE_64) { efi_system_table_64_t *stbl = (efi_system_table_64_t *)sys_tbl_pa; + struct efi_setup_data *esd; - *cfg_tbl_pa = stbl->tables; + /* kexec provides an alternative EFI conf table, check for it. */ + esd = get_kexec_setup_data(bp, et); + + *cfg_tbl_pa = esd ? esd->tables : stbl->tables; *cfg_tbl_len = stbl->nr_tables; } else if (et == EFI_TYPE_32) { efi_system_table_32_t *stbl = (efi_system_table_32_t *)sys_tbl_pa; |