From patchwork Thu Dec 15 12:38:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Evgeniy Baskov X-Patchwork-Id: 33628 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:e747:0:0:0:0:0 with SMTP id c7csp327802wrn; Thu, 15 Dec 2022 04:43:35 -0800 (PST) X-Google-Smtp-Source: AA0mqf7ZY8cQgVdTSFF3RlOoxATb+auqHQ5ZENu7cVKER49mb/LXVU/Ldjk1HQ6EZYKj5OpwR++H X-Received: by 2002:a17:906:3917:b0:7bf:1081:9472 with SMTP id f23-20020a170906391700b007bf10819472mr22187615eje.69.1671108215569; Thu, 15 Dec 2022 04:43:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671108215; cv=none; d=google.com; s=arc-20160816; b=lW5hrNxfkEepMo23qGdvUPeeY+sT7oW3ZTa8YmMObtYhtD2J9Ek0GRrlYQ3mZ2Y2z4 luKOcUWh40Gv1p50NRJ1m9wnNFvfXnlRUIqm42IKMuxCQR4hf1g999Vhwtoy7wLvQPMk RqSr+2RxlXWP9b9hNQZAdPCpsGDLMgNHWZhczNtIHXSLXB0vqExMTDfsp5oqa7qU8gRh x5uHBYIsO/tgWEQ13UjZkagLdQNFmmH5he5ZnaEG0EPaDp3tbszVYpz0YZImPu1bblY8 6fcs0qwTPtVQ47YFQyVcyyU0hUK5hAH/y47x0A6OSo4kZrhfeAwuzXObKcQwO++/dt77 sEnQ== 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 :dkim-signature:dkim-filter; bh=SXfOuN4XhQqZecp0fAbo/2/1GUdhrCJYeFoo3/yqXus=; b=f2uPjlwRJJHa5RTJVt+UKL7JK3TkzykftK7wQGKDvDGaGx65AU+KFoeMgqTb7cjIA+ eAMqaPuEF3WnVrtcLM5OUAem7ZDw3VJK8mnHtY8cVkgtUy4lqzO+zSA5HZNLDLV+zhCE HQbXBnUUMI8qDLDM7TQz7q2FM2J3yjvno1jHdwxPC1FK8Iz+rNYgaQo1OfnYqZGSqTb4 jO9AD4ae9pOuEgPvfBMeso7oNd62UFuiGqEkrsPl8DFn8j/5T310x1p5D+2R5yCjjsPM yQ/ExcRAylXaqiJyuCNSv/TlO3TLms6m6ZgztqNRTw1p6t7ukEtOs+inSfy4MD1ZyBAE 8GXg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ispras.ru header.s=default header.b="g1V5BjU/"; 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=pass (p=NONE sp=NONE dis=NONE) header.from=ispras.ru Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id dn12-20020a17090794cc00b007ac60b82ea5si15772013ejc.96.2022.12.15.04.43.11; Thu, 15 Dec 2022 04:43:35 -0800 (PST) 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; dkim=pass header.i=@ispras.ru header.s=default header.b="g1V5BjU/"; 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=pass (p=NONE sp=NONE dis=NONE) header.from=ispras.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230099AbiLOMlz (ORCPT + 99 others); Thu, 15 Dec 2022 07:41:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54882 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229869AbiLOMl0 (ORCPT ); Thu, 15 Dec 2022 07:41:26 -0500 Received: from mail.ispras.ru (mail.ispras.ru [83.149.199.84]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9CBC12F013; Thu, 15 Dec 2022 04:40:25 -0800 (PST) Received: from localhost.localdomain (unknown [83.149.199.65]) by mail.ispras.ru (Postfix) with ESMTPSA id 9F25340737B6; Thu, 15 Dec 2022 12:40:23 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.ispras.ru 9F25340737B6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ispras.ru; s=default; t=1671108023; bh=SXfOuN4XhQqZecp0fAbo/2/1GUdhrCJYeFoo3/yqXus=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=g1V5BjU/RdhYXl0WPUCtk9+RvlC1h2yphrk3zLRjpreEEROQoyPuVupJC/D9WZ1OC k7aTmzCBfhDlAUXNZ7V3TbQnS1j3y902gW6/BuG0Y9jief23Yx0syXPQshh4mdK/wg q3Tn84RUxuckMAEKiwneBYNVvtjh3KMmzZoDN9R8= From: Evgeniy Baskov To: Ard Biesheuvel Cc: Evgeniy Baskov , Borislav Petkov , Andy Lutomirski , Dave Hansen , Ingo Molnar , Peter Zijlstra , Thomas Gleixner , Alexey Khoroshilov , Peter Jones , "Limonciello, Mario" , joeyli , lvc-project@linuxtesting.org, x86@kernel.org, linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v4 11/26] x86/boot: Make console interface more abstract Date: Thu, 15 Dec 2022 15:38:02 +0300 Message-Id: <3827032b3688e111428a9e727782d2b2712c7e34.1671098103.git.baskov@ispras.ru> X-Mailer: git-send-email 2.37.4 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS 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 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1752283968175833889?= X-GMAIL-MSGID: =?utf-8?q?1752283968175833889?= To be able to extract kernel from EFI, console output functions need to be replaceable by alternative implementations. Make all of those functions pointers. Move serial console code to separate file. Tested-by: Mario Limonciello Tested-by: Peter Jones Signed-off-by: Evgeniy Baskov --- arch/x86/boot/compressed/Makefile | 2 +- arch/x86/boot/compressed/misc.c | 109 +------------------------ arch/x86/boot/compressed/misc.h | 9 ++- arch/x86/boot/compressed/putstr.c | 130 ++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 111 deletions(-) create mode 100644 arch/x86/boot/compressed/putstr.c diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 4dcab38f5a38..4b1524446875 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -93,7 +93,7 @@ $(obj)/misc.o: $(obj)/../voffset.h vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/kernel_info.o $(obj)/head_$(BITS).o \ $(obj)/misc.o $(obj)/string.o $(obj)/cmdline.o $(obj)/error.o \ - $(obj)/piggy.o $(obj)/cpuflags.o + $(obj)/piggy.o $(obj)/cpuflags.o $(obj)/putstr.o vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 0c7ec290044d..aa4a22bc9cf9 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -53,13 +53,6 @@ struct port_io_ops pio_ops; memptr free_mem_ptr; memptr free_mem_end_ptr; -static char *vidmem; -static int vidport; - -/* These might be accessed before .bss is cleared, so use .data instead. */ -static int lines __section(".data"); -static int cols __section(".data"); - #ifdef CONFIG_KERNEL_GZIP #include "../../../../lib/decompress_inflate.c" #endif @@ -92,95 +85,6 @@ static int cols __section(".data"); * ../header.S. */ -static void scroll(void) -{ - int i; - - memmove(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2); - for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2) - vidmem[i] = ' '; -} - -#define XMTRDY 0x20 - -#define TXR 0 /* Transmit register (WRITE) */ -#define LSR 5 /* Line Status */ -static void serial_putchar(int ch) -{ - unsigned timeout = 0xffff; - - while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) - cpu_relax(); - - outb(ch, early_serial_base + TXR); -} - -void __putstr(const char *s) -{ - int x, y, pos; - char c; - - if (early_serial_base) { - const char *str = s; - while (*str) { - if (*str == '\n') - serial_putchar('\r'); - serial_putchar(*str++); - } - } - - if (lines == 0 || cols == 0) - return; - - x = boot_params->screen_info.orig_x; - y = boot_params->screen_info.orig_y; - - while ((c = *s++) != '\0') { - if (c == '\n') { - x = 0; - if (++y >= lines) { - scroll(); - y--; - } - } else { - vidmem[(x + cols * y) * 2] = c; - if (++x >= cols) { - x = 0; - if (++y >= lines) { - scroll(); - y--; - } - } - } - } - - boot_params->screen_info.orig_x = x; - boot_params->screen_info.orig_y = y; - - pos = (x + cols * y) * 2; /* Update cursor position */ - outb(14, vidport); - outb(0xff & (pos >> 9), vidport+1); - outb(15, vidport); - outb(0xff & (pos >> 1), vidport+1); -} - -void __puthex(unsigned long value) -{ - char alpha[2] = "0"; - int bits; - - for (bits = sizeof(value) * 8 - 4; bits >= 0; bits -= 4) { - unsigned long digit = (value >> bits) & 0xf; - - if (digit < 0xA) - alpha[0] = '0' + digit; - else - alpha[0] = 'a' + (digit - 0xA); - - __putstr(alpha); - } -} - #ifdef CONFIG_X86_NEED_RELOCS static void handle_relocations(void *output, unsigned long output_len, unsigned long virt_addr) @@ -406,17 +310,6 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, sanitize_boot_params(boot_params); - if (boot_params->screen_info.orig_video_mode == 7) { - vidmem = (char *) 0xb0000; - vidport = 0x3b4; - } else { - vidmem = (char *) 0xb8000; - vidport = 0x3d4; - } - - lines = boot_params->screen_info.orig_video_lines; - cols = boot_params->screen_info.orig_video_cols; - init_default_io_ops(); /* @@ -427,7 +320,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, */ early_tdx_detect(); - console_init(); + init_bare_console(); /* * Save RSDP address for later use. Have this after console_init() diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 033db9b536e6..38d31bec062d 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -57,8 +57,8 @@ extern memptr free_mem_end_ptr; void *malloc(int size); void free(void *where); extern struct boot_params *boot_params; -void __putstr(const char *s); -void __puthex(unsigned long value); +extern void (*__putstr)(const char *s); +extern void (*__puthex)(unsigned long value); #define error_putstr(__x) __putstr(__x) #define error_puthex(__x) __puthex(__x) @@ -128,6 +128,11 @@ static inline void console_init(void) { } #endif +/* putstr.c */ +void init_bare_console(void); +void init_console_func(void (*putstr_)(const char *), + void (*puthex_)(unsigned long)); + #ifdef CONFIG_AMD_MEM_ENCRYPT void sev_enable(struct boot_params *bp); void sev_es_shutdown_ghcb(void); diff --git a/arch/x86/boot/compressed/putstr.c b/arch/x86/boot/compressed/putstr.c new file mode 100644 index 000000000000..44a4c3dacec5 --- /dev/null +++ b/arch/x86/boot/compressed/putstr.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "misc.h" + +/* These might be accessed before .bss is cleared, so use .data instead. */ +static char *vidmem __section(".data"); +static int vidport __section(".data"); +static int lines __section(".data"); +static int cols __section(".data"); + +void (*__putstr)(const char *s); +void (*__puthex)(unsigned long value); + +static void putstr(const char *s); +static void puthex(unsigned long value); + +void init_console_func(void (*putstr_)(const char *), + void (*puthex_)(unsigned long)) +{ + __putstr = putstr_; + __puthex = puthex_; +} + +void init_bare_console(void) +{ + init_console_func(putstr, puthex); + + if (boot_params->screen_info.orig_video_mode == 7) { + vidmem = (char *) 0xb0000; + vidport = 0x3b4; + } else { + vidmem = (char *) 0xb8000; + vidport = 0x3d4; + } + + lines = boot_params->screen_info.orig_video_lines; + cols = boot_params->screen_info.orig_video_cols; + + console_init(); +} + +static void scroll(void) +{ + int i; + + memmove(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2); + for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2) + vidmem[i] = ' '; +} + +#define XMTRDY 0x20 + +#define TXR 0 /* Transmit register (WRITE) */ +#define LSR 5 /* Line Status */ + +static void serial_putchar(int ch) +{ + unsigned int timeout = 0xffff; + + while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) + cpu_relax(); + + outb(ch, early_serial_base + TXR); +} + +static void putstr(const char *s) +{ + int x, y, pos; + char c; + + if (early_serial_base) { + const char *str = s; + + while (*str) { + if (*str == '\n') + serial_putchar('\r'); + serial_putchar(*str++); + } + } + + if (lines == 0 || cols == 0) + return; + + x = boot_params->screen_info.orig_x; + y = boot_params->screen_info.orig_y; + + while ((c = *s++) != '\0') { + if (c == '\n') { + x = 0; + if (++y >= lines) { + scroll(); + y--; + } + } else { + vidmem[(x + cols * y) * 2] = c; + if (++x >= cols) { + x = 0; + if (++y >= lines) { + scroll(); + y--; + } + } + } + } + + boot_params->screen_info.orig_x = x; + boot_params->screen_info.orig_y = y; + + pos = (x + cols * y) * 2; /* Update cursor position */ + outb(14, vidport); + outb(0xff & (pos >> 9), vidport+1); + outb(15, vidport); + outb(0xff & (pos >> 1), vidport+1); +} + +static void puthex(unsigned long value) +{ + char alpha[2] = "0"; + int bits; + + for (bits = sizeof(value) * 8 - 4; bits >= 0; bits -= 4) { + unsigned long digit = (value >> bits) & 0xf; + + if (digit < 0xA) + alpha[0] = '0' + digit; + else + alpha[0] = 'a' + (digit - 0xA); + + putstr(alpha); + } +}