There is no way to implement a proper tstc() with the semihosting console, so for now, let's add it as output-only console. Currently, the console is only usable when not running as EFI payload to avoid duplicate output when it's exposed over regular EFI protocol. In the future, we could make it opt-in by providing a way to create the semihosting device from shell. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- drivers/serial/Kconfig | 8 ++++++ drivers/serial/Makefile | 1 + drivers/serial/serial_semihosting.c | 44 +++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 drivers/serial/serial_semihosting.c diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 60b0e5f1dc1f..20fe26439048 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -151,4 +151,12 @@ config SERIAL_SBI Select this option if you are building barebox for a RISCV platform that implements a serial over SBI. +config SERIAL_SEMIHOSTING + bool "Semihosting console" + depends on SEMIHOSTING + help + Select this option if you want barebox to be able to output to + the semihosting console implemented by a debugger or emulator. + This console can not be read from. + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 4887e24ee1c1..f4ccb249003a 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_SERIAL_SIFIVE) += serial_sifive.o obj-$(CONFIG_SERIAL_SBI) += serial_sbi.o obj-$(CONFIG_SOC_LITEX) += serial_litex.o +obj-$(CONFIG_SERIAL_SEMIHOSTING) += serial_semihosting.o diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c new file mode 100644 index 000000000000..d495b07f11ca --- /dev/null +++ b/drivers/serial/serial_semihosting.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <console.h> +#include <asm/semihosting.h> +#include <efi/efi-mode.h> + +static void smh_serial_putc(struct console_device *cdev, char ch) +{ + semihosting_writec(ch); +} + +static int smh_serial_probe(struct device *dev) +{ + struct console_device *cdev; + + cdev = xzalloc(sizeof(*cdev)); + + cdev->dev = dev; + cdev->putc = smh_serial_putc; + + return console_register(cdev); +} + +static struct driver serial_semihosting_driver = { + .name = "serial_semihosting", + .probe = smh_serial_probe, +}; + +static int __init serial_semihosting_register(void) +{ + if (!efi_is_payload()) { + struct device *dev; + int ret; + + dev = device_alloc("serial_semihosting", 0); + + ret = platform_device_register(dev); + if (ret) + return ret; + } + + return platform_driver_register(&serial_semihosting_driver); +} +console_initcall(serial_semihosting_register); -- 2.39.2