Received: by 2002:a05:6358:bb9e:b0:b9:5105:a5b4 with SMTP id df30csp4198764rwb; Tue, 6 Sep 2022 04:14:31 -0700 (PDT) X-Google-Smtp-Source: AA6agR7H+bmNFhIJCcwA5R10aG0FqGG0PKSCBBx4AoMO6cBjcywvM1SVY72TPRsv3Tz/9IIZwTos X-Received: by 2002:a17:907:7ea3:b0:741:a1a3:b33a with SMTP id qb35-20020a1709077ea300b00741a1a3b33amr25897167ejc.356.1662462871383; Tue, 06 Sep 2022 04:14:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662462871; cv=none; d=google.com; s=arc-20160816; b=cev00lWTrUzz4knlqENaegFniwMXSZ/Pf/LCWSwXEOA09Muf25wC/J6MWuvc9leVgr zJVsvYeFS1jmrD5CNM+yKtG11wKjKxkLjNQOKJ83o6mw2/N7uyfwjVu9EsBVRxuQ63dz CbRE/2lI/RmwMWxaslL3kMEV4zME4XJnqdzUdtc1xG9ElDrWAhCY4D2uaVgo0Nkn5F1J mGVG+y/SFZDGNaZxVN35cSHzE3jIeqbD/32S2DgSpixyKD9R3a5wPXRrjpn4CSRmsrER YbREa7Jv4fw82yWti9Qaoh2ON25FHEQCIw6t1EL4Boz2BAzJcXQiE9Wq/KsFcSja4gVT 9x0A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=Z49otyx2QkREMDV98m9oR7g7o2GtnmqIwTpmtE2pZ9c=; b=yPS8AcGFI5cWuYYu0s0hWsVQ54LhOpbCoMM8RNVvZ2spmNTSD1dS765Rl+xuDq01BI 9ZJ2B+iHVlc+qEfiHsFGifGVvVvpDWuJhQ6cjtEbgb3GgG37evoXg7BpEsL7PXOh5QsP 7jgLNpwDdLLzmFbMMeb+ThaSjuGisRzxtcun4B7an1dnkQczb7gOjmmm85oZWR3GahBo EgdjZiovJg/bXtCiABkHNWNEe46td+tG5GBpBZRcksrto2CRA7K0vmh48MqlWhhuke2+ PF/6BSTV7bl0COqUPVr8DmvkrSUietoFwJor00gIlP4qkucjWjA2veQ9MPC0XSlLrop1 av1w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ispras.ru Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gs7-20020a1709072d0700b00741a18d4a5asi10595307ejc.994.2022.09.06.04.13.55; Tue, 06 Sep 2022 04:14:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ispras.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239701AbiIFKmi (ORCPT + 99 others); Tue, 6 Sep 2022 06:42:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56904 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238694AbiIFKl5 (ORCPT ); Tue, 6 Sep 2022 06:41:57 -0400 Received: from mail.ispras.ru (mail.ispras.ru [83.149.199.84]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7979660683; Tue, 6 Sep 2022 03:41:47 -0700 (PDT) Received: from localhost.localdomain (unknown [83.149.199.65]) by mail.ispras.ru (Postfix) with ESMTPSA id 8D727407625F; Tue, 6 Sep 2022 10:41:39 +0000 (UTC) From: Evgeniy Baskov To: Ard Biesheuvel Cc: Evgeniy Baskov , Borislav Petkov , Andy Lutomirski , Dave Hansen , Ingo Molnar , Peter Zijlstra , Thomas Gleixner , Alexey Khoroshilov , lvc-project@linuxtesting.org, x86@kernel.org, linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH 12/16] x86/boot: Add EFI kernel extraction interface Date: Tue, 6 Sep 2022 13:41:16 +0300 Message-Id: <8e9f2d7b0645e17efaa9eec0423f6d2c4a55fc16.1662459668.git.baskov@ispras.ru> X-Mailer: git-send-email 2.35.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org To enable extraction of kernel image from EFI stub code directly extraction code needs to have separate interface that avoid part of low level initialization logic, i.e. serial port setup. Add kernel extraction function callable from libstub as a part of preparation for extracting the kernel directly from EFI environment. Signed-off-by: Evgeniy Baskov --- arch/x86/boot/compressed/head_32.S | 3 +- arch/x86/boot/compressed/head_64.S | 2 +- arch/x86/boot/compressed/misc.c | 85 +++++++++++++++++++++--------- arch/x86/boot/compressed/misc.h | 2 + arch/x86/boot/compressed/putstr.c | 9 ++++ 5 files changed, 73 insertions(+), 28 deletions(-) diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index 3b354eb9516d..b46a1c4109cf 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -217,8 +217,7 @@ SYM_DATA(image_offset, .long 0) */ .bss .balign 4 -boot_heap: - .fill BOOT_HEAP_SIZE, 1, 0 +SYM_DATA(boot_heap, .fill BOOT_HEAP_SIZE, 1, 0) boot_stack: .fill BOOT_STACK_SIZE, 1, 0 boot_stack_end: diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 889ca7176aa7..37ce094571b5 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -1007,7 +1007,7 @@ SYM_FUNC_END(startup32_check_sev_cbit) */ .bss .balign 4 -SYM_DATA_LOCAL(boot_heap, .fill BOOT_HEAP_SIZE, 1, 0) +SYM_DATA(boot_heap, .fill BOOT_HEAP_SIZE, 1, 0) SYM_DATA_START_LOCAL(boot_stack) .fill BOOT_STACK_SIZE, 1, 0 diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index e2c0d05ac293..8016cc5c300e 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -293,11 +293,11 @@ static void parse_elf(void *output, unsigned long output_len, * |-------uncompressed kernel image---------| * */ -asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, - unsigned char *input_data, - unsigned long input_len, - unsigned char *output, - unsigned long output_len) +static void *do_extract_kernel(void *rmode, + unsigned char *input_data, + unsigned long input_len, + unsigned char *output, + unsigned long output_len) { const unsigned long kernel_total_size = VO__end - VO__text; unsigned long virt_addr = LOAD_PHYSICAL_ADDR; @@ -311,18 +311,6 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, sanitize_boot_params(boot_params); - init_default_io_ops(); - - /* - * Detect TDX guest environment. - * - * It has to be done before console_init() in order to use - * paravirtualized port I/O operations if needed. - */ - early_tdx_detect(); - - init_bare_console(); - /* * Save RSDP address for later use. Have this after console_init() * so that early debugging output from the RSDP parsing code can be @@ -330,11 +318,6 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, */ boot_params->acpi_rsdp_addr = get_rsdp_addr(); - debug_putstr("early console in extract_kernel\n"); - - free_mem_ptr = heap; /* Heap */ - free_mem_end_ptr = heap + BOOT_HEAP_SIZE; - /* * The memory hole needed for the kernel is the larger of either * the entire decompressed kernel plus relocation table, or the @@ -387,12 +370,12 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, if (virt_addr & (MIN_KERNEL_ALIGN - 1)) error("Destination virtual address inappropriately aligned"); #ifdef CONFIG_X86_64 - if (heap > 0x3fffffffffffUL) + if (phys_addr > 0x3fffffffffffUL) error("Destination address too large"); if (virt_addr + max(output_len, kernel_total_size) > KERNEL_IMAGE_SIZE) error("Destination virtual address is beyond the kernel mapping area"); #else - if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff)) + if (phys_addr > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff)) error("Destination address too large"); #endif #ifndef CONFIG_RELOCATABLE @@ -406,12 +389,64 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, parse_elf(output, output_len, virt_addr); debug_putstr("done.\nBooting the kernel.\n"); + return output; +} + +asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, + unsigned char *input_data, + unsigned long input_len, + unsigned char *output, + unsigned long output_len) +{ + void *entry; + + init_default_io_ops(); + + /* + * Detect TDX guest environment. + * + * It has to be done before console_init() in order to use + * paravirtualized port I/O operations if needed. + */ + early_tdx_detect(); + + init_bare_console(); + + debug_putstr("early console in extract_kernel\n"); + + free_mem_ptr = heap; /* Heap */ + free_mem_end_ptr = heap + BOOT_HEAP_SIZE; + + entry = do_extract_kernel(rmode, input_data, + input_len, output, output_len); + /* Disable exception handling before booting the kernel */ cleanup_exception_handling(); - return output; + return entry; } +void *efi_extract_kernel(struct boot_params *rmode, + struct efi_iofunc *iofunc, + unsigned char *input_data, + unsigned long input_len, + unsigned char *output, + unsigned long output_len) +{ + extern char boot_heap[BOOT_HEAP_SIZE]; + + free_mem_ptr = (unsigned long)boot_heap; /* Heap */ + free_mem_end_ptr = (unsigned long)boot_heap + BOOT_HEAP_SIZE; + + init_efi_console(iofunc); + + return do_extract_kernel(rmode, input_data, + input_len, output, output_len); +} + + + + void fortify_panic(const char *name) { error("detected buffer overflow"); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 39dc3de50268..b5aa0af6c59e 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "tdx.h" @@ -126,6 +127,7 @@ static inline void console_init(void) /* putstr.c */ void init_bare_console(void); +void init_efi_console(struct efi_iofunc *iofunc); #ifdef CONFIG_AMD_MEM_ENCRYPT void sev_enable(struct boot_params *bp); diff --git a/arch/x86/boot/compressed/putstr.c b/arch/x86/boot/compressed/putstr.c index accba0de8be9..238d9677df61 100644 --- a/arch/x86/boot/compressed/putstr.c +++ b/arch/x86/boot/compressed/putstr.c @@ -32,6 +32,15 @@ void init_bare_console(void) console_init(); } +void init_efi_console(struct efi_iofunc *iofunc) +{ + __putstr = iofunc->putstr; + __puthex = iofunc->puthex; +#ifdef CONFIG_X86_64 + kernel_add_identity_map = iofunc->map_range; +#endif +} + static void scroll(void) { int i; -- 2.35.1