From nobody Wed Sep 17 22:39:31 2025 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 3006AC4332F for ; Thu, 15 Dec 2022 12:42:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230109AbiLOMl4 (ORCPT ); Thu, 15 Dec 2022 07:41:56 -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 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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/M= akefile 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 =20 vmlinux-objs-y :=3D $(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 =20 vmlinux-objs-$(CONFIG_EARLY_PRINTK) +=3D $(obj)/early_serial_console.o vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) +=3D $(obj)/kaslr.o diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/mis= c.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; =20 -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. */ =20 -static void scroll(void) -{ - int i; - - memmove(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2); - for (i =3D (lines - 1) * cols * 2; i < lines * cols * 2; i +=3D 2) - vidmem[i] =3D ' '; -} - -#define XMTRDY 0x20 - -#define TXR 0 /* Transmit register (WRITE) */ -#define LSR 5 /* Line Status */ -static void serial_putchar(int ch) -{ - unsigned timeout =3D 0xffff; - - while ((inb(early_serial_base + LSR) & XMTRDY) =3D=3D 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 =3D s; - while (*str) { - if (*str =3D=3D '\n') - serial_putchar('\r'); - serial_putchar(*str++); - } - } - - if (lines =3D=3D 0 || cols =3D=3D 0) - return; - - x =3D boot_params->screen_info.orig_x; - y =3D boot_params->screen_info.orig_y; - - while ((c =3D *s++) !=3D '\0') { - if (c =3D=3D '\n') { - x =3D 0; - if (++y >=3D lines) { - scroll(); - y--; - } - } else { - vidmem[(x + cols * y) * 2] =3D c; - if (++x >=3D cols) { - x =3D 0; - if (++y >=3D lines) { - scroll(); - y--; - } - } - } - } - - boot_params->screen_info.orig_x =3D x; - boot_params->screen_info.orig_y =3D y; - - pos =3D (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] =3D "0"; - int bits; - - for (bits =3D sizeof(value) * 8 - 4; bits >=3D 0; bits -=3D 4) { - unsigned long digit =3D (value >> bits) & 0xf; - - if (digit < 0xA) - alpha[0] =3D '0' + digit; - else - alpha[0] =3D '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, =20 sanitize_boot_params(boot_params); =20 - if (boot_params->screen_info.orig_video_mode =3D=3D 7) { - vidmem =3D (char *) 0xb0000; - vidport =3D 0x3b4; - } else { - vidmem =3D (char *) 0xb8000; - vidport =3D 0x3d4; - } - - lines =3D boot_params->screen_info.orig_video_lines; - cols =3D boot_params->screen_info.orig_video_cols; - init_default_io_ops(); =20 /* @@ -427,7 +320,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, = memptr heap, */ early_tdx_detect(); =20 - console_init(); + init_bare_console(); =20 /* * 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/mis= c.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) =20 @@ -128,6 +128,11 @@ static inline void console_init(void) { } #endif =20 +/* 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/p= utstr.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 =3D putstr_; + __puthex =3D puthex_; +} + +void init_bare_console(void) +{ + init_console_func(putstr, puthex); + + if (boot_params->screen_info.orig_video_mode =3D=3D 7) { + vidmem =3D (char *) 0xb0000; + vidport =3D 0x3b4; + } else { + vidmem =3D (char *) 0xb8000; + vidport =3D 0x3d4; + } + + lines =3D boot_params->screen_info.orig_video_lines; + cols =3D 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 =3D (lines - 1) * cols * 2; i < lines * cols * 2; i +=3D 2) + vidmem[i] =3D ' '; +} + +#define XMTRDY 0x20 + +#define TXR 0 /* Transmit register (WRITE) */ +#define LSR 5 /* Line Status */ + +static void serial_putchar(int ch) +{ + unsigned int timeout =3D 0xffff; + + while ((inb(early_serial_base + LSR) & XMTRDY) =3D=3D 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 =3D s; + + while (*str) { + if (*str =3D=3D '\n') + serial_putchar('\r'); + serial_putchar(*str++); + } + } + + if (lines =3D=3D 0 || cols =3D=3D 0) + return; + + x =3D boot_params->screen_info.orig_x; + y =3D boot_params->screen_info.orig_y; + + while ((c =3D *s++) !=3D '\0') { + if (c =3D=3D '\n') { + x =3D 0; + if (++y >=3D lines) { + scroll(); + y--; + } + } else { + vidmem[(x + cols * y) * 2] =3D c; + if (++x >=3D cols) { + x =3D 0; + if (++y >=3D lines) { + scroll(); + y--; + } + } + } + } + + boot_params->screen_info.orig_x =3D x; + boot_params->screen_info.orig_y =3D y; + + pos =3D (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] =3D "0"; + int bits; + + for (bits =3D sizeof(value) * 8 - 4; bits >=3D 0; bits -=3D 4) { + unsigned long digit =3D (value >> bits) & 0xf; + + if (digit < 0xA) + alpha[0] =3D '0' + digit; + else + alpha[0] =3D 'a' + (digit - 0xA); + + putstr(alpha); + } +} --=20 2.37.4