linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver
@ 2022-08-06 16:32 Markuss Broks
  2022-08-06 16:32 ` [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name Markuss Broks
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Markuss Broks @ 2022-08-06 16:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: ~postmarketos/upstreaming, phone-devel, Markuss Broks,
	Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman, Jiri Slaby,
	Helge Deller, Paul E. McKenney, Borislav Petkov, Kees Cook,
	Andrew Morton, Randy Dunlap, Damien Le Moal, Thomas Zimmermann,
	Michal Suchanek, Javier Martinez Canillas, Arnd Bergmann,
	Maarten Lankhorst, Wei Ming Chen, Bartlomiej Zolnierkiewicz,
	Tony Lindgren, linux-doc, linux-efi, linux-serial, linux-fbdev,
	dri-devel

Make the EFI earlycon driver be suitable for any linear framebuffers.
This should be helpful for early porting of boards with no other means of
output, like smartphones/tablets. There seems to be an issue with early_ioremap
function on ARM32, but I am unable to find the exact cause. It appears the mappings
returned by it are somehow incorrect, thus the driver is disabled on ARM. EFI early
console was disabled on IA64 previously because of missing early_memremap_prot,
and this is inherited to this driver.

This patch also changes behavior on EFI systems, by selecting the mapping type
based on if the framebuffer region intersects with system RAM. If it does, it's
common sense that it should be in RAM as a whole, and so the system RAM mapping is
used. It was tested to be working on my PC (Intel Z490 platform), as well as several
ARM64 boards (Samsung Galaxy S9 (Exynos), iPad Air 2, Xiaomi Mi Pad 4, ...).

Markuss Broks (2):
  drivers: serial: earlycon: Pass device-tree node
  efi: earlycon: Add support for generic framebuffers and move to fbdev
    subsystem


v1 -> v2:

- a new patch correcting serial/earlycon.c argument name to "offset" instead
  of "node"
- move IA64 exclusion from EFI earlycon Kconfig to earlycon driver Kconfig
  (IA64 has no early_memremap_prot)
- move driver from fbdev to console subsystem
- select EFI earlycon by default
- fetch stride manually from device-tree, as on some devices it seems stride
  doesn't match the horizontal resolution * bpp.
- use saner format (e.g. 1920x1080x32 instead of 1920,1080,32).

 .../admin-guide/kernel-parameters.txt         |  12 +-
 MAINTAINERS                                   |   5 +
 drivers/firmware/efi/Kconfig                  |   6 +-
 drivers/firmware/efi/Makefile                 |   1 -
 drivers/firmware/efi/earlycon.c               | 246 --------------
 drivers/tty/serial/earlycon.c                 |   3 +
 drivers/video/fbdev/Kconfig                   |  11 +
 drivers/video/fbdev/Makefile                  |   1 +
 drivers/video/fbdev/earlycon.c                | 301 ++++++++++++++++++
 include/linux/serial_core.h                   |   1 +
 10 files changed, 331 insertions(+), 256 deletions(-)
 delete mode 100644 drivers/firmware/efi/earlycon.c
 create mode 100644 drivers/video/fbdev/earlycon.c

-- 
2.37.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name
  2022-08-06 16:32 [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Markuss Broks
@ 2022-08-06 16:32 ` Markuss Broks
  2022-08-06 16:56   ` Andy Shevchenko
                     ` (2 more replies)
  2022-08-06 16:32 ` [PATCH v2 2/3] drivers: serial: earlycon: Pass device-tree node Markuss Broks
                   ` (2 subsequent siblings)
  3 siblings, 3 replies; 15+ messages in thread
From: Markuss Broks @ 2022-08-06 16:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: ~postmarketos/upstreaming, phone-devel, Markuss Broks,
	Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman, Jiri Slaby,
	Helge Deller, Paul E. McKenney, Borislav Petkov, Kees Cook,
	Andrew Morton, Randy Dunlap, Damien Le Moal, Thomas Zimmermann,
	Michal Suchanek, Javier Martinez Canillas, Arnd Bergmann,
	Maarten Lankhorst, Wei Ming Chen, Bartlomiej Zolnierkiewicz,
	Tony Lindgren, linux-doc, linux-efi, linux-serial, linux-fbdev,
	dri-devel, Rob Herring

The "node" argument is actually an offset, and it's also
an "int", and not "unsigned long". Correct the of_setup_earlycon
function.

Signed-off-by: Markuss Broks <markuss.broks@gmail.com>
---
 drivers/tty/serial/earlycon.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 57c70851f22a0e78805f34d1a7700708104b6f6a..bc210ae8173d97d5ef422468acf2755a853cb943 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -244,7 +244,7 @@ early_param("earlycon", param_setup_earlycon);
 #ifdef CONFIG_OF_EARLY_FLATTREE
 
 int __init of_setup_earlycon(const struct earlycon_id *match,
-			     unsigned long node,
+			     int offset,
 			     const char *options)
 {
 	int err;
@@ -255,25 +255,25 @@ int __init of_setup_earlycon(const struct earlycon_id *match,
 
 	spin_lock_init(&port->lock);
 	port->iotype = UPIO_MEM;
-	addr = of_flat_dt_translate_address(node);
+	addr = of_flat_dt_translate_address(offset);
 	if (addr == OF_BAD_ADDR) {
 		pr_warn("[%s] bad address\n", match->name);
 		return -ENXIO;
 	}
 	port->mapbase = addr;
 
-	val = of_get_flat_dt_prop(node, "reg-offset", NULL);
+	val = of_get_flat_dt_prop(offset, "reg-offset", NULL);
 	if (val)
 		port->mapbase += be32_to_cpu(*val);
 	port->membase = earlycon_map(port->mapbase, SZ_4K);
 
-	val = of_get_flat_dt_prop(node, "reg-shift", NULL);
+	val = of_get_flat_dt_prop(offset, "reg-shift", NULL);
 	if (val)
 		port->regshift = be32_to_cpu(*val);
-	big_endian = of_get_flat_dt_prop(node, "big-endian", NULL) != NULL ||
+	big_endian = of_get_flat_dt_prop(offset, "big-endian", NULL) != NULL ||
 		(IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
-		 of_get_flat_dt_prop(node, "native-endian", NULL) != NULL);
-	val = of_get_flat_dt_prop(node, "reg-io-width", NULL);
+		 of_get_flat_dt_prop(offset, "native-endian", NULL) != NULL);
+	val = of_get_flat_dt_prop(offset, "reg-io-width", NULL);
 	if (val) {
 		switch (be32_to_cpu(*val)) {
 		case 1:
@@ -291,11 +291,11 @@ int __init of_setup_earlycon(const struct earlycon_id *match,
 		}
 	}
 
-	val = of_get_flat_dt_prop(node, "current-speed", NULL);
+	val = of_get_flat_dt_prop(offset, "current-speed", NULL);
 	if (val)
 		early_console_dev.baud = be32_to_cpu(*val);
 
-	val = of_get_flat_dt_prop(node, "clock-frequency", NULL);
+	val = of_get_flat_dt_prop(offset, "clock-frequency", NULL);
 	if (val)
 		port->uartclk = be32_to_cpu(*val);
 
-- 
2.37.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 2/3] drivers: serial: earlycon: Pass device-tree node
  2022-08-06 16:32 [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Markuss Broks
  2022-08-06 16:32 ` [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name Markuss Broks
@ 2022-08-06 16:32 ` Markuss Broks
  2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
  2022-09-06 16:54 ` [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Ard Biesheuvel
  3 siblings, 0 replies; 15+ messages in thread
From: Markuss Broks @ 2022-08-06 16:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: ~postmarketos/upstreaming, phone-devel, Markuss Broks,
	Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman, Jiri Slaby,
	Helge Deller, Paul E. McKenney, Borislav Petkov, Kees Cook,
	Andrew Morton, Randy Dunlap, Damien Le Moal, Thomas Zimmermann,
	Michal Suchanek, Javier Martinez Canillas, Arnd Bergmann,
	Maarten Lankhorst, Wei Ming Chen, Bartlomiej Zolnierkiewicz,
	Tony Lindgren, linux-doc, linux-efi, linux-serial, linux-fbdev,
	dri-devel

Pass a pointer to device-tree node in case the driver probed from
OF. This makes early console drivers able to fetch options from
device-tree node properties.

Signed-off-by: Markuss Broks <markuss.broks@gmail.com>
---
 drivers/tty/serial/earlycon.c | 3 +++
 include/linux/serial_core.h   | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index bc210ae8173d97d5ef422468acf2755a853cb943..be2f01520f6608f6ece725dd83d2526e30477b47 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -304,6 +304,9 @@ int __init of_setup_earlycon(const struct earlycon_id *match,
 		strlcpy(early_console_dev.options, options,
 			sizeof(early_console_dev.options));
 	}
+
+	early_console_dev.offset = offset;
+
 	earlycon_init(&early_console_dev, match->name);
 	err = match->setup(&early_console_dev, options);
 	earlycon_print_info(&early_console_dev);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index cbd5070bc87f42aa450c4ca7af8a9b59fbe88574..e65b9aba4e5fdaedb560d2cbbf326a11cfecbcac 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -349,6 +349,7 @@ struct earlycon_device {
 	struct uart_port port;
 	char options[16];		/* e.g., 115200n8 */
 	unsigned int baud;
+	int offset;
 };
 
 struct earlycon_id {
-- 
2.37.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-08-06 16:32 [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Markuss Broks
  2022-08-06 16:32 ` [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name Markuss Broks
  2022-08-06 16:32 ` [PATCH v2 2/3] drivers: serial: earlycon: Pass device-tree node Markuss Broks
@ 2022-08-06 16:32 ` Markuss Broks
  2022-08-06 21:37   ` Andy Shevchenko
                     ` (4 more replies)
  2022-09-06 16:54 ` [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Ard Biesheuvel
  3 siblings, 5 replies; 15+ messages in thread
From: Markuss Broks @ 2022-08-06 16:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: ~postmarketos/upstreaming, phone-devel, Markuss Broks,
	Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman, Jiri Slaby,
	Helge Deller, Paul E. McKenney, Borislav Petkov, Kees Cook,
	Andrew Morton, Randy Dunlap, Damien Le Moal, Thomas Zimmermann,
	Michal Suchanek, Javier Martinez Canillas, Arnd Bergmann,
	Maarten Lankhorst, Wei Ming Chen, Bartlomiej Zolnierkiewicz,
	Tony Lindgren, linux-doc, linux-efi, linux-serial, linux-fbdev,
	dri-devel

Add early console support for generic linear framebuffer devices.
This driver supports probing from cmdline early parameters
or from the device-tree using information in simple-framebuffer node.
The EFI functionality should be retained in whole.
The driver was disabled on ARM because of a bug in early_ioremap
implementation on ARM and on IA64 because of lack of early_memremap_prot.

Signed-off-by: Markuss Broks <markuss.broks@gmail.com>
---
 .../admin-guide/kernel-parameters.txt         |  12 +-
 MAINTAINERS                                   |   5 +
 drivers/firmware/efi/Kconfig                  |   7 +-
 drivers/firmware/efi/Makefile                 |   1 -
 drivers/firmware/efi/earlycon.c               | 246 --------------
 drivers/video/console/Kconfig                 |  11 +
 drivers/video/console/Makefile                |   1 +
 drivers/video/console/earlycon.c              | 305 ++++++++++++++++++
 8 files changed, 332 insertions(+), 256 deletions(-)
 delete mode 100644 drivers/firmware/efi/earlycon.c
 create mode 100644 drivers/video/console/earlycon.c

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 8090130b544b0701237a7b657a29c83c000a60f4..bccb1ac8978eb5cf7e2bb20834b1881b27040666 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1281,12 +1281,9 @@
 			specified address. The serial port must already be
 			setup and configured. Options are not yet supported.
 
-		efifb,[options]
+		efifb
 			Start an early, unaccelerated console on the EFI
-			memory mapped framebuffer (if available). On cache
-			coherent non-x86 systems that use system memory for
-			the framebuffer, pass the 'ram' option so that it is
-			mapped with the correct attributes.
+			memory mapped framebuffer (if available).
 
 		linflex,<addr>
 			Use early console provided by Freescale LINFlexD UART
@@ -1294,6 +1291,11 @@
 			address must be provided, and the serial port must
 			already be setup and configured.
 
+		simplefb,<addr>,<width>x<height>x<bpp>
+			Use early console with simple framebuffer that is
+			pre-initialized by firmware. A valid base address,
+			width, height and pixel size must be provided.
+
 	earlyprintk=	[X86,SH,ARM,M68k,S390]
 			earlyprintk=vga
 			earlyprintk=sclp
diff --git a/MAINTAINERS b/MAINTAINERS
index 1fc9ead83d2aa3e60ccc4cfa8ee16df09ef579bf..af8b8e289483b6a264d477145061bd0e0ba34a25 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7033,6 +7033,11 @@ Q:	http://patchwork.linuxtv.org/project/linux-media/list/
 T:	git git://linuxtv.org/anttip/media_tree.git
 F:	drivers/media/tuners/e4000*
 
+EARLY CONSOLE FRAMEBUFFER DRIVER
+M:	Markuss Broks <markuss.broks@gmail.com>
+S:	Maintained
+F:	drivers/video/console/earlycon.c
+
 EARTH_PT1 MEDIA DRIVER
 M:	Akihiro Tsukada <tskd08@gmail.com>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 7aa4717cdcac46f91dd202f868c463388eb02735..ea76ccfb9bcd8ba44ddca06052eaa442ed6c30f7 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -259,10 +259,9 @@ config EFI_DISABLE_PCI_DMA
 	  may be used to override this option.
 
 config EFI_EARLYCON
-	def_bool y
-	depends on SERIAL_EARLYCON && !ARM && !IA64
-	select FONT_SUPPORT
-	select ARCH_USE_MEMREMAP_PROT
+	bool "EFI early console support"
+	select FB_EARLYCON
+	default y
 
 config EFI_CUSTOM_SSDT_OVERLAYS
 	bool "Load custom ACPI SSDT overlay from an EFI variable"
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index c02ff25dd47707090a2ab86ee4f330e467f878f5..64eea61fbb43d76ec2d5416d467dfbb9aa21bda0 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -44,6 +44,5 @@ obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
 riscv-obj-$(CONFIG_EFI)			:= efi-init.o riscv-runtime.o
 obj-$(CONFIG_RISCV)			+= $(riscv-obj-y)
 obj-$(CONFIG_EFI_CAPSULE_LOADER)	+= capsule-loader.o
-obj-$(CONFIG_EFI_EARLYCON)		+= earlycon.o
 obj-$(CONFIG_UEFI_CPER_ARM)		+= cper-arm.o
 obj-$(CONFIG_UEFI_CPER_X86)		+= cper-x86.o
diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c
deleted file mode 100644
index a52236e11e5f73ddea5bb1f42ca2ca7c42425dab..0000000000000000000000000000000000000000
--- a/drivers/firmware/efi/earlycon.c
+++ /dev/null
@@ -1,246 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2013 Intel Corporation; author Matt Fleming
- */
-
-#include <linux/console.h>
-#include <linux/efi.h>
-#include <linux/font.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/serial_core.h>
-#include <linux/screen_info.h>
-
-#include <asm/early_ioremap.h>
-
-static const struct console *earlycon_console __initdata;
-static const struct font_desc *font;
-static u32 efi_x, efi_y;
-static u64 fb_base;
-static bool fb_wb;
-static void *efi_fb;
-
-/*
- * EFI earlycon needs to use early_memremap() to map the framebuffer.
- * But early_memremap() is not usable for 'earlycon=efifb keep_bootcon',
- * memremap() should be used instead. memremap() will be available after
- * paging_init() which is earlier than initcall callbacks. Thus adding this
- * early initcall function early_efi_map_fb() to map the whole EFI framebuffer.
- */
-static int __init efi_earlycon_remap_fb(void)
-{
-	/* bail if there is no bootconsole or it has been disabled already */
-	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
-		return 0;
-
-	efi_fb = memremap(fb_base, screen_info.lfb_size,
-			  fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
-
-	return efi_fb ? 0 : -ENOMEM;
-}
-early_initcall(efi_earlycon_remap_fb);
-
-static int __init efi_earlycon_unmap_fb(void)
-{
-	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
-	if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
-		memunmap(efi_fb);
-	return 0;
-}
-late_initcall(efi_earlycon_unmap_fb);
-
-static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
-{
-	pgprot_t fb_prot;
-
-	if (efi_fb)
-		return efi_fb + start;
-
-	fb_prot = fb_wb ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL);
-	return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
-}
-
-static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
-{
-	if (efi_fb)
-		return;
-
-	early_memunmap(addr, len);
-}
-
-static void efi_earlycon_clear_scanline(unsigned int y)
-{
-	unsigned long *dst;
-	u16 len;
-
-	len = screen_info.lfb_linelength;
-	dst = efi_earlycon_map(y*len, len);
-	if (!dst)
-		return;
-
-	memset(dst, 0, len);
-	efi_earlycon_unmap(dst, len);
-}
-
-static void efi_earlycon_scroll_up(void)
-{
-	unsigned long *dst, *src;
-	u16 len;
-	u32 i, height;
-
-	len = screen_info.lfb_linelength;
-	height = screen_info.lfb_height;
-
-	for (i = 0; i < height - font->height; i++) {
-		dst = efi_earlycon_map(i*len, len);
-		if (!dst)
-			return;
-
-		src = efi_earlycon_map((i + font->height) * len, len);
-		if (!src) {
-			efi_earlycon_unmap(dst, len);
-			return;
-		}
-
-		memmove(dst, src, len);
-
-		efi_earlycon_unmap(src, len);
-		efi_earlycon_unmap(dst, len);
-	}
-}
-
-static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h)
-{
-	const u32 color_black = 0x00000000;
-	const u32 color_white = 0x00ffffff;
-	const u8 *src;
-	int m, n, bytes;
-	u8 x;
-
-	bytes = BITS_TO_BYTES(font->width);
-	src = font->data + c * font->height * bytes + h * bytes;
-
-	for (m = 0; m < font->width; m++) {
-		n = m % 8;
-		x = *(src + m / 8);
-		if ((x >> (7 - n)) & 1)
-			*dst = color_white;
-		else
-			*dst = color_black;
-		dst++;
-	}
-}
-
-static void
-efi_earlycon_write(struct console *con, const char *str, unsigned int num)
-{
-	struct screen_info *si;
-	unsigned int len;
-	const char *s;
-	void *dst;
-
-	si = &screen_info;
-	len = si->lfb_linelength;
-
-	while (num) {
-		unsigned int linemax;
-		unsigned int h, count = 0;
-
-		for (s = str; *s && *s != '\n'; s++) {
-			if (count == num)
-				break;
-			count++;
-		}
-
-		linemax = (si->lfb_width - efi_x) / font->width;
-		if (count > linemax)
-			count = linemax;
-
-		for (h = 0; h < font->height; h++) {
-			unsigned int n, x;
-
-			dst = efi_earlycon_map((efi_y + h) * len, len);
-			if (!dst)
-				return;
-
-			s = str;
-			n = count;
-			x = efi_x;
-
-			while (n-- > 0) {
-				efi_earlycon_write_char(dst + x*4, *s, h);
-				x += font->width;
-				s++;
-			}
-
-			efi_earlycon_unmap(dst, len);
-		}
-
-		num -= count;
-		efi_x += count * font->width;
-		str += count;
-
-		if (num > 0 && *s == '\n') {
-			efi_x = 0;
-			efi_y += font->height;
-			str++;
-			num--;
-		}
-
-		if (efi_x + font->width > si->lfb_width) {
-			efi_x = 0;
-			efi_y += font->height;
-		}
-
-		if (efi_y + font->height > si->lfb_height) {
-			u32 i;
-
-			efi_y -= font->height;
-			efi_earlycon_scroll_up();
-
-			for (i = 0; i < font->height; i++)
-				efi_earlycon_clear_scanline(efi_y + i);
-		}
-	}
-}
-
-static int __init efi_earlycon_setup(struct earlycon_device *device,
-				     const char *opt)
-{
-	struct screen_info *si;
-	u16 xres, yres;
-	u32 i;
-
-	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
-		return -ENODEV;
-
-	fb_base = screen_info.lfb_base;
-	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
-		fb_base |= (u64)screen_info.ext_lfb_base << 32;
-
-	fb_wb = opt && !strcmp(opt, "ram");
-
-	si = &screen_info;
-	xres = si->lfb_width;
-	yres = si->lfb_height;
-
-	/*
-	 * efi_earlycon_write_char() implicitly assumes a framebuffer with
-	 * 32 bits per pixel.
-	 */
-	if (si->lfb_depth != 32)
-		return -ENODEV;
-
-	font = get_default_font(xres, yres, -1, -1);
-	if (!font)
-		return -ENODEV;
-
-	efi_y = rounddown(yres, font->height) - font->height;
-	for (i = 0; i < (yres - efi_y) / font->height; i++)
-		efi_earlycon_scroll_up();
-
-	device->con->write = efi_earlycon_write;
-	earlycon_console = device->con;
-	return 0;
-}
-EARLYCON_DECLARE(efifb, efi_earlycon_setup);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 40c50fa2dd70c33a1549141b15e6cba721352d2d..8052507e058fce37f5a51058e58ae2eb10d9669a 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -69,6 +69,17 @@ config DUMMY_CONSOLE_ROWS
 	  monitor.
 	  Select 25 if you use a 640x480 resolution by default.
 
+config FB_EARLYCON
+	bool "Generic framebuffer early console"
+	depends on SERIAL_EARLYCON && !ARM && !IA64
+	select FONT_SUPPORT
+	select ARCH_USE_MEMREMAP_PROT
+	help
+	  Say Y here if you want early console support for firmware established
+	  linear framebuffer. Unless you are using EFI framebuffer, you need to
+	  specify framebuffer geometry and address in device-tree or in kernel
+	  command line.
+
 config FRAMEBUFFER_CONSOLE
 	bool "Framebuffer Console support"
 	depends on FB && !UML
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index db07b784bd2ccdcbffde933926ed5cee2bbbc7d4..7818faee587fc9c40b429617cfa224c0ccbc557c 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_STI_CONSOLE)         += sticon.o sticore.o
 obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
 obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
 
+obj-$(CONFIG_FB_EARLYCON)         += earlycon.o
 obj-$(CONFIG_FB_STI)              += sticore.o
diff --git a/drivers/video/console/earlycon.c b/drivers/video/console/earlycon.c
new file mode 100644
index 0000000000000000000000000000000000000000..54436587e3db90034652dcc144669dca91b863d5
--- /dev/null
+++ b/drivers/video/console/earlycon.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2013 Intel Corporation; author Matt Fleming
+ * Copyright (C) 2022 Markuss Broks <markuss.broks@gmail.com>
+ */
+
+#include <asm/early_ioremap.h>
+#include <linux/console.h>
+#include <linux/efi.h>
+#include <linux/font.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/serial_core.h>
+#include <linux/screen_info.h>
+
+struct fb_earlycon {
+	u32 x, y, curr_x, curr_y, depth, stride;
+	size_t size;
+	phys_addr_t phys_base;
+	void __iomem *virt_base;
+};
+
+static const struct console *earlycon_console __initconst;
+static struct fb_earlycon info;
+static const struct font_desc *font;
+
+static int __init simplefb_earlycon_remap_fb(void)
+{
+	unsigned long mapping;
+	/* bail if there is no bootconsole or it has been disabled already */
+	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
+		return 0;
+
+	if (region_intersects(info.phys_base, info.size,
+			      IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) == REGION_INTERSECTS)		
+		mapping = MEMREMAP_WB;
+	else
+		mapping = MEMREMAP_WC;
+
+	info.virt_base = memremap(info.phys_base, info.size, mapping);
+
+	return info.virt_base ? 0 : -ENOMEM;
+}
+early_initcall(simplefb_earlycon_remap_fb);
+
+static int __init simplefb_earlycon_unmap_fb(void)
+{
+	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
+	if (info.virt_base && !(earlycon_console->flags & CON_ENABLED))
+		memunmap(info.virt_base);
+	return 0;
+}
+late_initcall(simplefb_earlycon_unmap_fb);
+
+static __ref void *simplefb_earlycon_map(unsigned long start, unsigned long len)
+{
+	pgprot_t fb_prot;
+
+	if (info.virt_base)
+		return info.virt_base + start;
+
+	fb_prot = PAGE_KERNEL;
+	return early_memremap_prot(info.phys_base + start, len, pgprot_val(fb_prot));
+}
+
+static __ref void simplefb_earlycon_unmap(void *addr, unsigned long len)
+{
+	if (info.virt_base)
+		return;
+
+	early_memunmap(addr, len);
+}
+
+static void simplefb_earlycon_clear_scanline(unsigned int y)
+{
+	unsigned long *dst;
+	u16 len;
+
+	len = info.stride;
+	dst = simplefb_earlycon_map(y * len, len);
+	if (!dst)
+		return;
+
+	memset(dst, 0, len);
+	simplefb_earlycon_unmap(dst, len);
+}
+
+static void simplefb_earlycon_scroll_up(void)
+{
+	unsigned long *dst, *src;
+	u16 len;
+	u32 i, height;
+
+	len = info.stride;
+	height = info.y;
+
+	for (i = 0; i < height - font->height; i++) {
+		dst = simplefb_earlycon_map(i * len, len);
+		if (!dst)
+			return;
+
+		src = simplefb_earlycon_map((i + font->height) * len, len);
+		if (!src) {
+			simplefb_earlycon_unmap(dst, len);
+			return;
+		}
+
+		memmove(dst, src, len);
+
+		simplefb_earlycon_unmap(src, len);
+		simplefb_earlycon_unmap(dst, len);
+	}
+}
+
+static void simplefb_earlycon_write_char(u8 *dst, unsigned char c, unsigned int h)
+{
+	const u8 *src;
+	int m, n, bytes;
+	u8 x;
+
+	bytes = BITS_TO_BYTES(font->width);
+	src = font->data + c * font->height * bytes + h * bytes;
+
+	for (m = 0; m < font->width; m++) {
+		n = m % 8;
+		x = *(src + m / 8);
+		if ((x >> (7 - n)) & 1)
+			memset(dst, 0xff, (info.depth / 8));
+		else
+			memset(dst, 0, (info.depth / 8));
+		dst += (info.depth / 8);
+	}
+}
+
+static void
+simplefb_earlycon_write(struct console *con, const char *str, unsigned int num)
+{
+	unsigned int len;
+	const char *s;
+	void *dst;
+
+	len = info.stride;
+
+	while (num) {
+		unsigned int linemax;
+		unsigned int h, count = 0;
+
+		for (s = str; *s && *s != '\n'; s++) {
+			if (count == num)
+				break;
+			count++;
+		}
+
+		linemax = (info.x - info.curr_x) / font->width;
+		if (count > linemax)
+			count = linemax;
+
+		for (h = 0; h < font->height; h++) {
+			unsigned int n, x;
+
+			dst = simplefb_earlycon_map((info.curr_y + h) * len, len);
+			if (!dst)
+				return;
+
+			s = str;
+			n = count;
+			x = info.curr_x;
+
+			while (n-- > 0) {
+				simplefb_earlycon_write_char(dst + (x * 4), *s, h);
+				x += font->width;
+				s++;
+			}
+
+			simplefb_earlycon_unmap(dst, len);
+		}
+
+		num -= count;
+		info.curr_x += count * font->width;
+		str += count;
+
+		if (num > 0 && *s == '\n') {
+			info.curr_x = 0;
+			info.curr_y += font->height;
+			str++;
+			num--;
+		}
+
+		if (info.curr_x + font->width > info.x) {
+			info.curr_x = 0;
+			info.curr_y += font->height;
+		}
+
+		if (info.curr_y + font->height > info.y) {
+			u32 i;
+
+			info.curr_y -= font->height;
+			simplefb_earlycon_scroll_up();
+
+			for (i = 0; i < font->height; i++)
+				simplefb_earlycon_clear_scanline(info.curr_y + i);
+		}
+	}
+}
+
+static int __init simplefb_earlycon_setup_common(struct earlycon_device *device,
+						 const char *opt)
+{
+	int i;
+
+	info.size = info.x * info.y * (info.depth / 8);
+
+	font = get_default_font(info.x, info.y, -1, -1);
+	if (!font)
+		return -ENODEV;
+
+	info.curr_y = rounddown(info.y, font->height) - font->height;
+	for (i = 0; i < (info.y - info.curr_y) / font->height; i++)
+		simplefb_earlycon_scroll_up();
+
+	device->con->write = simplefb_earlycon_write;
+	earlycon_console = device->con;
+	return 0;
+}
+
+static int __init simplefb_earlycon_setup(struct earlycon_device *device,
+					  const char *opt)
+{
+	struct uart_port *port = &device->port;
+	int ret;
+
+	if (!port->mapbase)
+		return -ENODEV;
+
+	info.phys_base = port->mapbase;
+
+	ret = sscanf(device->options, "%ux%ux%u", &info.x, &info.y, &info.depth);
+	if (ret != 3)
+		return -ENODEV;
+
+	info.stride = info.x * (info.depth / 8);
+
+	return simplefb_earlycon_setup_common(device, opt);
+}
+
+EARLYCON_DECLARE(simplefb, simplefb_earlycon_setup);
+
+#ifdef CONFIG_EFI_EARLYCON
+static int __init simplefb_earlycon_setup_efi(struct earlycon_device *device,
+					      const char *opt)
+{
+	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+		return -ENODEV;
+
+	info.phys_base = screen_info.lfb_base;
+	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+		info.phys_base |= (u64)screen_info.ext_lfb_base << 32;
+
+	info.x = screen_info.lfb_width;
+	info.y = screen_info.lfb_height;
+	info.depth = screen_info.lfb_depth;
+	info.stride = screen_info.lfb_linelength;
+
+	return simplefb_earlycon_setup_common(device, opt);
+}
+
+EARLYCON_DECLARE(efifb, simplefb_earlycon_setup_efi);
+#endif
+
+#ifdef CONFIG_OF_EARLY_FLATTREE
+static int __init simplefb_earlycon_setup_of(struct earlycon_device *device,
+					     const char *opt)
+{
+	struct uart_port *port = &device->port;
+	const __be32 *val;
+
+	if (!port->mapbase)
+		return -ENODEV;
+
+	info.phys_base = port->mapbase;
+
+	val = of_get_flat_dt_prop(device->offset, "width", NULL);
+	if (!val)
+		return -ENODEV;
+	info.x = be32_to_cpu(*val);
+
+	val = of_get_flat_dt_prop(device->offset, "height", NULL);
+	if (!val)
+		return -ENODEV;
+	info.y = be32_to_cpu(*val);
+
+	val = of_get_flat_dt_prop(device->offset, "stride", NULL);
+	if (!val)
+		return -ENODEV;
+	info.stride = be32_to_cpu(*val);
+	info.depth = (info.stride / info.x) * 8;
+
+	return simplefb_earlycon_setup_common(device, opt);
+}
+
+OF_EARLYCON_DECLARE(simplefb, "simple-framebuffer", simplefb_earlycon_setup_of);
+#endif
-- 
2.37.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name
  2022-08-06 16:32 ` [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name Markuss Broks
@ 2022-08-06 16:56   ` Andy Shevchenko
  2022-08-08  1:28   ` kernel test robot
  2022-08-08 15:55   ` Rob Herring
  2 siblings, 0 replies; 15+ messages in thread
From: Andy Shevchenko @ 2022-08-06 16:56 UTC (permalink / raw)
  To: Markuss Broks
  Cc: Linux Kernel Mailing List, ~postmarketos/upstreaming,
	phone-devel, Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman,
	Jiri Slaby, Helge Deller, Paul E. McKenney, Borislav Petkov,
	Kees Cook, Andrew Morton, Randy Dunlap, Damien Le Moal,
	Thomas Zimmermann, Michal Suchanek, Javier Martinez Canillas,
	Arnd Bergmann, Maarten Lankhorst, Wei Ming Chen,
	Bartlomiej Zolnierkiewicz, Tony Lindgren,
	Linux Documentation List, linux-efi, open list:SERIAL DRIVERS,
	open list:FRAMEBUFFER LAYER, dri-devel, Rob Herring

On Sat, Aug 6, 2022 at 6:37 PM Markuss Broks <markuss.broks@gmail.com> wrote:
>
> The "node" argument is actually an offset, and it's also
> an "int", and not "unsigned long". Correct the of_setup_earlycon
> function.

Suggested-by: Greg KH?

> Signed-off-by: Markuss Broks <markuss.broks@gmail.com>

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
@ 2022-08-06 21:37   ` Andy Shevchenko
  2022-08-07 13:16   ` kernel test robot
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: Andy Shevchenko @ 2022-08-06 21:37 UTC (permalink / raw)
  To: Markuss Broks
  Cc: Linux Kernel Mailing List, ~postmarketos/upstreaming,
	phone-devel, Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman,
	Jiri Slaby, Helge Deller, Paul E. McKenney, Borislav Petkov,
	Kees Cook, Andrew Morton, Randy Dunlap, Damien Le Moal,
	Thomas Zimmermann, Michal Suchanek, Javier Martinez Canillas,
	Arnd Bergmann, Maarten Lankhorst, Wei Ming Chen,
	Bartlomiej Zolnierkiewicz, Tony Lindgren,
	Linux Documentation List, linux-efi, open list:SERIAL DRIVERS,
	open list:FRAMEBUFFER LAYER, dri-devel

On Sat, Aug 6, 2022 at 6:38 PM Markuss Broks <markuss.broks@gmail.com> wrote:
>
> Add early console support for generic linear framebuffer devices.
> This driver supports probing from cmdline early parameters
> or from the device-tree using information in simple-framebuffer node.
> The EFI functionality should be retained in whole.
> The driver was disabled on ARM because of a bug in early_ioremap

We refer to functions like func().

> implementation on ARM and on IA64 because of lack of early_memremap_prot.

Ditto.

...

> +#include <asm/early_ioremap.h>

Can it be placed after linux/* ones?

> +#include <linux/console.h>
> +#include <linux/efi.h>
> +#include <linux/font.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mm.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/serial_core.h>
> +#include <linux/screen_info.h>

...

> +static int __init simplefb_earlycon_remap_fb(void)
> +{
> +       unsigned long mapping;

+ Blank line.

> +       /* bail if there is no bootconsole or it has been disabled already */
> +       if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
> +               return 0;
> +
> +       if (region_intersects(info.phys_base, info.size,
> +                             IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) == REGION_INTERSECTS)
> +               mapping = MEMREMAP_WB;
> +       else
> +               mapping = MEMREMAP_WC;

> +       info.virt_base = memremap(info.phys_base, info.size, mapping);
> +
> +       return info.virt_base ? 0 : -ENOMEM;

Easier to read the standard pattern:

  if (!info.virt_base)
    return -ENOMEM;

  return 0;

> +}

...

> +static void simplefb_earlycon_write_char(u8 *dst, unsigned char c, unsigned int h)
> +{
> +       const u8 *src;
> +       int m, n, bytes;
> +       u8 x;
> +
> +       bytes = BITS_TO_BYTES(font->width);
> +       src = font->data + c * font->height * bytes + h * bytes;
> +
> +       for (m = 0; m < font->width; m++) {
> +               n = m % 8;
> +               x = *(src + m / 8);

I would write it as

  x = src[m / 8];

> +               if ((x >> (7 - n)) & 1)

> +                       memset(dst, 0xff, (info.depth / 8));

Too many parentheses.

> +               else
> +                       memset(dst, 0, (info.depth / 8));

Ditto.

> +               dst += (info.depth / 8);

Ditto.

> +       }
> +}

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
  2022-08-06 21:37   ` Andy Shevchenko
@ 2022-08-07 13:16   ` kernel test robot
  2022-08-14  0:01   ` kernel test robot
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: kernel test robot @ 2022-08-07 13:16 UTC (permalink / raw)
  To: Markuss Broks, linux-kernel
  Cc: kbuild-all, ~postmarketos/upstreaming, phone-devel,
	Markuss Broks, Jonathan Corbet, Ard Biesheuvel,
	Greg Kroah-Hartman, Jiri Slaby, Helge Deller, Paul E. McKenney,
	Borislav Petkov, Kees Cook, Andrew Morton,
	Linux Memory Management List, Randy Dunlap, Damien Le Moal,
	Thomas Zimmermann, Michal Suchanek, Javier Martinez Canillas,
	Arnd Bergmann, Maarten Lankhorst, Wei Ming Chen,
	Bartlomiej Zolnierkiewicz, Tony Lindgren, linux-doc, linux-efi,
	linux-serial, linux-fbdev, dri-devel

Hi Markuss,

I love your patch! Yet something to improve:

[auto build test ERROR on tty/tty-testing]
[also build test ERROR on efi/next staging/staging-testing usb/usb-testing linus/master v5.19 next-20220805]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20220807/202208072145.yWoGkrW1-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/97dfc2aa69b065de769a191352afe2099c52fedb
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
        git checkout 97dfc2aa69b065de769a191352afe2099c52fedb
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/video/console/earlycon.c:7:10: fatal error: asm/early_ioremap.h: No such file or directory
       7 | #include <asm/early_ioremap.h>
         |          ^~~~~~~~~~~~~~~~~~~~~
   compilation terminated.


vim +7 drivers/video/console/earlycon.c

   > 7	#include <asm/early_ioremap.h>
     8	#include <linux/console.h>
     9	#include <linux/efi.h>
    10	#include <linux/font.h>
    11	#include <linux/io.h>
    12	#include <linux/kernel.h>
    13	#include <linux/mm.h>
    14	#include <linux/of.h>
    15	#include <linux/of_fdt.h>
    16	#include <linux/serial_core.h>
    17	#include <linux/screen_info.h>
    18	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name
  2022-08-06 16:32 ` [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name Markuss Broks
  2022-08-06 16:56   ` Andy Shevchenko
@ 2022-08-08  1:28   ` kernel test robot
  2022-08-08 15:55   ` Rob Herring
  2 siblings, 0 replies; 15+ messages in thread
From: kernel test robot @ 2022-08-08  1:28 UTC (permalink / raw)
  To: Markuss Broks, linux-kernel
  Cc: llvm, kbuild-all, ~postmarketos/upstreaming, phone-devel,
	Markuss Broks, Jonathan Corbet, Ard Biesheuvel,
	Greg Kroah-Hartman, Jiri Slaby, Helge Deller, Paul E. McKenney,
	Borislav Petkov, Kees Cook, Andrew Morton,
	Linux Memory Management List, Randy Dunlap, Damien Le Moal,
	Thomas Zimmermann, Michal Suchanek, Javier Martinez Canillas,
	Arnd Bergmann, Maarten Lankhorst, Wei Ming Chen,
	Bartlomiej Zolnierkiewicz, Tony Lindgren, linux-doc, linux-efi,
	linux-serial, linux-fbdev, dri-devel, Rob Herring

Hi Markuss,

I love your patch! Yet something to improve:

[auto build test ERROR on tty/tty-testing]
[also build test ERROR on efi/next staging/staging-testing usb/usb-testing linus/master v5.19 next-20220805]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
config: x86_64-randconfig-a012 (https://download.01.org/0day-ci/archive/20220807/202208071111.oWn8uZfx-lkp@intel.com/config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 5f1c7e2cc5a3c07cbc2412e851a7283c1841f520)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/dedd7c138e9492439eeda05fa75a18bf19883a08
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
        git checkout dedd7c138e9492439eeda05fa75a18bf19883a08
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/tty/serial/earlycon.c:246:12: error: conflicting types for 'of_setup_earlycon'
   int __init of_setup_earlycon(const struct earlycon_id *match,
              ^
   include/linux/serial_core.h:708:12: note: previous declaration is here
   extern int of_setup_earlycon(const struct earlycon_id *match,
              ^
   1 error generated.


vim +/of_setup_earlycon +246 drivers/tty/serial/earlycon.c

8477614d9f7c5c Peter Hurley       2016-01-16  245  
c90fe9c0394b06 Peter Hurley       2016-01-16 @246  int __init of_setup_earlycon(const struct earlycon_id *match,
dedd7c138e9492 Markuss Broks      2022-08-06  247  			     int offset,
4d118c9a866590 Peter Hurley       2016-01-16  248  			     const char *options)
b0b6abd34c1b50 Rob Herring        2014-03-27  249  {
b0b6abd34c1b50 Rob Herring        2014-03-27  250  	int err;
b0b6abd34c1b50 Rob Herring        2014-03-27  251  	struct uart_port *port = &early_console_dev.port;
088da2a17619cf Peter Hurley       2016-01-16  252  	const __be32 *val;
088da2a17619cf Peter Hurley       2016-01-16  253  	bool big_endian;
c90fe9c0394b06 Peter Hurley       2016-01-16  254  	u64 addr;
b0b6abd34c1b50 Rob Herring        2014-03-27  255  
65e20e8cbbccaf Michael Walle      2022-06-28  256  	if (early_con.flags & CON_ENABLED)
65e20e8cbbccaf Michael Walle      2022-06-28  257  		return -EALREADY;
65e20e8cbbccaf Michael Walle      2022-06-28  258  
e1dd3bef6d03c9 Geert Uytterhoeven 2015-11-27  259  	spin_lock_init(&port->lock);
b0b6abd34c1b50 Rob Herring        2014-03-27  260  	port->iotype = UPIO_MEM;
dedd7c138e9492 Markuss Broks      2022-08-06  261  	addr = of_flat_dt_translate_address(offset);
c90fe9c0394b06 Peter Hurley       2016-01-16  262  	if (addr == OF_BAD_ADDR) {
c90fe9c0394b06 Peter Hurley       2016-01-16  263  		pr_warn("[%s] bad address\n", match->name);
c90fe9c0394b06 Peter Hurley       2016-01-16  264  		return -ENXIO;
c90fe9c0394b06 Peter Hurley       2016-01-16  265  	}
b0b6abd34c1b50 Rob Herring        2014-03-27  266  	port->mapbase = addr;
b0b6abd34c1b50 Rob Herring        2014-03-27  267  
dedd7c138e9492 Markuss Broks      2022-08-06  268  	val = of_get_flat_dt_prop(offset, "reg-offset", NULL);
088da2a17619cf Peter Hurley       2016-01-16  269  	if (val)
088da2a17619cf Peter Hurley       2016-01-16  270  		port->mapbase += be32_to_cpu(*val);
1f66dd36bb1843 Greentime Hu       2018-02-13  271  	port->membase = earlycon_map(port->mapbase, SZ_4K);
1f66dd36bb1843 Greentime Hu       2018-02-13  272  
dedd7c138e9492 Markuss Broks      2022-08-06  273  	val = of_get_flat_dt_prop(offset, "reg-shift", NULL);
088da2a17619cf Peter Hurley       2016-01-16  274  	if (val)
088da2a17619cf Peter Hurley       2016-01-16  275  		port->regshift = be32_to_cpu(*val);
dedd7c138e9492 Markuss Broks      2022-08-06  276  	big_endian = of_get_flat_dt_prop(offset, "big-endian", NULL) != NULL ||
088da2a17619cf Peter Hurley       2016-01-16  277  		(IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
dedd7c138e9492 Markuss Broks      2022-08-06  278  		 of_get_flat_dt_prop(offset, "native-endian", NULL) != NULL);
dedd7c138e9492 Markuss Broks      2022-08-06  279  	val = of_get_flat_dt_prop(offset, "reg-io-width", NULL);
088da2a17619cf Peter Hurley       2016-01-16  280  	if (val) {
088da2a17619cf Peter Hurley       2016-01-16  281  		switch (be32_to_cpu(*val)) {
088da2a17619cf Peter Hurley       2016-01-16  282  		case 1:
088da2a17619cf Peter Hurley       2016-01-16  283  			port->iotype = UPIO_MEM;
088da2a17619cf Peter Hurley       2016-01-16  284  			break;
088da2a17619cf Peter Hurley       2016-01-16  285  		case 2:
088da2a17619cf Peter Hurley       2016-01-16  286  			port->iotype = UPIO_MEM16;
088da2a17619cf Peter Hurley       2016-01-16  287  			break;
088da2a17619cf Peter Hurley       2016-01-16  288  		case 4:
088da2a17619cf Peter Hurley       2016-01-16  289  			port->iotype = (big_endian) ? UPIO_MEM32BE : UPIO_MEM32;
088da2a17619cf Peter Hurley       2016-01-16  290  			break;
088da2a17619cf Peter Hurley       2016-01-16  291  		default:
088da2a17619cf Peter Hurley       2016-01-16  292  			pr_warn("[%s] unsupported reg-io-width\n", match->name);
088da2a17619cf Peter Hurley       2016-01-16  293  			return -EINVAL;
088da2a17619cf Peter Hurley       2016-01-16  294  		}
088da2a17619cf Peter Hurley       2016-01-16  295  	}
088da2a17619cf Peter Hurley       2016-01-16  296  
dedd7c138e9492 Markuss Broks      2022-08-06  297  	val = of_get_flat_dt_prop(offset, "current-speed", NULL);
31cb9a8575ca04 Eugeniy Paltsev    2017-08-21  298  	if (val)
31cb9a8575ca04 Eugeniy Paltsev    2017-08-21  299  		early_console_dev.baud = be32_to_cpu(*val);
31cb9a8575ca04 Eugeniy Paltsev    2017-08-21  300  
dedd7c138e9492 Markuss Broks      2022-08-06  301  	val = of_get_flat_dt_prop(offset, "clock-frequency", NULL);
814453adea7d08 Michal Simek       2018-04-10  302  	if (val)
814453adea7d08 Michal Simek       2018-04-10  303  		port->uartclk = be32_to_cpu(*val);
814453adea7d08 Michal Simek       2018-04-10  304  
4d118c9a866590 Peter Hurley       2016-01-16  305  	if (options) {
31cb9a8575ca04 Eugeniy Paltsev    2017-08-21  306  		early_console_dev.baud = simple_strtoul(options, NULL, 0);
4d118c9a866590 Peter Hurley       2016-01-16  307  		strlcpy(early_console_dev.options, options,
4d118c9a866590 Peter Hurley       2016-01-16  308  			sizeof(early_console_dev.options));
4d118c9a866590 Peter Hurley       2016-01-16  309  	}
05d961320ba624 Peter Hurley       2016-01-16  310  	earlycon_init(&early_console_dev, match->name);
4d118c9a866590 Peter Hurley       2016-01-16  311  	err = match->setup(&early_console_dev, options);
f28295cc8ce14b Hsin-Yi Wang       2020-09-15  312  	earlycon_print_info(&early_console_dev);
b0b6abd34c1b50 Rob Herring        2014-03-27  313  	if (err < 0)
b0b6abd34c1b50 Rob Herring        2014-03-27  314  		return err;
b0b6abd34c1b50 Rob Herring        2014-03-27  315  	if (!early_console_dev.con->write)
b0b6abd34c1b50 Rob Herring        2014-03-27  316  		return -ENODEV;
b0b6abd34c1b50 Rob Herring        2014-03-27  317  
b0b6abd34c1b50 Rob Herring        2014-03-27  318  
b0b6abd34c1b50 Rob Herring        2014-03-27  319  	register_console(early_console_dev.con);
b0b6abd34c1b50 Rob Herring        2014-03-27  320  	return 0;
b0b6abd34c1b50 Rob Herring        2014-03-27  321  }
8477614d9f7c5c Peter Hurley       2016-01-16  322  

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name
  2022-08-06 16:32 ` [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name Markuss Broks
  2022-08-06 16:56   ` Andy Shevchenko
  2022-08-08  1:28   ` kernel test robot
@ 2022-08-08 15:55   ` Rob Herring
  2 siblings, 0 replies; 15+ messages in thread
From: Rob Herring @ 2022-08-08 15:55 UTC (permalink / raw)
  To: Markuss Broks
  Cc: linux-kernel,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
	<devicetree@vger.kernel.org>,
	Hans de Goede <hdegoede@redhat.com>,
	Andy Shevchenko <andy.shevchenko@gmail.com>,,
	phone-devel, Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman,
	Jiri Slaby, Helge Deller, Paul E. McKenney, Borislav Petkov,
	Kees Cook, Andrew Morton, Randy Dunlap, Damien Le Moal,
	Thomas Zimmermann, Michal Suchanek, Javier Martinez Canillas,
	Arnd Bergmann, Maarten Lankhorst, Wei Ming Chen,
	Bartlomiej Zolnierkiewicz, Tony Lindgren, Linux Doc Mailing List,
	linux-efi, open list:SERIAL DRIVERS,
	Linux Fbdev development list, dri-devel

On Sat, Aug 6, 2022 at 10:34 AM Markuss Broks <markuss.broks@gmail.com> wrote:
>
> The "node" argument is actually an offset,

It's an offset to a node in the FDT. The fact that it is an offset is
an internal implementation detail of the FDT format. So really, it's a
handle to a node. 'node' is more descriptive to its purpose.

> and it's also an "int", and not "unsigned long".

Uh, no it's not. of_flat_dt_*() functions all take an unsigned long.

Rob

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
  2022-08-06 21:37   ` Andy Shevchenko
  2022-08-07 13:16   ` kernel test robot
@ 2022-08-14  0:01   ` kernel test robot
  2022-08-14  7:04   ` kernel test robot
  2022-09-06 21:52   ` Daniel Vetter
  4 siblings, 0 replies; 15+ messages in thread
From: kernel test robot @ 2022-08-14  0:01 UTC (permalink / raw)
  To: Markuss Broks, linux-kernel
  Cc: kbuild-all, ~postmarketos/upstreaming, phone-devel,
	Markuss Broks, Jonathan Corbet, Ard Biesheuvel,
	Greg Kroah-Hartman, Jiri Slaby, Helge Deller, Paul E. McKenney,
	Borislav Petkov, Kees Cook, Andrew Morton,
	Linux Memory Management List, Randy Dunlap, Damien Le Moal,
	Thomas Zimmermann, Michal Suchanek, Javier Martinez Canillas,
	Arnd Bergmann, Maarten Lankhorst, Wei Ming Chen,
	Bartlomiej Zolnierkiewicz, Tony Lindgren, linux-doc, linux-efi,
	linux-serial, linux-fbdev, dri-devel

Hi Markuss,

I love your patch! Perhaps something to improve:

[auto build test WARNING on tty/tty-testing]
[also build test WARNING on efi/next staging/staging-testing usb/usb-testing linus/master v5.19 next-20220812]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
config: loongarch-randconfig-s031-20220807 (https://download.01.org/0day-ci/archive/20220814/202208140705.bU9i1c1t-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 12.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/97dfc2aa69b065de769a191352afe2099c52fedb
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
        git checkout 97dfc2aa69b065de769a191352afe2099c52fedb
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=loongarch SHELL=/bin/bash drivers/video/console/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

sparse warnings: (new ones prefixed by >>)
>> drivers/video/console/earlycon.c:43:24: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected void [noderef] __iomem *static [toplevel] virt_base @@     got void * @@
   drivers/video/console/earlycon.c:43:24: sparse:     expected void [noderef] __iomem *static [toplevel] virt_base
   drivers/video/console/earlycon.c:43:24: sparse:     got void *
>> drivers/video/console/earlycon.c:53:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void *addr @@     got void [noderef] __iomem *static [toplevel] virt_base @@
   drivers/video/console/earlycon.c:53:30: sparse:     expected void *addr
   drivers/video/console/earlycon.c:53:30: sparse:     got void [noderef] __iomem *static [toplevel] virt_base
>> drivers/video/console/earlycon.c:63:39: sparse: sparse: incorrect type in return expression (different address spaces) @@     expected void * @@     got void [noderef] __iomem * @@
   drivers/video/console/earlycon.c:63:39: sparse:     expected void *
   drivers/video/console/earlycon.c:63:39: sparse:     got void [noderef] __iomem *
>> drivers/video/console/earlycon.c:74:24: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __iomem *addr @@     got void *addr @@
   drivers/video/console/earlycon.c:74:24: sparse:     expected void [noderef] __iomem *addr
   drivers/video/console/earlycon.c:74:24: sparse:     got void *addr

vim +43 drivers/video/console/earlycon.c

    29	
    30	static int __init simplefb_earlycon_remap_fb(void)
    31	{
    32		unsigned long mapping;
    33		/* bail if there is no bootconsole or it has been disabled already */
    34		if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
    35			return 0;
    36	
    37		if (region_intersects(info.phys_base, info.size,
    38				      IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) == REGION_INTERSECTS)		
    39			mapping = MEMREMAP_WB;
    40		else
    41			mapping = MEMREMAP_WC;
    42	
  > 43		info.virt_base = memremap(info.phys_base, info.size, mapping);
    44	
    45		return info.virt_base ? 0 : -ENOMEM;
    46	}
    47	early_initcall(simplefb_earlycon_remap_fb);
    48	
    49	static int __init simplefb_earlycon_unmap_fb(void)
    50	{
    51		/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
    52		if (info.virt_base && !(earlycon_console->flags & CON_ENABLED))
  > 53			memunmap(info.virt_base);
    54		return 0;
    55	}
    56	late_initcall(simplefb_earlycon_unmap_fb);
    57	
    58	static __ref void *simplefb_earlycon_map(unsigned long start, unsigned long len)
    59	{
    60		pgprot_t fb_prot;
    61	
    62		if (info.virt_base)
  > 63			return info.virt_base + start;
    64	
    65		fb_prot = PAGE_KERNEL;
    66		return early_memremap_prot(info.phys_base + start, len, pgprot_val(fb_prot));
    67	}
    68	
    69	static __ref void simplefb_earlycon_unmap(void *addr, unsigned long len)
    70	{
    71		if (info.virt_base)
    72			return;
    73	
  > 74		early_memunmap(addr, len);
    75	}
    76	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
                     ` (2 preceding siblings ...)
  2022-08-14  0:01   ` kernel test robot
@ 2022-08-14  7:04   ` kernel test robot
  2022-09-06 21:52   ` Daniel Vetter
  4 siblings, 0 replies; 15+ messages in thread
From: kernel test robot @ 2022-08-14  7:04 UTC (permalink / raw)
  To: Markuss Broks, linux-kernel
  Cc: Paul Gazzillo, Necip Fazil Yildiran, kbuild-all,
	~postmarketos/upstreaming, phone-devel, Markuss Broks,
	Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman, Jiri Slaby,
	Helge Deller, Paul E. McKenney, Borislav Petkov, Kees Cook,
	Andrew Morton, Linux Memory Management List, Randy Dunlap,
	Damien Le Moal, Thomas Zimmermann, Michal Suchanek,
	Javier Martinez Canillas, Arnd Bergmann, Maarten Lankhorst,
	Wei Ming Chen, Bartlomiej Zolnierkiewicz, Tony Lindgren,
	linux-doc, linux-efi, linux-serial, linux-fbdev, dri-devel

Hi Markuss,

I love your patch! Perhaps something to improve:

[auto build test WARNING on tty/tty-testing]
[also build test WARNING on efi/next staging/staging-testing usb/usb-testing linus/master v5.19 next-20220812]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
config: x86_64-kismet-CONFIG_FB_EARLYCON-CONFIG_EFI_EARLYCON-0-0 (https://download.01.org/0day-ci/archive/20220814/202208141430.Ez8EkEwO-lkp@intel.com/config)
reproduce:
        # https://github.com/intel-lab-lkp/linux/commit/97dfc2aa69b065de769a191352afe2099c52fedb
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Markuss-Broks/Add-generic-framebuffer-support-to-EFI-earlycon-driver/20220807-003646
        git checkout 97dfc2aa69b065de769a191352afe2099c52fedb
        # 1. reproduce by kismet
           # install kmax per https://github.com/paulgazz/kmax/blob/master/README.md
           kismet --linux-ksrc=linux --selectees CONFIG_FB_EARLYCON --selectors CONFIG_EFI_EARLYCON -a=x86_64
        # 2. reproduce by make
           # save the config file to linux source tree
           cd linux
           make ARCH=x86_64 olddefconfig

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

kismet warnings: (new ones prefixed by >>)
>> kismet: WARNING: unmet direct dependencies detected for FB_EARLYCON when selected by EFI_EARLYCON
   
   WARNING: unmet direct dependencies detected for FB_EARLYCON
     Depends on [n]: VT [=y] && SERIAL_EARLYCON [=n] && !ARM && !IA64
     Selected by [y]:
     - EFI_EARLYCON [=y] && EFI [=y]

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver
  2022-08-06 16:32 [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Markuss Broks
                   ` (2 preceding siblings ...)
  2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
@ 2022-09-06 16:54 ` Ard Biesheuvel
  3 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2022-09-06 16:54 UTC (permalink / raw)
  To: Markuss Broks
  Cc: linux-kernel, ~postmarketos/upstreaming, phone-devel,
	Jonathan Corbet, Greg Kroah-Hartman, Jiri Slaby, Helge Deller,
	Paul E. McKenney, Borislav Petkov, Kees Cook, Andrew Morton,
	Randy Dunlap, Damien Le Moal, Thomas Zimmermann, Michal Suchanek,
	Javier Martinez Canillas, Arnd Bergmann, Maarten Lankhorst,
	Wei Ming Chen, Bartlomiej Zolnierkiewicz, Tony Lindgren,
	linux-doc, linux-efi, linux-serial, linux-fbdev, dri-devel

On Sat, 6 Aug 2022 at 18:34, Markuss Broks <markuss.broks@gmail.com> wrote:
>
> Make the EFI earlycon driver be suitable for any linear framebuffers.
> This should be helpful for early porting of boards with no other means of
> output, like smartphones/tablets. There seems to be an issue with early_ioremap
> function on ARM32, but I am unable to find the exact cause. It appears the mappings
> returned by it are somehow incorrect, thus the driver is disabled on ARM. EFI early
> console was disabled on IA64 previously because of missing early_memremap_prot,
> and this is inherited to this driver.
>
> This patch also changes behavior on EFI systems, by selecting the mapping type
> based on if the framebuffer region intersects with system RAM. If it does, it's
> common sense that it should be in RAM as a whole, and so the system RAM mapping is
> used. It was tested to be working on my PC (Intel Z490 platform), as well as several
> ARM64 boards (Samsung Galaxy S9 (Exynos), iPad Air 2, Xiaomi Mi Pad 4, ...).
>
> Markuss Broks (2):
>   drivers: serial: earlycon: Pass device-tree node
>   efi: earlycon: Add support for generic framebuffers and move to fbdev
>     subsystem
>
>
> v1 -> v2:
>
> - a new patch correcting serial/earlycon.c argument name to "offset" instead
>   of "node"
> - move IA64 exclusion from EFI earlycon Kconfig to earlycon driver Kconfig
>   (IA64 has no early_memremap_prot)
> - move driver from fbdev to console subsystem
> - select EFI earlycon by default

Wasn't EFI earlycon already enabled by default?

> - fetch stride manually from device-tree, as on some devices it seems stride
>   doesn't match the horizontal resolution * bpp.
> - use saner format (e.g. 1920x1080x32 instead of 1920,1080,32).
>
>  .../admin-guide/kernel-parameters.txt         |  12 +-
>  MAINTAINERS                                   |   5 +
>  drivers/firmware/efi/Kconfig                  |   6 +-
>  drivers/firmware/efi/Makefile                 |   1 -
>  drivers/firmware/efi/earlycon.c               | 246 --------------
>  drivers/tty/serial/earlycon.c                 |   3 +
>  drivers/video/fbdev/Kconfig                   |  11 +
>  drivers/video/fbdev/Makefile                  |   1 +
>  drivers/video/fbdev/earlycon.c                | 301 ++++++++++++++++++
>  include/linux/serial_core.h                   |   1 +
>  10 files changed, 331 insertions(+), 256 deletions(-)
>  delete mode 100644 drivers/firmware/efi/earlycon.c
>  create mode 100644 drivers/video/fbdev/earlycon.c
>
> --
> 2.37.0
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
                     ` (3 preceding siblings ...)
  2022-08-14  7:04   ` kernel test robot
@ 2022-09-06 21:52   ` Daniel Vetter
  2022-09-07  6:55     ` Thomas Zimmermann
  2022-09-07  8:22     ` Arnd Bergmann
  4 siblings, 2 replies; 15+ messages in thread
From: Daniel Vetter @ 2022-09-06 21:52 UTC (permalink / raw)
  To: Markuss Broks
  Cc: linux-kernel, ~postmarketos/upstreaming, phone-devel,
	Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman, Jiri Slaby,
	Helge Deller, Paul E. McKenney, Borislav Petkov, Kees Cook,
	Andrew Morton, Randy Dunlap, Damien Le Moal, Thomas Zimmermann,
	Michal Suchanek, Javier Martinez Canillas, Arnd Bergmann,
	Maarten Lankhorst, Wei Ming Chen, Bartlomiej Zolnierkiewicz,
	Tony Lindgren, linux-doc, linux-efi, linux-serial, linux-fbdev,
	dri-devel

On Sat, Aug 06, 2022 at 07:32:24PM +0300, Markuss Broks wrote:
> Add early console support for generic linear framebuffer devices.
> This driver supports probing from cmdline early parameters
> or from the device-tree using information in simple-framebuffer node.
> The EFI functionality should be retained in whole.
> The driver was disabled on ARM because of a bug in early_ioremap
> implementation on ARM and on IA64 because of lack of early_memremap_prot.
> 
> Signed-off-by: Markuss Broks <markuss.broks@gmail.com>
> ---
>  .../admin-guide/kernel-parameters.txt         |  12 +-
>  MAINTAINERS                                   |   5 +
>  drivers/firmware/efi/Kconfig                  |   7 +-
>  drivers/firmware/efi/Makefile                 |   1 -
>  drivers/firmware/efi/earlycon.c               | 246 --------------
>  drivers/video/console/Kconfig                 |  11 +
>  drivers/video/console/Makefile                |   1 +
>  drivers/video/console/earlycon.c              | 305 ++++++++++++++++++

Ok I have a more fundamental issue with this than the lack of proper patch
splitting I mentioned in the other thread.

This is the wrong place.

drivers/video/console is about the various vt console implementations,
which supply a struct consw to con_register_driver.

This otoh is an (early) kernel/printk console implemented using struct
console. Totally different thing, and really shouldn't end up in
drivers/video/console imo. Somewhere in drivers/firmware might still be
the best place, the sysfb stuff is also there. Maybe
drivers/firmware/sysfb_earlycon.c?

Also patch split is still an issue here, like I and Greg already said.
-Daniel

>  8 files changed, 332 insertions(+), 256 deletions(-)
>  delete mode 100644 drivers/firmware/efi/earlycon.c
>  create mode 100644 drivers/video/console/earlycon.c
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 8090130b544b0701237a7b657a29c83c000a60f4..bccb1ac8978eb5cf7e2bb20834b1881b27040666 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1281,12 +1281,9 @@
>  			specified address. The serial port must already be
>  			setup and configured. Options are not yet supported.
>  
> -		efifb,[options]
> +		efifb
>  			Start an early, unaccelerated console on the EFI
> -			memory mapped framebuffer (if available). On cache
> -			coherent non-x86 systems that use system memory for
> -			the framebuffer, pass the 'ram' option so that it is
> -			mapped with the correct attributes.
> +			memory mapped framebuffer (if available).
>  
>  		linflex,<addr>
>  			Use early console provided by Freescale LINFlexD UART
> @@ -1294,6 +1291,11 @@
>  			address must be provided, and the serial port must
>  			already be setup and configured.
>  
> +		simplefb,<addr>,<width>x<height>x<bpp>
> +			Use early console with simple framebuffer that is
> +			pre-initialized by firmware. A valid base address,
> +			width, height and pixel size must be provided.
> +
>  	earlyprintk=	[X86,SH,ARM,M68k,S390]
>  			earlyprintk=vga
>  			earlyprintk=sclp
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1fc9ead83d2aa3e60ccc4cfa8ee16df09ef579bf..af8b8e289483b6a264d477145061bd0e0ba34a25 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7033,6 +7033,11 @@ Q:	http://patchwork.linuxtv.org/project/linux-media/list/
>  T:	git git://linuxtv.org/anttip/media_tree.git
>  F:	drivers/media/tuners/e4000*
>  
> +EARLY CONSOLE FRAMEBUFFER DRIVER
> +M:	Markuss Broks <markuss.broks@gmail.com>
> +S:	Maintained
> +F:	drivers/video/console/earlycon.c
> +
>  EARTH_PT1 MEDIA DRIVER
>  M:	Akihiro Tsukada <tskd08@gmail.com>
>  L:	linux-media@vger.kernel.org
> diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
> index 7aa4717cdcac46f91dd202f868c463388eb02735..ea76ccfb9bcd8ba44ddca06052eaa442ed6c30f7 100644
> --- a/drivers/firmware/efi/Kconfig
> +++ b/drivers/firmware/efi/Kconfig
> @@ -259,10 +259,9 @@ config EFI_DISABLE_PCI_DMA
>  	  may be used to override this option.
>  
>  config EFI_EARLYCON
> -	def_bool y
> -	depends on SERIAL_EARLYCON && !ARM && !IA64
> -	select FONT_SUPPORT
> -	select ARCH_USE_MEMREMAP_PROT
> +	bool "EFI early console support"
> +	select FB_EARLYCON
> +	default y
>  
>  config EFI_CUSTOM_SSDT_OVERLAYS
>  	bool "Load custom ACPI SSDT overlay from an EFI variable"
> diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
> index c02ff25dd47707090a2ab86ee4f330e467f878f5..64eea61fbb43d76ec2d5416d467dfbb9aa21bda0 100644
> --- a/drivers/firmware/efi/Makefile
> +++ b/drivers/firmware/efi/Makefile
> @@ -44,6 +44,5 @@ obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
>  riscv-obj-$(CONFIG_EFI)			:= efi-init.o riscv-runtime.o
>  obj-$(CONFIG_RISCV)			+= $(riscv-obj-y)
>  obj-$(CONFIG_EFI_CAPSULE_LOADER)	+= capsule-loader.o
> -obj-$(CONFIG_EFI_EARLYCON)		+= earlycon.o
>  obj-$(CONFIG_UEFI_CPER_ARM)		+= cper-arm.o
>  obj-$(CONFIG_UEFI_CPER_X86)		+= cper-x86.o
> diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c
> deleted file mode 100644
> index a52236e11e5f73ddea5bb1f42ca2ca7c42425dab..0000000000000000000000000000000000000000
> --- a/drivers/firmware/efi/earlycon.c
> +++ /dev/null
> @@ -1,246 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * Copyright (C) 2013 Intel Corporation; author Matt Fleming
> - */
> -
> -#include <linux/console.h>
> -#include <linux/efi.h>
> -#include <linux/font.h>
> -#include <linux/io.h>
> -#include <linux/kernel.h>
> -#include <linux/serial_core.h>
> -#include <linux/screen_info.h>
> -
> -#include <asm/early_ioremap.h>
> -
> -static const struct console *earlycon_console __initdata;
> -static const struct font_desc *font;
> -static u32 efi_x, efi_y;
> -static u64 fb_base;
> -static bool fb_wb;
> -static void *efi_fb;
> -
> -/*
> - * EFI earlycon needs to use early_memremap() to map the framebuffer.
> - * But early_memremap() is not usable for 'earlycon=efifb keep_bootcon',
> - * memremap() should be used instead. memremap() will be available after
> - * paging_init() which is earlier than initcall callbacks. Thus adding this
> - * early initcall function early_efi_map_fb() to map the whole EFI framebuffer.
> - */
> -static int __init efi_earlycon_remap_fb(void)
> -{
> -	/* bail if there is no bootconsole or it has been disabled already */
> -	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
> -		return 0;
> -
> -	efi_fb = memremap(fb_base, screen_info.lfb_size,
> -			  fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
> -
> -	return efi_fb ? 0 : -ENOMEM;
> -}
> -early_initcall(efi_earlycon_remap_fb);
> -
> -static int __init efi_earlycon_unmap_fb(void)
> -{
> -	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
> -	if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
> -		memunmap(efi_fb);
> -	return 0;
> -}
> -late_initcall(efi_earlycon_unmap_fb);
> -
> -static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
> -{
> -	pgprot_t fb_prot;
> -
> -	if (efi_fb)
> -		return efi_fb + start;
> -
> -	fb_prot = fb_wb ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL);
> -	return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
> -}
> -
> -static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
> -{
> -	if (efi_fb)
> -		return;
> -
> -	early_memunmap(addr, len);
> -}
> -
> -static void efi_earlycon_clear_scanline(unsigned int y)
> -{
> -	unsigned long *dst;
> -	u16 len;
> -
> -	len = screen_info.lfb_linelength;
> -	dst = efi_earlycon_map(y*len, len);
> -	if (!dst)
> -		return;
> -
> -	memset(dst, 0, len);
> -	efi_earlycon_unmap(dst, len);
> -}
> -
> -static void efi_earlycon_scroll_up(void)
> -{
> -	unsigned long *dst, *src;
> -	u16 len;
> -	u32 i, height;
> -
> -	len = screen_info.lfb_linelength;
> -	height = screen_info.lfb_height;
> -
> -	for (i = 0; i < height - font->height; i++) {
> -		dst = efi_earlycon_map(i*len, len);
> -		if (!dst)
> -			return;
> -
> -		src = efi_earlycon_map((i + font->height) * len, len);
> -		if (!src) {
> -			efi_earlycon_unmap(dst, len);
> -			return;
> -		}
> -
> -		memmove(dst, src, len);
> -
> -		efi_earlycon_unmap(src, len);
> -		efi_earlycon_unmap(dst, len);
> -	}
> -}
> -
> -static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h)
> -{
> -	const u32 color_black = 0x00000000;
> -	const u32 color_white = 0x00ffffff;
> -	const u8 *src;
> -	int m, n, bytes;
> -	u8 x;
> -
> -	bytes = BITS_TO_BYTES(font->width);
> -	src = font->data + c * font->height * bytes + h * bytes;
> -
> -	for (m = 0; m < font->width; m++) {
> -		n = m % 8;
> -		x = *(src + m / 8);
> -		if ((x >> (7 - n)) & 1)
> -			*dst = color_white;
> -		else
> -			*dst = color_black;
> -		dst++;
> -	}
> -}
> -
> -static void
> -efi_earlycon_write(struct console *con, const char *str, unsigned int num)
> -{
> -	struct screen_info *si;
> -	unsigned int len;
> -	const char *s;
> -	void *dst;
> -
> -	si = &screen_info;
> -	len = si->lfb_linelength;
> -
> -	while (num) {
> -		unsigned int linemax;
> -		unsigned int h, count = 0;
> -
> -		for (s = str; *s && *s != '\n'; s++) {
> -			if (count == num)
> -				break;
> -			count++;
> -		}
> -
> -		linemax = (si->lfb_width - efi_x) / font->width;
> -		if (count > linemax)
> -			count = linemax;
> -
> -		for (h = 0; h < font->height; h++) {
> -			unsigned int n, x;
> -
> -			dst = efi_earlycon_map((efi_y + h) * len, len);
> -			if (!dst)
> -				return;
> -
> -			s = str;
> -			n = count;
> -			x = efi_x;
> -
> -			while (n-- > 0) {
> -				efi_earlycon_write_char(dst + x*4, *s, h);
> -				x += font->width;
> -				s++;
> -			}
> -
> -			efi_earlycon_unmap(dst, len);
> -		}
> -
> -		num -= count;
> -		efi_x += count * font->width;
> -		str += count;
> -
> -		if (num > 0 && *s == '\n') {
> -			efi_x = 0;
> -			efi_y += font->height;
> -			str++;
> -			num--;
> -		}
> -
> -		if (efi_x + font->width > si->lfb_width) {
> -			efi_x = 0;
> -			efi_y += font->height;
> -		}
> -
> -		if (efi_y + font->height > si->lfb_height) {
> -			u32 i;
> -
> -			efi_y -= font->height;
> -			efi_earlycon_scroll_up();
> -
> -			for (i = 0; i < font->height; i++)
> -				efi_earlycon_clear_scanline(efi_y + i);
> -		}
> -	}
> -}
> -
> -static int __init efi_earlycon_setup(struct earlycon_device *device,
> -				     const char *opt)
> -{
> -	struct screen_info *si;
> -	u16 xres, yres;
> -	u32 i;
> -
> -	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
> -		return -ENODEV;
> -
> -	fb_base = screen_info.lfb_base;
> -	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
> -		fb_base |= (u64)screen_info.ext_lfb_base << 32;
> -
> -	fb_wb = opt && !strcmp(opt, "ram");
> -
> -	si = &screen_info;
> -	xres = si->lfb_width;
> -	yres = si->lfb_height;
> -
> -	/*
> -	 * efi_earlycon_write_char() implicitly assumes a framebuffer with
> -	 * 32 bits per pixel.
> -	 */
> -	if (si->lfb_depth != 32)
> -		return -ENODEV;
> -
> -	font = get_default_font(xres, yres, -1, -1);
> -	if (!font)
> -		return -ENODEV;
> -
> -	efi_y = rounddown(yres, font->height) - font->height;
> -	for (i = 0; i < (yres - efi_y) / font->height; i++)
> -		efi_earlycon_scroll_up();
> -
> -	device->con->write = efi_earlycon_write;
> -	earlycon_console = device->con;
> -	return 0;
> -}
> -EARLYCON_DECLARE(efifb, efi_earlycon_setup);
> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> index 40c50fa2dd70c33a1549141b15e6cba721352d2d..8052507e058fce37f5a51058e58ae2eb10d9669a 100644
> --- a/drivers/video/console/Kconfig
> +++ b/drivers/video/console/Kconfig
> @@ -69,6 +69,17 @@ config DUMMY_CONSOLE_ROWS
>  	  monitor.
>  	  Select 25 if you use a 640x480 resolution by default.
>  
> +config FB_EARLYCON
> +	bool "Generic framebuffer early console"
> +	depends on SERIAL_EARLYCON && !ARM && !IA64
> +	select FONT_SUPPORT
> +	select ARCH_USE_MEMREMAP_PROT
> +	help
> +	  Say Y here if you want early console support for firmware established
> +	  linear framebuffer. Unless you are using EFI framebuffer, you need to
> +	  specify framebuffer geometry and address in device-tree or in kernel
> +	  command line.
> +
>  config FRAMEBUFFER_CONSOLE
>  	bool "Framebuffer Console support"
>  	depends on FB && !UML
> diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
> index db07b784bd2ccdcbffde933926ed5cee2bbbc7d4..7818faee587fc9c40b429617cfa224c0ccbc557c 100644
> --- a/drivers/video/console/Makefile
> +++ b/drivers/video/console/Makefile
> @@ -9,4 +9,5 @@ obj-$(CONFIG_STI_CONSOLE)         += sticon.o sticore.o
>  obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
>  obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
>  
> +obj-$(CONFIG_FB_EARLYCON)         += earlycon.o
>  obj-$(CONFIG_FB_STI)              += sticore.o
> diff --git a/drivers/video/console/earlycon.c b/drivers/video/console/earlycon.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..54436587e3db90034652dcc144669dca91b863d5
> --- /dev/null
> +++ b/drivers/video/console/earlycon.c
> @@ -0,0 +1,305 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2013 Intel Corporation; author Matt Fleming
> + * Copyright (C) 2022 Markuss Broks <markuss.broks@gmail.com>
> + */
> +
> +#include <asm/early_ioremap.h>
> +#include <linux/console.h>
> +#include <linux/efi.h>
> +#include <linux/font.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mm.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/serial_core.h>
> +#include <linux/screen_info.h>
> +
> +struct fb_earlycon {
> +	u32 x, y, curr_x, curr_y, depth, stride;
> +	size_t size;
> +	phys_addr_t phys_base;
> +	void __iomem *virt_base;
> +};
> +
> +static const struct console *earlycon_console __initconst;
> +static struct fb_earlycon info;
> +static const struct font_desc *font;
> +
> +static int __init simplefb_earlycon_remap_fb(void)
> +{
> +	unsigned long mapping;
> +	/* bail if there is no bootconsole or it has been disabled already */
> +	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
> +		return 0;
> +
> +	if (region_intersects(info.phys_base, info.size,
> +			      IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) == REGION_INTERSECTS)		
> +		mapping = MEMREMAP_WB;
> +	else
> +		mapping = MEMREMAP_WC;
> +
> +	info.virt_base = memremap(info.phys_base, info.size, mapping);
> +
> +	return info.virt_base ? 0 : -ENOMEM;
> +}
> +early_initcall(simplefb_earlycon_remap_fb);
> +
> +static int __init simplefb_earlycon_unmap_fb(void)
> +{
> +	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
> +	if (info.virt_base && !(earlycon_console->flags & CON_ENABLED))
> +		memunmap(info.virt_base);
> +	return 0;
> +}
> +late_initcall(simplefb_earlycon_unmap_fb);
> +
> +static __ref void *simplefb_earlycon_map(unsigned long start, unsigned long len)
> +{
> +	pgprot_t fb_prot;
> +
> +	if (info.virt_base)
> +		return info.virt_base + start;
> +
> +	fb_prot = PAGE_KERNEL;
> +	return early_memremap_prot(info.phys_base + start, len, pgprot_val(fb_prot));
> +}
> +
> +static __ref void simplefb_earlycon_unmap(void *addr, unsigned long len)
> +{
> +	if (info.virt_base)
> +		return;
> +
> +	early_memunmap(addr, len);
> +}
> +
> +static void simplefb_earlycon_clear_scanline(unsigned int y)
> +{
> +	unsigned long *dst;
> +	u16 len;
> +
> +	len = info.stride;
> +	dst = simplefb_earlycon_map(y * len, len);
> +	if (!dst)
> +		return;
> +
> +	memset(dst, 0, len);
> +	simplefb_earlycon_unmap(dst, len);
> +}
> +
> +static void simplefb_earlycon_scroll_up(void)
> +{
> +	unsigned long *dst, *src;
> +	u16 len;
> +	u32 i, height;
> +
> +	len = info.stride;
> +	height = info.y;
> +
> +	for (i = 0; i < height - font->height; i++) {
> +		dst = simplefb_earlycon_map(i * len, len);
> +		if (!dst)
> +			return;
> +
> +		src = simplefb_earlycon_map((i + font->height) * len, len);
> +		if (!src) {
> +			simplefb_earlycon_unmap(dst, len);
> +			return;
> +		}
> +
> +		memmove(dst, src, len);
> +
> +		simplefb_earlycon_unmap(src, len);
> +		simplefb_earlycon_unmap(dst, len);
> +	}
> +}
> +
> +static void simplefb_earlycon_write_char(u8 *dst, unsigned char c, unsigned int h)
> +{
> +	const u8 *src;
> +	int m, n, bytes;
> +	u8 x;
> +
> +	bytes = BITS_TO_BYTES(font->width);
> +	src = font->data + c * font->height * bytes + h * bytes;
> +
> +	for (m = 0; m < font->width; m++) {
> +		n = m % 8;
> +		x = *(src + m / 8);
> +		if ((x >> (7 - n)) & 1)
> +			memset(dst, 0xff, (info.depth / 8));
> +		else
> +			memset(dst, 0, (info.depth / 8));
> +		dst += (info.depth / 8);
> +	}
> +}
> +
> +static void
> +simplefb_earlycon_write(struct console *con, const char *str, unsigned int num)
> +{
> +	unsigned int len;
> +	const char *s;
> +	void *dst;
> +
> +	len = info.stride;
> +
> +	while (num) {
> +		unsigned int linemax;
> +		unsigned int h, count = 0;
> +
> +		for (s = str; *s && *s != '\n'; s++) {
> +			if (count == num)
> +				break;
> +			count++;
> +		}
> +
> +		linemax = (info.x - info.curr_x) / font->width;
> +		if (count > linemax)
> +			count = linemax;
> +
> +		for (h = 0; h < font->height; h++) {
> +			unsigned int n, x;
> +
> +			dst = simplefb_earlycon_map((info.curr_y + h) * len, len);
> +			if (!dst)
> +				return;
> +
> +			s = str;
> +			n = count;
> +			x = info.curr_x;
> +
> +			while (n-- > 0) {
> +				simplefb_earlycon_write_char(dst + (x * 4), *s, h);
> +				x += font->width;
> +				s++;
> +			}
> +
> +			simplefb_earlycon_unmap(dst, len);
> +		}
> +
> +		num -= count;
> +		info.curr_x += count * font->width;
> +		str += count;
> +
> +		if (num > 0 && *s == '\n') {
> +			info.curr_x = 0;
> +			info.curr_y += font->height;
> +			str++;
> +			num--;
> +		}
> +
> +		if (info.curr_x + font->width > info.x) {
> +			info.curr_x = 0;
> +			info.curr_y += font->height;
> +		}
> +
> +		if (info.curr_y + font->height > info.y) {
> +			u32 i;
> +
> +			info.curr_y -= font->height;
> +			simplefb_earlycon_scroll_up();
> +
> +			for (i = 0; i < font->height; i++)
> +				simplefb_earlycon_clear_scanline(info.curr_y + i);
> +		}
> +	}
> +}
> +
> +static int __init simplefb_earlycon_setup_common(struct earlycon_device *device,
> +						 const char *opt)
> +{
> +	int i;
> +
> +	info.size = info.x * info.y * (info.depth / 8);
> +
> +	font = get_default_font(info.x, info.y, -1, -1);
> +	if (!font)
> +		return -ENODEV;
> +
> +	info.curr_y = rounddown(info.y, font->height) - font->height;
> +	for (i = 0; i < (info.y - info.curr_y) / font->height; i++)
> +		simplefb_earlycon_scroll_up();
> +
> +	device->con->write = simplefb_earlycon_write;
> +	earlycon_console = device->con;
> +	return 0;
> +}
> +
> +static int __init simplefb_earlycon_setup(struct earlycon_device *device,
> +					  const char *opt)
> +{
> +	struct uart_port *port = &device->port;
> +	int ret;
> +
> +	if (!port->mapbase)
> +		return -ENODEV;
> +
> +	info.phys_base = port->mapbase;
> +
> +	ret = sscanf(device->options, "%ux%ux%u", &info.x, &info.y, &info.depth);
> +	if (ret != 3)
> +		return -ENODEV;
> +
> +	info.stride = info.x * (info.depth / 8);
> +
> +	return simplefb_earlycon_setup_common(device, opt);
> +}
> +
> +EARLYCON_DECLARE(simplefb, simplefb_earlycon_setup);
> +
> +#ifdef CONFIG_EFI_EARLYCON
> +static int __init simplefb_earlycon_setup_efi(struct earlycon_device *device,
> +					      const char *opt)
> +{
> +	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
> +		return -ENODEV;
> +
> +	info.phys_base = screen_info.lfb_base;
> +	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
> +		info.phys_base |= (u64)screen_info.ext_lfb_base << 32;
> +
> +	info.x = screen_info.lfb_width;
> +	info.y = screen_info.lfb_height;
> +	info.depth = screen_info.lfb_depth;
> +	info.stride = screen_info.lfb_linelength;
> +
> +	return simplefb_earlycon_setup_common(device, opt);
> +}
> +
> +EARLYCON_DECLARE(efifb, simplefb_earlycon_setup_efi);
> +#endif
> +
> +#ifdef CONFIG_OF_EARLY_FLATTREE
> +static int __init simplefb_earlycon_setup_of(struct earlycon_device *device,
> +					     const char *opt)
> +{
> +	struct uart_port *port = &device->port;
> +	const __be32 *val;
> +
> +	if (!port->mapbase)
> +		return -ENODEV;
> +
> +	info.phys_base = port->mapbase;
> +
> +	val = of_get_flat_dt_prop(device->offset, "width", NULL);
> +	if (!val)
> +		return -ENODEV;
> +	info.x = be32_to_cpu(*val);
> +
> +	val = of_get_flat_dt_prop(device->offset, "height", NULL);
> +	if (!val)
> +		return -ENODEV;
> +	info.y = be32_to_cpu(*val);
> +
> +	val = of_get_flat_dt_prop(device->offset, "stride", NULL);
> +	if (!val)
> +		return -ENODEV;
> +	info.stride = be32_to_cpu(*val);
> +	info.depth = (info.stride / info.x) * 8;
> +
> +	return simplefb_earlycon_setup_common(device, opt);
> +}
> +
> +OF_EARLYCON_DECLARE(simplefb, "simple-framebuffer", simplefb_earlycon_setup_of);
> +#endif
> -- 
> 2.37.0
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-09-06 21:52   ` Daniel Vetter
@ 2022-09-07  6:55     ` Thomas Zimmermann
  2022-09-07  8:22     ` Arnd Bergmann
  1 sibling, 0 replies; 15+ messages in thread
From: Thomas Zimmermann @ 2022-09-07  6:55 UTC (permalink / raw)
  To: Markuss Broks, linux-kernel, ~postmarketos/upstreaming,
	phone-devel, Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman,
	Jiri Slaby, Helge Deller, Paul E. McKenney, Borislav Petkov,
	Kees Cook, Andrew Morton, Randy Dunlap, Damien Le Moal,
	Michal Suchanek, Javier Martinez Canillas, Arnd Bergmann,
	Maarten Lankhorst, Wei Ming Chen, Bartlomiej Zolnierkiewicz,
	Tony Lindgren, linux-doc, linux-efi, linux-serial, linux-fbdev,
	dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 22762 bytes --]

Hi

Am 06.09.22 um 23:52 schrieb Daniel Vetter:
> On Sat, Aug 06, 2022 at 07:32:24PM +0300, Markuss Broks wrote:
>> Add early console support for generic linear framebuffer devices.
>> This driver supports probing from cmdline early parameters
>> or from the device-tree using information in simple-framebuffer node.
>> The EFI functionality should be retained in whole.
>> The driver was disabled on ARM because of a bug in early_ioremap
>> implementation on ARM and on IA64 because of lack of early_memremap_prot.
>>
>> Signed-off-by: Markuss Broks <markuss.broks@gmail.com>
>> ---
>>   .../admin-guide/kernel-parameters.txt         |  12 +-
>>   MAINTAINERS                                   |   5 +
>>   drivers/firmware/efi/Kconfig                  |   7 +-
>>   drivers/firmware/efi/Makefile                 |   1 -
>>   drivers/firmware/efi/earlycon.c               | 246 --------------
>>   drivers/video/console/Kconfig                 |  11 +
>>   drivers/video/console/Makefile                |   1 +
>>   drivers/video/console/earlycon.c              | 305 ++++++++++++++++++
> 
> Ok I have a more fundamental issue with this than the lack of proper patch
> splitting I mentioned in the other thread.
> 
> This is the wrong place.
> 
> drivers/video/console is about the various vt console implementations,
> which supply a struct consw to con_register_driver.
> 
> This otoh is an (early) kernel/printk console implemented using struct
> console. Totally different thing, and really shouldn't end up in
> drivers/video/console imo. Somewhere in drivers/firmware might still be
> the best place, the sysfb stuff is also there. Maybe
> drivers/firmware/sysfb_earlycon.c?

Then better use just earlycon.c in that directory. We use the sysfb_ 
prefix for code of the framebuffer devices that simpledrm and simplefb 
run on top. It would not fit well here.

Best regards
Thomas

> 
> Also patch split is still an issue here, like I and Greg already said.
> -Daniel
> 
>>   8 files changed, 332 insertions(+), 256 deletions(-)
>>   delete mode 100644 drivers/firmware/efi/earlycon.c
>>   create mode 100644 drivers/video/console/earlycon.c
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>> index 8090130b544b0701237a7b657a29c83c000a60f4..bccb1ac8978eb5cf7e2bb20834b1881b27040666 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -1281,12 +1281,9 @@
>>   			specified address. The serial port must already be
>>   			setup and configured. Options are not yet supported.
>>   
>> -		efifb,[options]
>> +		efifb
>>   			Start an early, unaccelerated console on the EFI
>> -			memory mapped framebuffer (if available). On cache
>> -			coherent non-x86 systems that use system memory for
>> -			the framebuffer, pass the 'ram' option so that it is
>> -			mapped with the correct attributes.
>> +			memory mapped framebuffer (if available).
>>   
>>   		linflex,<addr>
>>   			Use early console provided by Freescale LINFlexD UART
>> @@ -1294,6 +1291,11 @@
>>   			address must be provided, and the serial port must
>>   			already be setup and configured.
>>   
>> +		simplefb,<addr>,<width>x<height>x<bpp>
>> +			Use early console with simple framebuffer that is
>> +			pre-initialized by firmware. A valid base address,
>> +			width, height and pixel size must be provided.
>> +
>>   	earlyprintk=	[X86,SH,ARM,M68k,S390]
>>   			earlyprintk=vga
>>   			earlyprintk=sclp
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 1fc9ead83d2aa3e60ccc4cfa8ee16df09ef579bf..af8b8e289483b6a264d477145061bd0e0ba34a25 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -7033,6 +7033,11 @@ Q:	http://patchwork.linuxtv.org/project/linux-media/list/
>>   T:	git git://linuxtv.org/anttip/media_tree.git
>>   F:	drivers/media/tuners/e4000*
>>   
>> +EARLY CONSOLE FRAMEBUFFER DRIVER
>> +M:	Markuss Broks <markuss.broks@gmail.com>
>> +S:	Maintained
>> +F:	drivers/video/console/earlycon.c
>> +
>>   EARTH_PT1 MEDIA DRIVER
>>   M:	Akihiro Tsukada <tskd08@gmail.com>
>>   L:	linux-media@vger.kernel.org
>> diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
>> index 7aa4717cdcac46f91dd202f868c463388eb02735..ea76ccfb9bcd8ba44ddca06052eaa442ed6c30f7 100644
>> --- a/drivers/firmware/efi/Kconfig
>> +++ b/drivers/firmware/efi/Kconfig
>> @@ -259,10 +259,9 @@ config EFI_DISABLE_PCI_DMA
>>   	  may be used to override this option.
>>   
>>   config EFI_EARLYCON
>> -	def_bool y
>> -	depends on SERIAL_EARLYCON && !ARM && !IA64
>> -	select FONT_SUPPORT
>> -	select ARCH_USE_MEMREMAP_PROT
>> +	bool "EFI early console support"
>> +	select FB_EARLYCON
>> +	default y
>>   
>>   config EFI_CUSTOM_SSDT_OVERLAYS
>>   	bool "Load custom ACPI SSDT overlay from an EFI variable"
>> diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
>> index c02ff25dd47707090a2ab86ee4f330e467f878f5..64eea61fbb43d76ec2d5416d467dfbb9aa21bda0 100644
>> --- a/drivers/firmware/efi/Makefile
>> +++ b/drivers/firmware/efi/Makefile
>> @@ -44,6 +44,5 @@ obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
>>   riscv-obj-$(CONFIG_EFI)			:= efi-init.o riscv-runtime.o
>>   obj-$(CONFIG_RISCV)			+= $(riscv-obj-y)
>>   obj-$(CONFIG_EFI_CAPSULE_LOADER)	+= capsule-loader.o
>> -obj-$(CONFIG_EFI_EARLYCON)		+= earlycon.o
>>   obj-$(CONFIG_UEFI_CPER_ARM)		+= cper-arm.o
>>   obj-$(CONFIG_UEFI_CPER_X86)		+= cper-x86.o
>> diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c
>> deleted file mode 100644
>> index a52236e11e5f73ddea5bb1f42ca2ca7c42425dab..0000000000000000000000000000000000000000
>> --- a/drivers/firmware/efi/earlycon.c
>> +++ /dev/null
>> @@ -1,246 +0,0 @@
>> -// SPDX-License-Identifier: GPL-2.0
>> -/*
>> - * Copyright (C) 2013 Intel Corporation; author Matt Fleming
>> - */
>> -
>> -#include <linux/console.h>
>> -#include <linux/efi.h>
>> -#include <linux/font.h>
>> -#include <linux/io.h>
>> -#include <linux/kernel.h>
>> -#include <linux/serial_core.h>
>> -#include <linux/screen_info.h>
>> -
>> -#include <asm/early_ioremap.h>
>> -
>> -static const struct console *earlycon_console __initdata;
>> -static const struct font_desc *font;
>> -static u32 efi_x, efi_y;
>> -static u64 fb_base;
>> -static bool fb_wb;
>> -static void *efi_fb;
>> -
>> -/*
>> - * EFI earlycon needs to use early_memremap() to map the framebuffer.
>> - * But early_memremap() is not usable for 'earlycon=efifb keep_bootcon',
>> - * memremap() should be used instead. memremap() will be available after
>> - * paging_init() which is earlier than initcall callbacks. Thus adding this
>> - * early initcall function early_efi_map_fb() to map the whole EFI framebuffer.
>> - */
>> -static int __init efi_earlycon_remap_fb(void)
>> -{
>> -	/* bail if there is no bootconsole or it has been disabled already */
>> -	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
>> -		return 0;
>> -
>> -	efi_fb = memremap(fb_base, screen_info.lfb_size,
>> -			  fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
>> -
>> -	return efi_fb ? 0 : -ENOMEM;
>> -}
>> -early_initcall(efi_earlycon_remap_fb);
>> -
>> -static int __init efi_earlycon_unmap_fb(void)
>> -{
>> -	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
>> -	if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
>> -		memunmap(efi_fb);
>> -	return 0;
>> -}
>> -late_initcall(efi_earlycon_unmap_fb);
>> -
>> -static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
>> -{
>> -	pgprot_t fb_prot;
>> -
>> -	if (efi_fb)
>> -		return efi_fb + start;
>> -
>> -	fb_prot = fb_wb ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL);
>> -	return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
>> -}
>> -
>> -static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
>> -{
>> -	if (efi_fb)
>> -		return;
>> -
>> -	early_memunmap(addr, len);
>> -}
>> -
>> -static void efi_earlycon_clear_scanline(unsigned int y)
>> -{
>> -	unsigned long *dst;
>> -	u16 len;
>> -
>> -	len = screen_info.lfb_linelength;
>> -	dst = efi_earlycon_map(y*len, len);
>> -	if (!dst)
>> -		return;
>> -
>> -	memset(dst, 0, len);
>> -	efi_earlycon_unmap(dst, len);
>> -}
>> -
>> -static void efi_earlycon_scroll_up(void)
>> -{
>> -	unsigned long *dst, *src;
>> -	u16 len;
>> -	u32 i, height;
>> -
>> -	len = screen_info.lfb_linelength;
>> -	height = screen_info.lfb_height;
>> -
>> -	for (i = 0; i < height - font->height; i++) {
>> -		dst = efi_earlycon_map(i*len, len);
>> -		if (!dst)
>> -			return;
>> -
>> -		src = efi_earlycon_map((i + font->height) * len, len);
>> -		if (!src) {
>> -			efi_earlycon_unmap(dst, len);
>> -			return;
>> -		}
>> -
>> -		memmove(dst, src, len);
>> -
>> -		efi_earlycon_unmap(src, len);
>> -		efi_earlycon_unmap(dst, len);
>> -	}
>> -}
>> -
>> -static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h)
>> -{
>> -	const u32 color_black = 0x00000000;
>> -	const u32 color_white = 0x00ffffff;
>> -	const u8 *src;
>> -	int m, n, bytes;
>> -	u8 x;
>> -
>> -	bytes = BITS_TO_BYTES(font->width);
>> -	src = font->data + c * font->height * bytes + h * bytes;
>> -
>> -	for (m = 0; m < font->width; m++) {
>> -		n = m % 8;
>> -		x = *(src + m / 8);
>> -		if ((x >> (7 - n)) & 1)
>> -			*dst = color_white;
>> -		else
>> -			*dst = color_black;
>> -		dst++;
>> -	}
>> -}
>> -
>> -static void
>> -efi_earlycon_write(struct console *con, const char *str, unsigned int num)
>> -{
>> -	struct screen_info *si;
>> -	unsigned int len;
>> -	const char *s;
>> -	void *dst;
>> -
>> -	si = &screen_info;
>> -	len = si->lfb_linelength;
>> -
>> -	while (num) {
>> -		unsigned int linemax;
>> -		unsigned int h, count = 0;
>> -
>> -		for (s = str; *s && *s != '\n'; s++) {
>> -			if (count == num)
>> -				break;
>> -			count++;
>> -		}
>> -
>> -		linemax = (si->lfb_width - efi_x) / font->width;
>> -		if (count > linemax)
>> -			count = linemax;
>> -
>> -		for (h = 0; h < font->height; h++) {
>> -			unsigned int n, x;
>> -
>> -			dst = efi_earlycon_map((efi_y + h) * len, len);
>> -			if (!dst)
>> -				return;
>> -
>> -			s = str;
>> -			n = count;
>> -			x = efi_x;
>> -
>> -			while (n-- > 0) {
>> -				efi_earlycon_write_char(dst + x*4, *s, h);
>> -				x += font->width;
>> -				s++;
>> -			}
>> -
>> -			efi_earlycon_unmap(dst, len);
>> -		}
>> -
>> -		num -= count;
>> -		efi_x += count * font->width;
>> -		str += count;
>> -
>> -		if (num > 0 && *s == '\n') {
>> -			efi_x = 0;
>> -			efi_y += font->height;
>> -			str++;
>> -			num--;
>> -		}
>> -
>> -		if (efi_x + font->width > si->lfb_width) {
>> -			efi_x = 0;
>> -			efi_y += font->height;
>> -		}
>> -
>> -		if (efi_y + font->height > si->lfb_height) {
>> -			u32 i;
>> -
>> -			efi_y -= font->height;
>> -			efi_earlycon_scroll_up();
>> -
>> -			for (i = 0; i < font->height; i++)
>> -				efi_earlycon_clear_scanline(efi_y + i);
>> -		}
>> -	}
>> -}
>> -
>> -static int __init efi_earlycon_setup(struct earlycon_device *device,
>> -				     const char *opt)
>> -{
>> -	struct screen_info *si;
>> -	u16 xres, yres;
>> -	u32 i;
>> -
>> -	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
>> -		return -ENODEV;
>> -
>> -	fb_base = screen_info.lfb_base;
>> -	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
>> -		fb_base |= (u64)screen_info.ext_lfb_base << 32;
>> -
>> -	fb_wb = opt && !strcmp(opt, "ram");
>> -
>> -	si = &screen_info;
>> -	xres = si->lfb_width;
>> -	yres = si->lfb_height;
>> -
>> -	/*
>> -	 * efi_earlycon_write_char() implicitly assumes a framebuffer with
>> -	 * 32 bits per pixel.
>> -	 */
>> -	if (si->lfb_depth != 32)
>> -		return -ENODEV;
>> -
>> -	font = get_default_font(xres, yres, -1, -1);
>> -	if (!font)
>> -		return -ENODEV;
>> -
>> -	efi_y = rounddown(yres, font->height) - font->height;
>> -	for (i = 0; i < (yres - efi_y) / font->height; i++)
>> -		efi_earlycon_scroll_up();
>> -
>> -	device->con->write = efi_earlycon_write;
>> -	earlycon_console = device->con;
>> -	return 0;
>> -}
>> -EARLYCON_DECLARE(efifb, efi_earlycon_setup);
>> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
>> index 40c50fa2dd70c33a1549141b15e6cba721352d2d..8052507e058fce37f5a51058e58ae2eb10d9669a 100644
>> --- a/drivers/video/console/Kconfig
>> +++ b/drivers/video/console/Kconfig
>> @@ -69,6 +69,17 @@ config DUMMY_CONSOLE_ROWS
>>   	  monitor.
>>   	  Select 25 if you use a 640x480 resolution by default.
>>   
>> +config FB_EARLYCON
>> +	bool "Generic framebuffer early console"
>> +	depends on SERIAL_EARLYCON && !ARM && !IA64
>> +	select FONT_SUPPORT
>> +	select ARCH_USE_MEMREMAP_PROT
>> +	help
>> +	  Say Y here if you want early console support for firmware established
>> +	  linear framebuffer. Unless you are using EFI framebuffer, you need to
>> +	  specify framebuffer geometry and address in device-tree or in kernel
>> +	  command line.
>> +
>>   config FRAMEBUFFER_CONSOLE
>>   	bool "Framebuffer Console support"
>>   	depends on FB && !UML
>> diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
>> index db07b784bd2ccdcbffde933926ed5cee2bbbc7d4..7818faee587fc9c40b429617cfa224c0ccbc557c 100644
>> --- a/drivers/video/console/Makefile
>> +++ b/drivers/video/console/Makefile
>> @@ -9,4 +9,5 @@ obj-$(CONFIG_STI_CONSOLE)         += sticon.o sticore.o
>>   obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
>>   obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
>>   
>> +obj-$(CONFIG_FB_EARLYCON)         += earlycon.o
>>   obj-$(CONFIG_FB_STI)              += sticore.o
>> diff --git a/drivers/video/console/earlycon.c b/drivers/video/console/earlycon.c
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..54436587e3db90034652dcc144669dca91b863d5
>> --- /dev/null
>> +++ b/drivers/video/console/earlycon.c
>> @@ -0,0 +1,305 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2013 Intel Corporation; author Matt Fleming
>> + * Copyright (C) 2022 Markuss Broks <markuss.broks@gmail.com>
>> + */
>> +
>> +#include <asm/early_ioremap.h>
>> +#include <linux/console.h>
>> +#include <linux/efi.h>
>> +#include <linux/font.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mm.h>
>> +#include <linux/of.h>
>> +#include <linux/of_fdt.h>
>> +#include <linux/serial_core.h>
>> +#include <linux/screen_info.h>
>> +
>> +struct fb_earlycon {
>> +	u32 x, y, curr_x, curr_y, depth, stride;
>> +	size_t size;
>> +	phys_addr_t phys_base;
>> +	void __iomem *virt_base;
>> +};
>> +
>> +static const struct console *earlycon_console __initconst;
>> +static struct fb_earlycon info;
>> +static const struct font_desc *font;
>> +
>> +static int __init simplefb_earlycon_remap_fb(void)
>> +{
>> +	unsigned long mapping;
>> +	/* bail if there is no bootconsole or it has been disabled already */
>> +	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
>> +		return 0;
>> +
>> +	if (region_intersects(info.phys_base, info.size,
>> +			      IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) == REGION_INTERSECTS)		
>> +		mapping = MEMREMAP_WB;
>> +	else
>> +		mapping = MEMREMAP_WC;
>> +
>> +	info.virt_base = memremap(info.phys_base, info.size, mapping);
>> +
>> +	return info.virt_base ? 0 : -ENOMEM;
>> +}
>> +early_initcall(simplefb_earlycon_remap_fb);
>> +
>> +static int __init simplefb_earlycon_unmap_fb(void)
>> +{
>> +	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
>> +	if (info.virt_base && !(earlycon_console->flags & CON_ENABLED))
>> +		memunmap(info.virt_base);
>> +	return 0;
>> +}
>> +late_initcall(simplefb_earlycon_unmap_fb);
>> +
>> +static __ref void *simplefb_earlycon_map(unsigned long start, unsigned long len)
>> +{
>> +	pgprot_t fb_prot;
>> +
>> +	if (info.virt_base)
>> +		return info.virt_base + start;
>> +
>> +	fb_prot = PAGE_KERNEL;
>> +	return early_memremap_prot(info.phys_base + start, len, pgprot_val(fb_prot));
>> +}
>> +
>> +static __ref void simplefb_earlycon_unmap(void *addr, unsigned long len)
>> +{
>> +	if (info.virt_base)
>> +		return;
>> +
>> +	early_memunmap(addr, len);
>> +}
>> +
>> +static void simplefb_earlycon_clear_scanline(unsigned int y)
>> +{
>> +	unsigned long *dst;
>> +	u16 len;
>> +
>> +	len = info.stride;
>> +	dst = simplefb_earlycon_map(y * len, len);
>> +	if (!dst)
>> +		return;
>> +
>> +	memset(dst, 0, len);
>> +	simplefb_earlycon_unmap(dst, len);
>> +}
>> +
>> +static void simplefb_earlycon_scroll_up(void)
>> +{
>> +	unsigned long *dst, *src;
>> +	u16 len;
>> +	u32 i, height;
>> +
>> +	len = info.stride;
>> +	height = info.y;
>> +
>> +	for (i = 0; i < height - font->height; i++) {
>> +		dst = simplefb_earlycon_map(i * len, len);
>> +		if (!dst)
>> +			return;
>> +
>> +		src = simplefb_earlycon_map((i + font->height) * len, len);
>> +		if (!src) {
>> +			simplefb_earlycon_unmap(dst, len);
>> +			return;
>> +		}
>> +
>> +		memmove(dst, src, len);
>> +
>> +		simplefb_earlycon_unmap(src, len);
>> +		simplefb_earlycon_unmap(dst, len);
>> +	}
>> +}
>> +
>> +static void simplefb_earlycon_write_char(u8 *dst, unsigned char c, unsigned int h)
>> +{
>> +	const u8 *src;
>> +	int m, n, bytes;
>> +	u8 x;
>> +
>> +	bytes = BITS_TO_BYTES(font->width);
>> +	src = font->data + c * font->height * bytes + h * bytes;
>> +
>> +	for (m = 0; m < font->width; m++) {
>> +		n = m % 8;
>> +		x = *(src + m / 8);
>> +		if ((x >> (7 - n)) & 1)
>> +			memset(dst, 0xff, (info.depth / 8));
>> +		else
>> +			memset(dst, 0, (info.depth / 8));
>> +		dst += (info.depth / 8);
>> +	}
>> +}
>> +
>> +static void
>> +simplefb_earlycon_write(struct console *con, const char *str, unsigned int num)
>> +{
>> +	unsigned int len;
>> +	const char *s;
>> +	void *dst;
>> +
>> +	len = info.stride;
>> +
>> +	while (num) {
>> +		unsigned int linemax;
>> +		unsigned int h, count = 0;
>> +
>> +		for (s = str; *s && *s != '\n'; s++) {
>> +			if (count == num)
>> +				break;
>> +			count++;
>> +		}
>> +
>> +		linemax = (info.x - info.curr_x) / font->width;
>> +		if (count > linemax)
>> +			count = linemax;
>> +
>> +		for (h = 0; h < font->height; h++) {
>> +			unsigned int n, x;
>> +
>> +			dst = simplefb_earlycon_map((info.curr_y + h) * len, len);
>> +			if (!dst)
>> +				return;
>> +
>> +			s = str;
>> +			n = count;
>> +			x = info.curr_x;
>> +
>> +			while (n-- > 0) {
>> +				simplefb_earlycon_write_char(dst + (x * 4), *s, h);
>> +				x += font->width;
>> +				s++;
>> +			}
>> +
>> +			simplefb_earlycon_unmap(dst, len);
>> +		}
>> +
>> +		num -= count;
>> +		info.curr_x += count * font->width;
>> +		str += count;
>> +
>> +		if (num > 0 && *s == '\n') {
>> +			info.curr_x = 0;
>> +			info.curr_y += font->height;
>> +			str++;
>> +			num--;
>> +		}
>> +
>> +		if (info.curr_x + font->width > info.x) {
>> +			info.curr_x = 0;
>> +			info.curr_y += font->height;
>> +		}
>> +
>> +		if (info.curr_y + font->height > info.y) {
>> +			u32 i;
>> +
>> +			info.curr_y -= font->height;
>> +			simplefb_earlycon_scroll_up();
>> +
>> +			for (i = 0; i < font->height; i++)
>> +				simplefb_earlycon_clear_scanline(info.curr_y + i);
>> +		}
>> +	}
>> +}
>> +
>> +static int __init simplefb_earlycon_setup_common(struct earlycon_device *device,
>> +						 const char *opt)
>> +{
>> +	int i;
>> +
>> +	info.size = info.x * info.y * (info.depth / 8);
>> +
>> +	font = get_default_font(info.x, info.y, -1, -1);
>> +	if (!font)
>> +		return -ENODEV;
>> +
>> +	info.curr_y = rounddown(info.y, font->height) - font->height;
>> +	for (i = 0; i < (info.y - info.curr_y) / font->height; i++)
>> +		simplefb_earlycon_scroll_up();
>> +
>> +	device->con->write = simplefb_earlycon_write;
>> +	earlycon_console = device->con;
>> +	return 0;
>> +}
>> +
>> +static int __init simplefb_earlycon_setup(struct earlycon_device *device,
>> +					  const char *opt)
>> +{
>> +	struct uart_port *port = &device->port;
>> +	int ret;
>> +
>> +	if (!port->mapbase)
>> +		return -ENODEV;
>> +
>> +	info.phys_base = port->mapbase;
>> +
>> +	ret = sscanf(device->options, "%ux%ux%u", &info.x, &info.y, &info.depth);
>> +	if (ret != 3)
>> +		return -ENODEV;
>> +
>> +	info.stride = info.x * (info.depth / 8);
>> +
>> +	return simplefb_earlycon_setup_common(device, opt);
>> +}
>> +
>> +EARLYCON_DECLARE(simplefb, simplefb_earlycon_setup);
>> +
>> +#ifdef CONFIG_EFI_EARLYCON
>> +static int __init simplefb_earlycon_setup_efi(struct earlycon_device *device,
>> +					      const char *opt)
>> +{
>> +	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
>> +		return -ENODEV;
>> +
>> +	info.phys_base = screen_info.lfb_base;
>> +	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
>> +		info.phys_base |= (u64)screen_info.ext_lfb_base << 32;
>> +
>> +	info.x = screen_info.lfb_width;
>> +	info.y = screen_info.lfb_height;
>> +	info.depth = screen_info.lfb_depth;
>> +	info.stride = screen_info.lfb_linelength;
>> +
>> +	return simplefb_earlycon_setup_common(device, opt);
>> +}
>> +
>> +EARLYCON_DECLARE(efifb, simplefb_earlycon_setup_efi);
>> +#endif
>> +
>> +#ifdef CONFIG_OF_EARLY_FLATTREE
>> +static int __init simplefb_earlycon_setup_of(struct earlycon_device *device,
>> +					     const char *opt)
>> +{
>> +	struct uart_port *port = &device->port;
>> +	const __be32 *val;
>> +
>> +	if (!port->mapbase)
>> +		return -ENODEV;
>> +
>> +	info.phys_base = port->mapbase;
>> +
>> +	val = of_get_flat_dt_prop(device->offset, "width", NULL);
>> +	if (!val)
>> +		return -ENODEV;
>> +	info.x = be32_to_cpu(*val);
>> +
>> +	val = of_get_flat_dt_prop(device->offset, "height", NULL);
>> +	if (!val)
>> +		return -ENODEV;
>> +	info.y = be32_to_cpu(*val);
>> +
>> +	val = of_get_flat_dt_prop(device->offset, "stride", NULL);
>> +	if (!val)
>> +		return -ENODEV;
>> +	info.stride = be32_to_cpu(*val);
>> +	info.depth = (info.stride / info.x) * 8;
>> +
>> +	return simplefb_earlycon_setup_common(device, opt);
>> +}
>> +
>> +OF_EARLYCON_DECLARE(simplefb, "simple-framebuffer", simplefb_earlycon_setup_of);
>> +#endif
>> -- 
>> 2.37.0
>>
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem
  2022-09-06 21:52   ` Daniel Vetter
  2022-09-07  6:55     ` Thomas Zimmermann
@ 2022-09-07  8:22     ` Arnd Bergmann
  1 sibling, 0 replies; 15+ messages in thread
From: Arnd Bergmann @ 2022-09-07  8:22 UTC (permalink / raw)
  To: Daniel Vetter, Markuss Broks
  Cc: linux-kernel, ~postmarketos/upstreaming, phone-devel,
	Jonathan Corbet, Ard Biesheuvel, Greg Kroah-Hartman, Jiri Slaby,
	Helge Deller, Paul E. McKenney, Borislav Petkov, Kees Cook,
	Andrew Morton, Randy Dunlap, Damien Le Moal, Thomas Zimmermann,
	Michal Suchanek, Javier Martinez Canillas, Maarten Lankhorst,
	Wei Ming Chen, Bartlomiej Zolnierkiewicz, Tony Lindgren,
	linux-doc, linux-efi, linux-serial, linux-fbdev, dri-devel

On Tue, Sep 6, 2022, at 11:52 PM, Daniel Vetter wrote:
> On Sat, Aug 06, 2022 at 07:32:24PM +0300, Markuss Broks wrote:
>
> Ok I have a more fundamental issue with this than the lack of proper patch
> splitting I mentioned in the other thread.
>
> This is the wrong place.
>
> drivers/video/console is about the various vt console implementations,
> which supply a struct consw to con_register_driver.

You are right, that was my mistake. The original patch was for
drivers/video/fbdev/, and I suggested moving it out of there because
it does not depend on the fbdev subsystem, but clearly my suggestions
of drivers/video/console was equally wrong.

> This otoh is an (early) kernel/printk console implemented using struct
> console. Totally different thing, and really shouldn't end up in
> drivers/video/console imo. Somewhere in drivers/firmware might still be
> the best place, the sysfb stuff is also there. Maybe
> drivers/firmware/sysfb_earlycon.c?

drivers/firmware/ is better but doesn't sound great to me either,
since one important thing the patch does is to not make it depend
on EFI firmware or BIOS style screen_info any more. 

Maybe drivers/tty/earlycon_simplefb.c would work better, keeping
it close to the earlycon base support in drivers/tty/serial/,
the vt console and the old simplefb driver/, without tying to too
closely to fbdev of UEFI.

     Arnd

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-09-07  9:06 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-06 16:32 [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Markuss Broks
2022-08-06 16:32 ` [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name Markuss Broks
2022-08-06 16:56   ` Andy Shevchenko
2022-08-08  1:28   ` kernel test robot
2022-08-08 15:55   ` Rob Herring
2022-08-06 16:32 ` [PATCH v2 2/3] drivers: serial: earlycon: Pass device-tree node Markuss Broks
2022-08-06 16:32 ` [PATCH v2 3/3] efi: earlycon: Add support for generic framebuffers and move to console subsystem Markuss Broks
2022-08-06 21:37   ` Andy Shevchenko
2022-08-07 13:16   ` kernel test robot
2022-08-14  0:01   ` kernel test robot
2022-08-14  7:04   ` kernel test robot
2022-09-06 21:52   ` Daniel Vetter
2022-09-07  6:55     ` Thomas Zimmermann
2022-09-07  8:22     ` Arnd Bergmann
2022-09-06 16:54 ` [PATCH v2 0/3] Add generic framebuffer support to EFI earlycon driver Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).