From patchwork Mon May 2 11:17:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 569140 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1AC9C433FE for ; Mon, 2 May 2022 11:17:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229768AbiEBLUy (ORCPT ); Mon, 2 May 2022 07:20:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229872AbiEBLUw (ORCPT ); Mon, 2 May 2022 07:20:52 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03A4EBC17; Mon, 2 May 2022 04:17:22 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 8B15761283; Mon, 2 May 2022 11:17:22 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41F0FC385AF; Mon, 2 May 2022 11:17:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1651490242; bh=GkYFnxMu4KkGdGXijx6fJDyeOKqT+h0EwHNgiNnnBK8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fv//++GuSKeLCwJG0gn1sKviE01NtlO/W4IDmpeVyOgPI8GvzHiEiMWb1PdtbHTFp CJg2HCtZ11W3S0M3m1DEq5XVRiCh70TjR3BwYc6cBIr31Oezrmj0eZol7eV4KGdVgl ewNSwer5OWRd0E0Gu4BButn62mMXobZjd06FBoUsEH4lPRuc/LdN4rJfMTuIRQOBM9 5luOlQ1PSPJVCCpDDZ222wzRKLbMn4jAlKaMt98znzeB5jQX3nPV8kBZ11d52Up+kB orSqqAZrWGjtw4C+kpIR2wbOB7esOjOvlhGYh5yOYpyu2cZ2qd/yDdlE1k0/mJzsLz Vl9VBugZXaV+g== From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: catalin.marinas@arm.com, will@kernel.org, Ard Biesheuvel , Arnd Bergmann , Huacai Chen Subject: [RFC PATCH 1/4] efi: stub: add prototypes for load_image and start_image Date: Mon, 2 May 2022 13:17:07 +0200 Message-Id: <20220502111710.4093567-2-ardb@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220502111710.4093567-1-ardb@kernel.org> References: <20220502111710.4093567-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1131; h=from:subject; bh=GkYFnxMu4KkGdGXijx6fJDyeOKqT+h0EwHNgiNnnBK8=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBib72xIBginCS26tW5lPV0Am+u4nhJKhJfv1OdqDDX FHO8zTCJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYm+9sQAKCRDDTyI5ktmPJL/kC/ 9aJ94BcWsWtSXHbvFgQFseIjMD/xVQlRiq0W0pgfRdZ74ZlP+i0B5JnOu0/2AhGBePPFgMJmsExJET RyGDtQ/S8mLOU3l1px97P09uJCStb6XI8Cwfw/f65W7v2KOEKyZbm+r8vcF0USzj1mddWj6C31gtus uYnjSkRAIYQZcucrEl6O9MTEHofL9qGxVtMtGeFabmbYg83sj8io0PzgutsIE5MZA504XPRIk71HAN 6lzSk82PAJ1EeUVAMBLcEdom6LQ9RXq+4Tf5A7dyw7l4ggMu5kgnEg5cVSnYekw6dgC6db4fjgmu6Q zPTKB2iYApDh3lfR5EOVzPDg+IT/GXvzzZORTU1sv/PTAOsWPEe7OAPF6JBqYfDP1A64KpkNMmXqnt NG5/1mYLJOKHhf2uXpqChn5IrDnLHsS/i7RuWHjZW29KLfsoLNKOmwh5RvEhxnhFYgvHrnBEi4csSi Zd7PwT4pyylClq8BwWZXtVV1z1PD1KvR/jszGgILmF5Qo= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Define the correct prototypes for the load_image and start_image boot service pointers so we can call them from the EFI zboot code. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/efistub.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index a0477afaa55f..af51ccc01ce2 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -254,8 +254,12 @@ union efi_boot_services { efi_handle_t *); efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *, void *); - void *load_image; - void *start_image; + efi_status_t (__efiapi *load_image)(bool, efi_handle_t, + efi_device_path_protocol_t *, + void *, unsigned long, + efi_handle_t *); + efi_status_t (__efiapi *start_image)(efi_handle_t, unsigned long *, + efi_char16_t **); efi_status_t __noreturn (__efiapi *exit)(efi_handle_t, efi_status_t, unsigned long, From patchwork Mon May 2 11:17:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 568822 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D9ACC433EF for ; Mon, 2 May 2022 11:17:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232459AbiEBLUz (ORCPT ); Mon, 2 May 2022 07:20:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34964 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231325AbiEBLUx (ORCPT ); Mon, 2 May 2022 07:20:53 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2D40ABCB0; Mon, 2 May 2022 04:17:25 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B5DA761277; Mon, 2 May 2022 11:17:24 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 675DCC385B2; Mon, 2 May 2022 11:17:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1651490244; bh=OOQBVOqF3++jx4QGewlUZACo0PAy/QbkHdOU9wLVVf8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fNHhIVfmpOaA+HcIRebkOP2LCEqA4zur1t+lysyhjs5APDe1T1RFZhMvn4IaaL1dF 00/jbrrlC2HR7MtI05fAtlie7EDU+Vqt7PuwdQS90Z6U8YVCxx2NBCDr8vajsuZCcG NcI5DyqS0A8E8XETUZeAEG1sB0qWiOJRCb/deTbMguMSgS0l+RjcMU83ScOGu2j+Te 3U2dTrcMczq05mJKjov7gNp/hyd/XetoF6kdTT6I9ZmNoOHIdBrN6UDUzf152kWzJH eUEyhbF54axQAaaDb/njVoZWFOE7UN3clTXXOxnz+Qt5KIIk7t3qOR+0QZkyWt/ahV xVcT4ptgMX6mw== From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: catalin.marinas@arm.com, will@kernel.org, Ard Biesheuvel , Arnd Bergmann , Huacai Chen Subject: [RFC PATCH 2/4] efi: stub: split off printk() routines Date: Mon, 2 May 2022 13:17:08 +0200 Message-Id: <20220502111710.4093567-3-ardb@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220502111710.4093567-1-ardb@kernel.org> References: <20220502111710.4093567-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=9433; h=from:subject; bh=OOQBVOqF3++jx4QGewlUZACo0PAy/QbkHdOU9wLVVf8=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBib72yW74QnfHB0luK669f/ZcvJ40i19xEpkVYUb6X P3WKIDmJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYm+9sgAKCRDDTyI5ktmPJH7rC/ 9HnD3zUL7i+ki5d7U37jVyAEaACuvc5Qut3nyG1xTwQ8vXHjGM/7fxBdRoyfhML8+06A2DMBBAmbO1 JglTUoeHUdTWGO3TgZ+DY0GIw8/ZCzI2Y9R7fdcrHCVuuAoLGnW8Ru8wT9uHEgpGxDxbtmF697AxUD pF4Q0WapIWFIr//vj0LRlSCgt1TSw6TTrRn2Kc3I9cdkHsi2S5+vAM5UTch6A3+fNYkJexUihTZWhl QVoFFlAuG5x2YJZ3U+E32urIKieXxoCEHveFgJL/0avGHwMsbbqvXjHnMxwUaGmGJZTwIg8hHW4oUi 2KPguJAA1pdpZjLztmvM/sfHPiyLorgswerIc9viORXaolMxugfJQ7u793CcelnzuMdT0Q+VwJlmSO x45/wnN/Vh7TkGvCr8lHEIfAq6eQ3IBt9dtfpAf57eKGg/G92Azo6sNlZu/6ZYg6fCVCl+2NV8/oMe sasaspvtETtRvVyqkWg4ui24ho842c3jGAmPRvELRapqs= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org We will be using the libstub static library also to build the EFI zboot decompressor, which is a separate binary and does not carry all the dependencies of efi-stub-helper.c, which is where efi_printk() currently lives. So split it off into printk.c so we can incorporate it separately. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/efi-stub-helper.c | 141 ----------------- drivers/firmware/efi/libstub/printk.c | 158 ++++++++++++++++++++ 3 files changed, 159 insertions(+), 142 deletions(-) diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index d0537573501e..475224be08e1 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -55,7 +55,7 @@ KCOV_INSTRUMENT := n lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ file.o mem.o random.o randomalloc.o pci.o \ skip_spaces.o lib-cmdline.o lib-ctype.o \ - alignedmem.o relocate.o vsprintf.o + alignedmem.o relocate.o vsprintf.o printk.o # include the stub's generic dependencies from lib/ when building for ARM/arm64 efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 3d972061c1b0..45910c834133 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -20,7 +20,6 @@ bool efi_nochunk; bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE); -int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT; bool efi_novamap; static bool efi_noinitrd; @@ -32,146 +31,6 @@ bool __pure __efi_soft_reserve_enabled(void) return !efi_nosoftreserve; } -/** - * efi_char16_puts() - Write a UCS-2 encoded string to the console - * @str: UCS-2 encoded string - */ -void efi_char16_puts(efi_char16_t *str) -{ - efi_call_proto(efi_table_attr(efi_system_table, con_out), - output_string, str); -} - -static -u32 utf8_to_utf32(const u8 **s8) -{ - u32 c32; - u8 c0, cx; - size_t clen, i; - - c0 = cx = *(*s8)++; - /* - * The position of the most-significant 0 bit gives us the length of - * a multi-octet encoding. - */ - for (clen = 0; cx & 0x80; ++clen) - cx <<= 1; - /* - * If the 0 bit is in position 8, this is a valid single-octet - * encoding. If the 0 bit is in position 7 or positions 1-3, the - * encoding is invalid. - * In either case, we just return the first octet. - */ - if (clen < 2 || clen > 4) - return c0; - /* Get the bits from the first octet. */ - c32 = cx >> clen--; - for (i = 0; i < clen; ++i) { - /* Trailing octets must have 10 in most significant bits. */ - cx = (*s8)[i] ^ 0x80; - if (cx & 0xc0) - return c0; - c32 = (c32 << 6) | cx; - } - /* - * Check for validity: - * - The character must be in the Unicode range. - * - It must not be a surrogate. - * - It must be encoded using the correct number of octets. - */ - if (c32 > 0x10ffff || - (c32 & 0xf800) == 0xd800 || - clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000)) - return c0; - *s8 += clen; - return c32; -} - -/** - * efi_puts() - Write a UTF-8 encoded string to the console - * @str: UTF-8 encoded string - */ -void efi_puts(const char *str) -{ - efi_char16_t buf[128]; - size_t pos = 0, lim = ARRAY_SIZE(buf); - const u8 *s8 = (const u8 *)str; - u32 c32; - - while (*s8) { - if (*s8 == '\n') - buf[pos++] = L'\r'; - c32 = utf8_to_utf32(&s8); - if (c32 < 0x10000) { - /* Characters in plane 0 use a single word. */ - buf[pos++] = c32; - } else { - /* - * Characters in other planes encode into a surrogate - * pair. - */ - buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10); - buf[pos++] = 0xdc00 + (c32 & 0x3ff); - } - if (*s8 == '\0' || pos >= lim - 2) { - buf[pos] = L'\0'; - efi_char16_puts(buf); - pos = 0; - } - } -} - -/** - * efi_printk() - Print a kernel message - * @fmt: format string - * - * The first letter of the format string is used to determine the logging level - * of the message. If the level is less then the current EFI logging level, the - * message is suppressed. The message will be truncated to 255 bytes. - * - * Return: number of printed characters - */ -int efi_printk(const char *fmt, ...) -{ - char printf_buf[256]; - va_list args; - int printed; - int loglevel = printk_get_level(fmt); - - switch (loglevel) { - case '0' ... '9': - loglevel -= '0'; - break; - default: - /* - * Use loglevel -1 for cases where we just want to print to - * the screen. - */ - loglevel = -1; - break; - } - - if (loglevel >= efi_loglevel) - return 0; - - if (loglevel >= 0) - efi_puts("EFI stub: "); - - fmt = printk_skip_level(fmt); - - va_start(args, fmt); - printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args); - va_end(args); - - efi_puts(printf_buf); - if (printed >= sizeof(printf_buf)) { - efi_puts("[Message truncated]\n"); - return -1; - } - - return printed; -} - /** * efi_parse_options() - Parse EFI command line options * @cmdline: kernel command line diff --git a/drivers/firmware/efi/libstub/printk.c b/drivers/firmware/efi/libstub/printk.c new file mode 100644 index 000000000000..ec09bf895c1a --- /dev/null +++ b/drivers/firmware/efi/libstub/printk.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Helper functions used by the EFI stub on multiple + * architectures. This should be #included by the EFI stub + * implementation files. + * + * Copyright 2011 Intel Corporation; author Matt Fleming + */ + +#include +#include +#include +#include /* For CONSOLE_LOGLEVEL_* */ +#include + +#include "efistub.h" + +int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT; + +/** + * efi_char16_puts() - Write a UCS-2 encoded string to the console + * @str: UCS-2 encoded string + */ +void efi_char16_puts(efi_char16_t *str) +{ + efi_call_proto(efi_table_attr(efi_system_table, con_out), + output_string, str); +} + +static +u32 utf8_to_utf32(const u8 **s8) +{ + u32 c32; + u8 c0, cx; + size_t clen, i; + + c0 = cx = *(*s8)++; + /* + * The position of the most-significant 0 bit gives us the length of + * a multi-octet encoding. + */ + for (clen = 0; cx & 0x80; ++clen) + cx <<= 1; + /* + * If the 0 bit is in position 8, this is a valid single-octet + * encoding. If the 0 bit is in position 7 or positions 1-3, the + * encoding is invalid. + * In either case, we just return the first octet. + */ + if (clen < 2 || clen > 4) + return c0; + /* Get the bits from the first octet. */ + c32 = cx >> clen--; + for (i = 0; i < clen; ++i) { + /* Trailing octets must have 10 in most significant bits. */ + cx = (*s8)[i] ^ 0x80; + if (cx & 0xc0) + return c0; + c32 = (c32 << 6) | cx; + } + /* + * Check for validity: + * - The character must be in the Unicode range. + * - It must not be a surrogate. + * - It must be encoded using the correct number of octets. + */ + if (c32 > 0x10ffff || + (c32 & 0xf800) == 0xd800 || + clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000)) + return c0; + *s8 += clen; + return c32; +} + +/** + * efi_puts() - Write a UTF-8 encoded string to the console + * @str: UTF-8 encoded string + */ +void efi_puts(const char *str) +{ + efi_char16_t buf[128]; + size_t pos = 0, lim = ARRAY_SIZE(buf); + const u8 *s8 = (const u8 *)str; + u32 c32; + + while (*s8) { + if (*s8 == '\n') + buf[pos++] = L'\r'; + c32 = utf8_to_utf32(&s8); + if (c32 < 0x10000) { + /* Characters in plane 0 use a single word. */ + buf[pos++] = c32; + } else { + /* + * Characters in other planes encode into a surrogate + * pair. + */ + buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10); + buf[pos++] = 0xdc00 + (c32 & 0x3ff); + } + if (*s8 == '\0' || pos >= lim - 2) { + buf[pos] = L'\0'; + efi_char16_puts(buf); + pos = 0; + } + } +} + +/** + * efi_printk() - Print a kernel message + * @fmt: format string + * + * The first letter of the format string is used to determine the logging level + * of the message. If the level is less then the current EFI logging level, the + * message is suppressed. The message will be truncated to 255 bytes. + * + * Return: number of printed characters + */ +int efi_printk(const char *fmt, ...) +{ + char printf_buf[256]; + va_list args; + int printed; + int loglevel = printk_get_level(fmt); + + switch (loglevel) { + case '0' ... '9': + loglevel -= '0'; + break; + default: + /* + * Use loglevel -1 for cases where we just want to print to + * the screen. + */ + loglevel = -1; + break; + } + + if (loglevel >= efi_loglevel) + return 0; + + if (loglevel >= 0) + efi_puts("EFI stub: "); + + fmt = printk_skip_level(fmt); + + va_start(args, fmt); + printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args); + va_end(args); + + efi_puts(printf_buf); + if (printed >= sizeof(printf_buf)) { + efi_puts("[Message truncated]\n"); + return -1; + } + + return printed; +} From patchwork Mon May 2 11:17:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 568821 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D854C433EF for ; Mon, 2 May 2022 11:17:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1384662AbiEBLU7 (ORCPT ); Mon, 2 May 2022 07:20:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231325AbiEBLU5 (ORCPT ); Mon, 2 May 2022 07:20:57 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C1D88BC17; Mon, 2 May 2022 04:17:28 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 773AEB81058; Mon, 2 May 2022 11:17:27 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8E30FC385B1; Mon, 2 May 2022 11:17:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1651490246; bh=XZW/JCwgq6tAw7SBVFrShBag6VMdsc/+bw/ci9pjai8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=meMSGpfLtiqiULufuetTFyooi5QvodYIOaB5T5MTHvniaV4y6KWwIgcoYX4wOyU5D TA49uykteL1QTu3HrWw7etPRbxupDe0Ho1VmFo5X77RWEiap7aGziyQZ+Ac6igpK3V SyVwtqbsxTkXeypY+mLIFP6/rOBZGL8UYLVuTXz8U4+u/5D/UaRu//3Yw6R2MKLf9P KtR/nzrh+K0QoAsacvlOKA2XTvFocohhV43OzYhzpfTfMKSBcL5AnnpBy8lwdp57ob RvvqHLbYxph5Y04LYj/eUkgSkzpwzNZlu8JoELW8gFC6wH6oB24dDmKd82GU3NY1ks HNaTFH58s0DVQ== From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: catalin.marinas@arm.com, will@kernel.org, Ard Biesheuvel , Arnd Bergmann , Huacai Chen Subject: [RFC PATCH 3/4] efi: stub: implement generic EFI zboot Date: Mon, 2 May 2022 13:17:09 +0200 Message-Id: <20220502111710.4093567-4-ardb@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220502111710.4093567-1-ardb@kernel.org> References: <20220502111710.4093567-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7694; h=from:subject; bh=XZW/JCwgq6tAw7SBVFrShBag6VMdsc/+bw/ci9pjai8=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBib720DoYS1bUZZqROM1Mfg1BFpkY8ohlfCZ05VNuj EZm9+suJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYm+9tAAKCRDDTyI5ktmPJFEKC/ 0drSc8Ho8I6aLTjcpoamZCH+R6SoI0sjd2wraHC7ZcEB8BPaNgYg6m1FgUoquOi1Te4zRDR4bV5dfy KjLF5vBGKl7auXLXe5BwvvQsWYd/+8KhPTZV5kYIsI9NAx5OyyjZ4J9RX/p69HZk0GYJut6PC50A5C 2KsikHg+fnNPESpyl4J9lQEN7Um6yJPv/y82WrEfQz7Jdd12BFAswjTQMP69K3PDcoZZ+BBuaBD9NA SfdJ8gwNPS9yY82wIpRZ+T+kC5bJokuL1wV+fR6QNVu8DZxWphLuDKpPGrcG2eVB+Xhv5BlKPEomac Hcx/Q6JvC0V55cFEhLqatprR+rKNugVgX55a8VRop+O8kbpteSz5ojcvXSDWdamxQRciG62SAZn9x4 vvkOQEtswViTWS8gRWAc3xzxFpPaIVvpDRblelK9j93HrfE2rV53GiGt1rgc88VZ232bcIGUeFT56G FrlFtP4F2Miv3t+LAdXjRWyNiZs65wH+PAOUl1T+wgT10= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Implement a minimal EFI app that decompresses the real kernel image and launches it using the firmware's LoadImage and StartImage boot services. This removes the need for any arch-specific hacks. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/Kconfig | 6 ++ drivers/firmware/efi/libstub/Makefile | 2 + drivers/firmware/efi/libstub/zboot-header.S | 88 ++++++++++++++++++++ drivers/firmware/efi/libstub/zboot.c | 86 +++++++++++++++++++ drivers/firmware/efi/libstub/zboot.lds | 44 ++++++++++ 5 files changed, 226 insertions(+) diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 4720ba98cec3..5fc986f66505 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -116,6 +116,12 @@ config EFI_RUNTIME_WRAPPERS config EFI_GENERIC_STUB bool +config EFI_ZBOOT + bool "Enable the generic EFI decompressor" + depends on EFI_GENERIC_STUB + depends on !ARM && !X86 + select HAVE_KERNEL_GZIP + config EFI_ARMSTUB_DTB_LOADER bool "Enable the DTB loader" depends on EFI_GENERIC_STUB && !RISCV diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 475224be08e1..71bd877077b1 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -111,8 +111,10 @@ STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS # a verification pass to see if any absolute relocations exist in any of the # object files. # +lib-$(CONFIG_EFI_ZBOOT) += zboot.o extra-y := $(lib-y) lib-y := $(patsubst %.o,%.stub.o,$(lib-y)) +lib-$(CONFIG_EFI_ZBOOT) += zboot-header.o STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \ --prefix-symbols=__efistub_ diff --git a/drivers/firmware/efi/libstub/zboot-header.S b/drivers/firmware/efi/libstub/zboot-header.S new file mode 100644 index 000000000000..8f471866081a --- /dev/null +++ b/drivers/firmware/efi/libstub/zboot-header.S @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include + + .section ".head", "a" + .globl __efistub_efi_zboot_header +__efistub_efi_zboot_header: +.Ldoshdr: + .long MZ_MAGIC + .org .Ldoshdr + 0x3c + .long .Lpehdr - .Ldoshdr + +.Lpehdr: + .long PE_MAGIC + .short pe_machine_type + .short .Lsection_count + .long 0 + .long 0 + .long 0 + .short .Lsection_table - .Loptional_header + .short IMAGE_FILE_DEBUG_STRIPPED | \ + IMAGE_FILE_EXECUTABLE_IMAGE | \ + IMAGE_FILE_LINE_NUMS_STRIPPED + +.Loptional_header: +#ifdef CONFIG_64BIT + .short PE_OPT_MAGIC_PE32PLUS +#else + .short PE_OPT_MAGIC_PE32 +#endif + .byte 0, 0 + .long _etext - .Lefi_header_end + .long __data_size + .long 0 + .long __efistub_efi_zboot_entry - .Ldoshdr + .long .Lefi_header_end - .Ldoshdr + +#ifdef CONFIG_64BIT + .quad 0 +#else + .long _etext - .Lhead + .long 0 +#endif + .long 4096 + .long 512 + .short 0, 0, 0, 0, 0, 0 + .long 0 + .long _end - .Ldoshdr + + .long .Lefi_header_end - .Ldoshdr + .long 0 + .short IMAGE_SUBSYSTEM_EFI_APPLICATION + .short 0 + .quad 0, 0, 0, 0 + .long 0 + .long (.Lsection_table - .) / 8 + .quad 0, 0, 0, 0, 0, 0 + +.Lsection_table: + .ascii ".text\0\0\0" + .long _etext - .Lefi_header_end + .long .Lefi_header_end - .Ldoshdr + .long _etext - .Lefi_header_end + .long .Lefi_header_end - .Ldoshdr + + .long 0, 0 + .short 0, 0 + .long IMAGE_SCN_CNT_CODE | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_EXECUTE + + .ascii ".data\0\0\0" + .long __data_size + .long _etext - .Ldoshdr + .long __data_rawsize + .long _etext - .Ldoshdr + + .long 0, 0 + .short 0, 0 + .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_WRITE + + .set .Lsection_count, (. - .Lsection_table) / 40 + + .align 12 +.Lefi_header_end: + diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c new file mode 100644 index 000000000000..edb3390c808c --- /dev/null +++ b/drivers/firmware/efi/libstub/zboot.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +#include "efistub.h" + +#define STATIC static + +static unsigned char zboot_heap[SZ_64K] __aligned(64); +static unsigned long free_mem_ptr, free_mem_end_ptr; + +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif + +const efi_system_table_t *efi_system_table; + +extern char _gzdata_start[], _gzdata_end[]; +extern u32 uncompressed_size __aligned(1); + +static void error(char *x) +{ + efi_err("%s\n", x); +} + +efi_status_t __efiapi efi_zboot_entry(efi_handle_t handle, + efi_system_table_t *systab) +{ + efi_guid_t loaded_image = LOADED_IMAGE_PROTOCOL_GUID; + efi_loaded_image_t *parent, *child; + efi_handle_t child_handle = NULL; + unsigned long image_buffer; + efi_status_t status; + + free_mem_ptr = (unsigned long)&zboot_heap; + free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap); + + efi_system_table = systab; + + efi_info("Entering EFI decompressor\n"); + + status = efi_bs_call(handle_protocol, handle, &loaded_image, + (void **)&parent); + if (status != EFI_SUCCESS) { + efi_err("Failed to locate parent's loaded image protocol\n"); + return status; + } + + status = efi_allocate_pages(uncompressed_size, &image_buffer, ULONG_MAX); + if (status != EFI_SUCCESS) { + efi_err("Failed to allocate memory\n"); + return status; + } + + if (__decompress(_gzdata_start, _gzdata_end - _gzdata_start, NULL, + NULL, (unsigned char *)image_buffer, 0, NULL, + error) < 0) + return EFI_LOAD_ERROR; + + status = efi_bs_call(load_image, true, handle, NULL, + (void *)image_buffer, uncompressed_size, + &child_handle); + if (status != EFI_SUCCESS) { + efi_err("Failed to load image: %lx\n", status); + return status; + } + + status = efi_bs_call(handle_protocol, child_handle, &loaded_image, + (void **)&child); + if (status != EFI_SUCCESS) { + efi_err("Failed to locate child's loaded image protocol\n"); + return status; + } + + // Copy the kernel command line + child->load_options = parent->load_options; + child->load_options_size = parent->load_options_size; + + status = efi_bs_call(start_image, child_handle, NULL, NULL); + if (status != EFI_SUCCESS) { + efi_err("Failed to start image: %lx\n", status); + return status; + } + return EFI_SUCCESS; +} diff --git a/drivers/firmware/efi/libstub/zboot.lds b/drivers/firmware/efi/libstub/zboot.lds new file mode 100644 index 000000000000..56777b5f2668 --- /dev/null +++ b/drivers/firmware/efi/libstub/zboot.lds @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +ENTRY(__efistub_efi_zboot_header); + +SECTIONS +{ + .text : ALIGN(4096) { + *(.head) + *(.text* .init.text*) + } + + .rodata : ALIGN(8) { + __efistub__gzdata_start = .; + *(.gzdata) + __efistub__gzdata_end = . - 4; + __efistub_uncompressed_size = . - 4; + *(.rodata* .init.rodata*) + _etext = ALIGN(4096); + . = _etext; + } + + .data : ALIGN(4096) { + *(.data* .init.data*) + _edata = ALIGN(512); + . = _edata; + } + + .bss : { + *(.bss* .init.bss*) + _end = ALIGN(512); + . = _end; + } + + /DISCARD/ : { + *(__ksymtab_strings ___ksymtab+*) + } +} + +PROVIDE(__data_rawsize = ABSOLUTE(_edata - _etext)); +PROVIDE(__data_size = ABSOLUTE(_end - _etext)); + +PROVIDE(__efistub_memcpy = __pi_memcpy); +PROVIDE(__efistub_memset = __pi_memset); +PROVIDE(__efistub_strnlen = __pi_strnlen); From patchwork Mon May 2 11:17:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 569139 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E46D2C433F5 for ; Mon, 2 May 2022 11:17:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1384581AbiEBLU6 (ORCPT ); Mon, 2 May 2022 07:20:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34990 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381044AbiEBLU5 (ORCPT ); Mon, 2 May 2022 07:20:57 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6A00ABCB0; Mon, 2 May 2022 04:17:29 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 04F626128E; Mon, 2 May 2022 11:17:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B402EC385B2; Mon, 2 May 2022 11:17:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1651490248; bh=KdTG5ILW+BimV/rUokcRVUnKrnKVJkh0mRI8hwDxv9c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nY3YeUh8wq/b7ruMqOaCgr+Td8NbU3vfs7xE26erkktuhf80/mBaLpY+hFB1S/n1a moxQYIUGqIlPHq8GojuWdeb/EbyfandoaZzVRlhqNj3D0/gMB2o5bT40O9ooWkxAff 9isDKWAm2SJs8bOlppVHFII36BSTNyIGAktodVcydUTvMj7+rsGt1EG7n3dJRxbCI4 50L1yLmLXRIOp/isyK6Nf2BzD0bnXVNuKYbUUKLthwjPm8rZH08giIaKTHZI0qhEjw /sx622IM3TBihssx4RNtul9RKQpM65kH7IdprfeLDmwHtJd+2+aPDYhlnnStEbVMql XR9Tx+wFiu/hg== From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: catalin.marinas@arm.com, will@kernel.org, Ard Biesheuvel , Arnd Bergmann , Huacai Chen Subject: [RFC PATCH 4/4] arm64: efi: enable generic EFI compressed boot Date: Mon, 2 May 2022 13:17:10 +0200 Message-Id: <20220502111710.4093567-5-ardb@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220502111710.4093567-1-ardb@kernel.org> References: <20220502111710.4093567-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1967; h=from:subject; bh=KdTG5ILW+BimV/rUokcRVUnKrnKVJkh0mRI8hwDxv9c=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBib721YQFXgTQ9rqQ5/5YC4MqDvd8W4LTztnbWv0qD +YGJ/PaJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYm+9tQAKCRDDTyI5ktmPJK92DA Cmdai5hwUZeWh8eqa1ig9Jiloi7qFITUH0u7nxxbmrhJwnJmPgdZbQOaXbmEpPcOt77JaoihxwAbYU ee4zh+LH0b8crlPyZyMFFwNBR4RQy8jOl257Un58tUHGtvfa/zOPAWaXKI0xaoKJ2kXn7ZODrDaRIk C92VrPPu8EJKJ8jhd4ytCbKi2NECM9EIHMGkMEtC6cQAWYgsSIEIHIXkNagThjDkw5VESOUsO4KmTL MImvTIxzCloCXUaLt425tAwxS5lh6Du9BxgUnynu+r2mES5cYRyKhyRQcpkFE7xIc0t1yCwnV6gYUN kUwQ1zcyyBhd/1j4N36mYNv54zH5DRXj1bK2JHq8Od16LFoYj6k0KXk2xK9ZgMHgevcBdoo76mWt2k suAj+Ctz0MNBX9Nz0EcG2h3P5qEN/4wktE2jWF2TI/kFegCuicNU/S1nd7nZYCBvTXvL6/LFDmZQQb Fg1B+gNcUdX1awONYrDDSzR8NQ8/VYNi53yUems0BjFvE= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Wire up the generic EFI zboot support for arm64. Signed-off-by: Ard Biesheuvel --- arch/arm64/Makefile | 5 +++++ arch/arm64/boot/Makefile | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 2f1de88651e6..c9580f78439f 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -162,6 +162,11 @@ Image: vmlinux Image.%: Image $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +ifneq ($(CONFIG_EFI_ZBOOT),) +zImage.efi: Image + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +endif + install: install-image := Image zinstall: install-image := Image.gz install zinstall: diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile index ebe80faab883..81500267ab79 100644 --- a/arch/arm64/boot/Makefile +++ b/arch/arm64/boot/Makefile @@ -16,7 +16,7 @@ OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S -targets := Image Image.bz2 Image.gz Image.lz4 Image.lzma Image.lzo +targets := Image Image.bz2 Image.gz Image.lz4 Image.lzma Image.lzo zImage.efi $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) @@ -35,3 +35,18 @@ $(obj)/Image.lzma: $(obj)/Image FORCE $(obj)/Image.lzo: $(obj)/Image FORCE $(call if_changed,lzo) + +OBJCOPYFLAGS_Image.gz.o := -O elf64-littleaarch64 -I binary \ + --rename-section .data=.gzdata,load,alloc,readonly,contents +$(obj)/Image.gz.o: $(obj)/Image.gz FORCE + $(call if_changed,objcopy) + +ZBOOT_DEPS := memcpy.o memset.o strnlen.o +$(obj)/zImage.efi.elf: $(obj)/Image.gz.o $(addprefix $(objtree)/arch/arm64/lib/,$(ZBOOT_DEPS)) + $(Q)$(LD) -T $(srctree)/drivers/firmware/efi/libstub/zboot.lds \ + -o $@ $^ $(objtree)/drivers/firmware/efi/libstub/lib.a \ + --defsym=pe_machine_type=0xaa64 + +$(obj)/zImage.efi: OBJCOPYFLAGS := -O binary +$(obj)/zImage.efi: $(obj)/zImage.efi.elf FORCE + $(call if_changed,objcopy)