Received: by 2002:a25:5b86:0:0:0:0:0 with SMTP id p128csp1258714ybb; Fri, 29 Mar 2019 00:28:50 -0700 (PDT) X-Google-Smtp-Source: APXvYqxeIiQCC8EmPlz/EpDElyR+Fo+VxPCzyTdVXV5es2IYBeCqVpFdsMG5YFrwStfhULJ4to+c X-Received: by 2002:a63:6949:: with SMTP id e70mr43995090pgc.89.1553844530292; Fri, 29 Mar 2019 00:28:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553844530; cv=none; d=google.com; s=arc-20160816; b=Oi72wm3R6Q1ZGaNZz1EXV1vy6Lcc6fDJVSq5uw1ZxY4X2A0LNxAi4M6JMTTYq9sY75 153fRhgyMwG/6K5EkxmgThrZSv3djvRvbdeGGsGgmIBOUebFthinwpsREqcZBnIjK3NN IAwBRFFRgAhGzaSuLRJNZ8cZbciIjxPryT6TKgNRFbqilzHtQpu0RkUy6MtwH4YaKDf4 lVpulekjz5RO2gUtzP6BBaZVWcJMkSEFsRinWobnc4GPiR3HZDMu0PrpE0qJVKwPQ2hj phOxsc7knMoY8lYjJabFBNzhEbvloNuoOpzb8q0G0L3/Y/NzIOupWGy9pLllrV2oSy6f 7CVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:content-transfer-encoding :content-id:content-language:accept-language:in-reply-to:references :message-id:date:thread-index:thread-topic:subject:cc:to:from; bh=gKtEga9ytqu2mRPqgh7KuHB/ljKg7KigPUBLCSbJJc0=; b=pXflXF37BZ1VFtY3elOpNHSvH0RNHbkDsyy5AtSWUX1kw7gCUgzsQ/LHO+hsvReZsY eAmIRk6bMLNjfi7emwUrM71dzNv7P4e2qFzypokztZWvDd3O3cSago06OlWoQpyu1wmP D+nzN8+3Snkune3JmfScPWD28m1RdYAPFvZ5FIj1jjcIRhdZAd0rxug355Ck11Jhijox CRt6ETTVwK1YsZdkWyuJ0rdkQPFz19OwHPB1BhuK3z4ykPK4uABHSHQBdbU++hynU05W 2D2L2Fdzk/TessSweJdpQpXHOYceW/065Kvz5RFcy8FG53D6l/U/kMGBigQA284mGNCb ZgcQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e10si1250474pgm.298.2019.03.29.00.28.22; Fri, 29 Mar 2019 00:28:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728878AbfC2HXv convert rfc822-to-8bit (ORCPT + 99 others); Fri, 29 Mar 2019 03:23:51 -0400 Received: from tyo161.gate.nec.co.jp ([114.179.232.161]:56221 "EHLO tyo161.gate.nec.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728790AbfC2HXv (ORCPT ); Fri, 29 Mar 2019 03:23:51 -0400 Received: from mailgate01.nec.co.jp ([114.179.233.122]) by tyo161.gate.nec.co.jp (8.15.1/8.15.1) with ESMTPS id x2T7NHxv029256 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Fri, 29 Mar 2019 16:23:17 +0900 Received: from mailsv02.nec.co.jp (mailgate-v.nec.co.jp [10.204.236.94]) by mailgate01.nec.co.jp (8.15.1/8.15.1) with ESMTP id x2T7NGZT030738; Fri, 29 Mar 2019 16:23:16 +0900 Received: from mail01b.kamome.nec.co.jp (mail01b.kamome.nec.co.jp [10.25.43.2]) by mailsv02.nec.co.jp (8.15.1/8.15.1) with ESMTP id x2T7LU9u026766; Fri, 29 Mar 2019 16:23:16 +0900 Received: from bpxc99gp.gisp.nec.co.jp ([10.38.151.140] [10.38.151.140]) by mail01b.kamome.nec.co.jp with ESMTP id BT-MMP-3805520; Fri, 29 Mar 2019 16:20:40 +0900 Received: from BPXM12GP.gisp.nec.co.jp ([10.38.151.204]) by BPXC12GP.gisp.nec.co.jp ([10.38.151.140]) with mapi id 14.03.0319.002; Fri, 29 Mar 2019 16:20:39 +0900 From: Junichi Nomura To: Borislav Petkov , "bhe@redhat.com" , "Dave Young" , "fanc.fnst@cn.fujitsu.com" CC: "kasong@redhat.com" , "x86@kernel.org" , "kexec@lists.infradead.org" , "linux-kernel@vger.kernel.org" Subject: [PATCH] x86/boot: Use efi_setup_data for searching RSDP on kexec-ed kernel Thread-Topic: [PATCH] x86/boot: Use efi_setup_data for searching RSDP on kexec-ed kernel Thread-Index: AQHU5f/oFwt4tfwJ5EeDzlajOHAcUA== Date: Fri, 29 Mar 2019 07:20:38 +0000 Message-ID: <20190329072037.GA5840@jeru.linux.bs1.fc.nec.co.jp> References: <20190325120149.GI12016@zn.tnic> <20190325122302.GC13160@dhcp-128-65.nay.redhat.com> <20190325123229.GL12016@zn.tnic> <20190325231000.GA9184@jeru.linux.bs1.fc.nec.co.jp> <20190326135714.GG1867@zn.tnic> <20190327014852.GA3659@MiWiFi-R3L-srv> <73322ba9-e436-68db-7863-afd31607d969@ce.jp.nec.com> <20190328064343.GA1877@MiWiFi-R3L-srv> <20190328074337.GA9470@jeru.linux.bs1.fc.nec.co.jp> <20190328155256.GP22720@zn.tnic> In-Reply-To: <20190328155256.GP22720@zn.tnic> Accept-Language: en-US, ja-JP Content-Language: ja-JP X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.34.125.85] Content-Type: text/plain; charset="iso-2022-jp" Content-ID: <717D56458AFA0548A857AD1D618F5F85@gisp.nec.co.jp> Content-Transfer-Encoding: 8BIT MIME-Version: 1.0 X-TM-AS-MML: disable Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 that will crash because the table address is virtual when the kernel was booted by kexec. In the case of kexec, physical address of EFI tables is provided via efi_setup_data in boot_params, which is set up by kexec(1). Factor out the table parsing code and use different pointers depending on whether the kernel is booted by kexec or not. Fixes: 3a63f70bf4c3a ("x86/boot: Early parse RSDP and save it in boot_params") Signed-off-by: Jun'ichi Nomura Cc: Chao Fan Cc: Borislav Petkov Cc: Dave Young Cc: Baoquan He diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c --- a/arch/x86/boot/compressed/acpi.c +++ b/arch/x86/boot/compressed/acpi.c @@ -44,17 +44,109 @@ static acpi_physical_address get_acpi_rsdp(void) return addr; } +#ifdef CONFIG_EFI +static unsigned long efi_get_kexec_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) +static acpi_physical_address +__efi_get_rsdp_addr(unsigned long config_tables, unsigned int nr_tables, + bool efi_64) { acpi_physical_address rsdp_addr = 0; + int i; + + /* Get EFI tables from systab. */ + for (i = 0; i < nr_tables; i++) { + acpi_physical_address table; + efi_guid_t guid; + + if (efi_64) { + efi_config_table_64_t *tbl = (efi_config_table_64_t *) config_tables + i; + + guid = tbl->guid; + table = tbl->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 *tbl = (efi_config_table_32_t *) config_tables + i; + + guid = tbl->guid; + table = tbl->table; + } + + if (!(efi_guidcmp(guid, ACPI_TABLE_GUID))) + rsdp_addr = table; + else if (!(efi_guidcmp(guid, ACPI_20_TABLE_GUID))) + return table; + } + + return rsdp_addr; +} +#endif +static acpi_physical_address kexec_get_rsdp_addr(void) +{ #ifdef CONFIG_EFI - unsigned long systab, systab_tables, config_tables; + efi_system_table_64_t *systab; + struct efi_setup_data *esd; + struct efi_info *ei; + char *sig; + + esd = (struct efi_setup_data *) efi_get_kexec_setup_data_addr(); + if (!esd) + return 0; + + if (!esd->tables) { + debug_putstr("Wrong kexec SETUP_EFI data.\n"); + return 0; + } + + ei = &boot_params->efi_info; + sig = (char *)&ei->efi_loader_signature; + /* + * EFI/kexec support is only added for 64bit. So we don't have to + * care 32bit case. + */ + if (strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) { + debug_putstr("Wrong kexec EFI loader signature.\n"); + return 0; + } + + /* Get systab from boot params. */ + systab = (efi_system_table_64_t *) (ei->efi_systab | ((__u64)ei->efi_systab_hi << 32)); + if (!systab) + error("EFI system table not found in kexec boot_params."); + + return __efi_get_rsdp_addr((unsigned long) esd->tables, + systab->nr_tables, true); +#else + return 0; +#endif +} + +static acpi_physical_address efi_get_rsdp_addr(void) +{ +#ifdef CONFIG_EFI + unsigned long systab, config_tables; unsigned int nr_tables; struct efi_info *ei; bool efi_64; - int size, i; char *sig; ei = &boot_params->efi_info; @@ -88,49 +180,20 @@ static acpi_physical_address efi_get_rsdp_addr(void) config_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; nr_tables = stbl->nr_tables; - size = sizeof(efi_config_table_32_t); } if (!config_tables) error("EFI config tables not found."); - /* Get EFI tables from systab. */ - for (i = 0; i < nr_tables; i++) { - acpi_physical_address table; - efi_guid_t guid; - - config_tables += size; - - if (efi_64) { - efi_config_table_64_t *tbl = (efi_config_table_64_t *)config_tables; - - guid = tbl->guid; - table = tbl->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 *tbl = (efi_config_table_32_t *)config_tables; - - guid = tbl->guid; - table = tbl->table; - } - - if (!(efi_guidcmp(guid, ACPI_TABLE_GUID))) - rsdp_addr = table; - else if (!(efi_guidcmp(guid, ACPI_20_TABLE_GUID))) - return table; - } + return __efi_get_rsdp_addr(config_tables, nr_tables, efi_64); +#else + return 0; #endif - return rsdp_addr; } static u8 compute_checksum(u8 *buffer, u32 length) @@ -221,6 +284,9 @@ acpi_physical_address get_rsdp_addr(void) pa = boot_params->acpi_rsdp_addr; if (!pa) + pa = kexec_get_rsdp_addr(); + + if (!pa) pa = efi_get_rsdp_addr(); if (!pa)