Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp6409535yba; Thu, 11 Apr 2019 19:57:24 -0700 (PDT) X-Google-Smtp-Source: APXvYqya4xvNvuzz3XOsSNBdwD3uezn+cyCbpzkf1w/Eu/Kzk/TfY6alftRc1ifzdLSnJ+6q6qzv X-Received: by 2002:a63:ac12:: with SMTP id v18mr48236100pge.111.1555037844813; Thu, 11 Apr 2019 19:57:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555037844; cv=none; d=google.com; s=arc-20160816; b=pLbJbChMEEONFacv9G5yJr1iUF46LlEJK/FE7x0S0/OXRSNHOgTX1t8J6kjH8j1Vmu bJkrjx5YbqHmh5YTU9FqSt3YIR/HBArQ//wkxcjhnw/dBG6xeg/J1oxc2OE31uyxCpLO XFs/nmdi32dvs4kUpupG/912d4DhufrXpk8fygY6NwLYNodBNbI14PzCRQK3YjAoBLdj XK7WtlDP31sLqg12DN95HNA7G909QJR8TeDWU8Q5fRqiRQlt59gtBXKReWrTG7c+6s1T 2oR/WN6uebI7IMVhxQvQn+I6O9kNam6HxYqgbiFKAoOB3GCuVFx7M+fMLlq79zyvIB8U dKiw== 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=HJq07Dltz7JmsBj1SVxuQ05RCafPcsEdErjehK8migk=; b=GrdhuutmhXqytrAWer8Puu9eFCLZWt8tsnlwmfbBQQIc2qoVNkH+7JtHQfMfL3UbCf ryqbqakkRZqWnscrLpFX+L6IVVvzzWlW0nmCBow0+Ue+QgN4GmoEiNFzS2PCtB/Lhjav Js1m//JLTm+YTXj1+oNElv0IxB2FlCuOb9mZ0dtyixGSH/KfZy85TUT1olSoHA7z6dh6 dwwNY1XGHO/3RqkawHjX/OiMpVg/JGDLUqRnJ20GDZPxMHZbyDcL7tKdXEzV1xBgCv2s jc9ELfbbkEnl5Z0oJQOqp1bX4IY+34So25sit6fWI+DSuQHFz5i9TkcPdXIk5asoZErW +PNw== 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 c10si35479073plo.216.2019.04.11.19.57.01; Thu, 11 Apr 2019 19:57:24 -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 S1726720AbfDLC4W convert rfc822-to-8bit (ORCPT + 99 others); Thu, 11 Apr 2019 22:56:22 -0400 Received: from tyo161.gate.nec.co.jp ([114.179.232.161]:37690 "EHLO tyo161.gate.nec.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726678AbfDLC4W (ORCPT ); Thu, 11 Apr 2019 22:56:22 -0400 Received: from mailgate02.nec.co.jp ([114.179.233.122]) by tyo161.gate.nec.co.jp (8.15.1/8.15.1) with ESMTPS id x3C2u0XY008886 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Fri, 12 Apr 2019 11:56:00 +0900 Received: from mailsv01.nec.co.jp (mailgate-v.nec.co.jp [10.204.236.94]) by mailgate02.nec.co.jp (8.15.1/8.15.1) with ESMTP id x3C2txWZ011981; Fri, 12 Apr 2019 11:55:59 +0900 Received: from mail01b.kamome.nec.co.jp (mail01b.kamome.nec.co.jp [10.25.43.2]) by mailsv01.nec.co.jp (8.15.1/8.15.1) with ESMTP id x3C2rd00029504; Fri, 12 Apr 2019 11:55:59 +0900 Received: from bpxc99gp.gisp.nec.co.jp ([10.38.151.136] [10.38.151.136]) by mail02.kamome.nec.co.jp with ESMTP id BT-MMP-4231867; Fri, 12 Apr 2019 11:54:18 +0900 Received: from BPXM12GP.gisp.nec.co.jp ([10.38.151.204]) by BPXC08GP.gisp.nec.co.jp ([10.38.151.136]) with mapi id 14.03.0319.002; Fri, 12 Apr 2019 11:54:17 +0900 From: Junichi Nomura To: Borislav Petkov CC: Dave Young , Chao Fan , Baoquan He , Kairui Song , "x86@kernel.org" , "kexec@lists.infradead.org" , "linux-kernel@vger.kernel.org" Subject: Re: [PATCH v4] x86/boot: Use efi_setup_data for searching RSDP on kexec-ed kernel Thread-Topic: [PATCH v4] x86/boot: Use efi_setup_data for searching RSDP on kexec-ed kernel Thread-Index: AQHU78DnNYRsXw6c0kywKGsyat34OKY1dZqAgACP04CAAAH9AIAABdcAgAAJ5YCAAAJaAIAAAziAgAACJICAADc+AIAA6YwA Date: Fri, 12 Apr 2019 02:54:17 +0000 Message-ID: <20190412025416.GA11070@jeru.linux.bs1.fc.nec.co.jp> References: <20190410171431.GE26580@zn.tnic> <7cbc096d-0548-18b1-a335-8ba114f234a7@ce.jp.nec.com> <20190411080927.GA30080@zn.tnic> <20190411083738.GC30080@zn.tnic> <2946b5e3-90bf-d617-16a4-d2225b490b5d@ce.jp.nec.com> <20190411125822.GE30080@zn.tnic> In-Reply-To: <20190411125822.GE30080@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: 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 On 4/11/19 9:58 PM, Borislav Petkov wrote: > Something like this based on your v3. I still need to figure out a > reliable way to check in kexec_get_rsdp_addr() whether we're a kexec-ed > kernel but other than that, it should look something like this: Thank you. > +static struct efi_setup_data *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 (struct efi_setup_data *)(pa_data + sizeof(struct setup_data)); > + > + pa_data = data->next; > + } > + return NULL; > +} Without #ifdef CONFIG_X86_64, I got compiler warnings on 32bit build about casting u64 to pointer. > +/* EFI/kexec support is 64-bit only. */ > +static acpi_physical_address kexec_get_rsdp_addr(void) > +{ We need #ifdef CONFIG_EFI to avoid build failure about undefined __efi_get_rsdp_addr(). > + efi_system_table_64_t *systab; > + struct efi_setup_data *esd; > + struct efi_info *ei; > + char *sig; > + > + if (!IS_ENABLED(CONFIG_X86_64)) > + return 0; > + > + esd = get_kexec_setup_data_addr(); > + if (!esd) > + return EFI_SETUP_DATA_INVALID; > > + if (!esd->tables) { > + debug_putstr("Wrong kexec SETUP_EFI data.\n"); > + return 0; > + } I think that should be the other way around: esd = get_kexec_setup_data_addr(); if (!esd) // the kernel is not kexec booted return 0; if (!esd->tables) { // kexec booted but data is invalid debug_putstr("Wrong kexec SETUP_EFI data.\n"); return EFI_SETUP_DATA_INVALID; } And other error returns in kexec_get_rsdp_addr() should also be EFI_SETUP_DATA_INVALID. > + /* Get systab from boot params. */ > + systab = (efi_system_table_64_t *) (ei->efi_systab | ((__u64)ei->efi_systab_hi << 32)); Though there is !IS_ENABLED(CONFIG_X86_64), compiler still sees this code and emits warning on 32bit build. To fix 32bit build warnings, non-EFI build errors and return values from kexec_get_rsdp_addr(), the patch becomes: diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c index 0ef4ad5..715a8b0 100644 --- a/arch/x86/boot/compressed/acpi.c +++ b/arch/x86/boot/compressed/acpi.c @@ -8,6 +8,8 @@ #include #include +#define EFI_SETUP_DATA_INVALID -1ULL + /* * Longest parameter of 'acpi=' is 'copy_dsdt', plus an extra '\0' * for termination. @@ -44,17 +46,114 @@ static acpi_physical_address get_acpi_rsdp(void) return addr; } -/* Search EFI system tables for RSDP. */ -static acpi_physical_address efi_get_rsdp_addr(void) +static struct efi_setup_data *get_kexec_setup_data_addr(void) +{ +#if defined(CONFIG_EFI) && defined(CONFIG_X86_64) + 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 (struct efi_setup_data *)(pa_data + sizeof(struct setup_data)); + + pa_data = data->next; + } +#endif + return NULL; +} + +#ifdef CONFIG_EFI +/* + * Search EFI system tables for RSDP. If both ACPI_20_TABLE_GUID and + * ACPI_TABLE_GUID are found, take the former, which has more features. + */ +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 + +/* EFI/kexec support is 64-bit only. */ +static acpi_physical_address kexec_get_rsdp_addr(void) { acpi_physical_address rsdp_addr = 0; +#if defined(CONFIG_EFI) && defined(CONFIG_X86_64) + efi_system_table_64_t *systab; + struct efi_setup_data *esd; + struct efi_info *ei; + char *sig; + + esd = get_kexec_setup_data_addr(); + if (!esd) + return 0; + if (!esd->tables) { + debug_putstr("Wrong kexec SETUP_EFI data.\n"); + return EFI_SETUP_DATA_INVALID; + } + + ei = &boot_params->efi_info; + sig = (char *)&ei->efi_loader_signature; + if (strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) { + debug_putstr("Wrong kexec EFI loader signature.\n"); + return EFI_SETUP_DATA_INVALID; + } + + /* 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."); + + rsdp_addr = __efi_get_rsdp_addr((unsigned long)esd->tables, systab->nr_tables, true); + if (!rsdp_addr) + return EFI_SETUP_DATA_INVALID; +#endif + + return rsdp_addr; +} + +static acpi_physical_address efi_get_rsdp_addr(void) +{ #ifdef CONFIG_EFI - unsigned long systab, systab_tables, config_tables; + 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 +187,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 +291,12 @@ acpi_physical_address get_rsdp_addr(void) pa = boot_params->acpi_rsdp_addr; if (!pa) + pa = kexec_get_rsdp_addr(); + + if (pa == EFI_SETUP_DATA_INVALID) + return 0; + + if (!pa) pa = efi_get_rsdp_addr(); if (!pa) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index c0d6c56..e98f8cf 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -379,6 +379,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, debug_putaddr(output); debug_putaddr(output_len); debug_putaddr(kernel_total_size); + debug_putaddr(boot_params->acpi_rsdp_addr); #ifdef CONFIG_X86_64 /* Report address of 32-bit trampoline */