From a609353e82fd757b7635d18ed6a0828fff657d59 Mon Sep 17 00:00:00 2001
From: Mark Kettenis <kettenis@openbsd.org>
Date: Tue, 19 Apr 2022 21:20:31 +0200
Subject: [PATCH] arm: apple: Point stdout-path to framebuffer when keyboard
 present

Unless you have a spare Apple Silicon machine, getting access to
the serial port on Apple Silicon machines requires special
hardware. Given that most machines come with a built-in screen
the framebuffer is likely to be the most convenient output device
for most users. While U-Boot will output to both serial and
framebuffer, OSes might not. Therefore set stdout-path to point
at /chosen/framebuffer when a keyboard is connected to the machine.

This behaviour can be overridden by setting the "stdout" variable
in the U-Boot environment. I addition to that keep the serial
console as the default when running under the m1n1 hypervisor.
The m1n1 hypervisor virtualizes the serial port such that it
can be easily accessed from any other machine with a USB port.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
Reviewed-by: Janne Grunau <j@jannau.net>
Tested-by: Janne Grunau <j@jannau.net>
---
 arch/arm/Kconfig            |  1 +
 arch/arm/mach-apple/board.c | 40 +++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3243bd0ee0..57946f61fa 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1021,6 +1021,7 @@ config ARCH_APPLE
 	select DM_VIDEO
 	select IOMMU
 	select LINUX_KERNEL_IMAGE_HEADER
+	select OF_BOARD_SETUP
 	select OF_CONTROL
 	select PINCTRL
 	select POSITION_INDEPENDENT
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
index ffc1301cf5..1525a9edee 100644
--- a/arch/arm/mach-apple/board.c
+++ b/arch/arm/mach-apple/board.c
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dm/uclass-internal.h>
 #include <efi_loader.h>
 #include <lmb.h>
 
@@ -461,3 +462,42 @@ int board_late_init(void)
 
 	return 0;
 }
+
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+	struct udevice *dev;
+	const char *stdoutname;
+	int node, ret;
+
+	/*
+	 * Modify the "stdout-path" property under "/chosen" to point
+	 * at "/chosen/framebuffer if a keyboard is available and
+	 * we're not running under the m1n1 hypervisor.
+	 * Developers can override this behaviour by dropping
+	 * "vidconsole" from the "stdout" environment variable.
+	 */
+
+	/* EL1 means we're running under the m1n1 hypervisor. */
+	if (current_el() == 1)
+		return 0;
+
+	ret = uclass_find_device(UCLASS_KEYBOARD, 0, &dev);
+	if (ret < 0)
+		return 0;
+
+	stdoutname = env_get("stdout");
+	if (!stdoutname || !strstr(stdoutname, "vidconsole"))
+		return 0;
+
+	/* Make sure we actually have a framebuffer. */
+	node = fdt_path_offset(blob, "/chosen/framebuffer");
+	if (node < 0 || !fdtdec_get_is_enabled(blob, node))
+		return 0;
+
+	node = fdt_path_offset(blob, "/chosen");
+	if (node < 0)
+		return 0;
+	fdt_setprop_string(blob, node, "stdout-path", "/chosen/framebuffer");
+
+	return 0;
+}
-- 
2.39.5