Messages in this thread Patch in this message | | | From | Junichi Nomura <> | Subject | [PATCH] x86/boot: Use EFI setup data if provided | Date | Fri, 22 Mar 2019 11:03:43 +0000 |
| |
Commit 3a63f70bf4c3a ("x86/boot: Early parse RSDP and save it in boot_params") broke kexec boot on EFI systems. efi_get_rsdp_addr() in the early parsing code tries to search RSDP from EFI table but whose address is virtual.
Since kexec(1) provides physical address of config_table via boot_params, efi_get_rsdp_addr() should look for setup_data in the same way as efi_systab_init() in arch/x86/platform/efi/efi.c does.
Fixes: 3a63f70bf4c3a ("x86/boot: Early parse RSDP and save it in boot_params") Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com> Cc: Chao Fan <fanc.fnst@cn.fujitsu.com> Cc: Borislav Petkov <bp@suse.de>
diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c index 0ef4ad5..9f3b1b9 100644 --- a/arch/x86/boot/compressed/acpi.c +++ b/arch/x86/boot/compressed/acpi.c @@ -44,6 +44,22 @@ static acpi_physical_address get_acpi_rsdp(void) return addr; } +static unsigned long efi_get_setup_data_addr(void) +{ + struct setup_data *data; + u64 pa_data; + + pa_data = boot_params->hdr.setup_data; + while (pa_data) { + data = (struct setup_data *) pa_data; + if (data->type == SETUP_EFI) + return pa_data + sizeof(struct setup_data); + pa_data = data->next; + } + + return 0; +} + /* Search EFI system tables for RSDP. */ static acpi_physical_address efi_get_rsdp_addr(void) { @@ -53,10 +69,12 @@ static acpi_physical_address efi_get_rsdp_addr(void) unsigned long systab, systab_tables, config_tables; unsigned int nr_tables; struct efi_info *ei; + struct efi_setup_data *esd; bool efi_64; int size, i; char *sig; + esd = (struct efi_setup_data *) efi_get_setup_data_addr(); ei = &boot_params->efi_info; sig = (char *)&ei->efi_loader_signature; @@ -86,13 +104,13 @@ static acpi_physical_address efi_get_rsdp_addr(void) if (efi_64) { efi_system_table_64_t *stbl = (efi_system_table_64_t *)systab; - config_tables = stbl->tables; + config_tables = esd ? esd->tables : stbl->tables; nr_tables = stbl->nr_tables; size = sizeof(efi_config_table_64_t); } else { efi_system_table_32_t *stbl = (efi_system_table_32_t *)systab; - config_tables = stbl->tables; + config_tables = esd ? esd->tables : stbl->tables; nr_tables = stbl->nr_tables; size = sizeof(efi_config_table_32_t); }
| |