From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AD6E4C54EE9 for ; Mon, 19 Sep 2022 11:23:13 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EAE4484C22; Mon, 19 Sep 2022 13:23:09 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=ventanamicro.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=ventanamicro.com header.i=@ventanamicro.com header.b="aofCQyMF"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DCE0D84C34; Mon, 19 Sep 2022 13:23:07 +0200 (CEST) Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C779A84C21 for ; Mon, 19 Sep 2022 13:23:02 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=ventanamicro.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=kconsul@ventanamicro.com Received: by mail-pf1-x431.google.com with SMTP id a29so4130068pfk.5 for ; Mon, 19 Sep 2022 04:23:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=ubXqH4uoMGkv6TYgZNXwIIMcD8Tz4DSC4auG7SOnVSA=; b=aofCQyMFXtpbLbBUrpHNjz9WFCK6lhq0Tw6hzBRqiTNxLyIZbKTZ1Yw0OKM/a10+v7 6DMzMc6OdEpVdaag2WgRaZ0PoYv3xu/SucuLl4WtVdaDh8XmIYvlCkRsq7mTIoB5by1g yMB5bZr3dthu60DaGJEGJ3boWPeLL/8FGQ7N+ILGcq6UqWb6f07lzu2Xsk+VF7GcHw8z qIlyahaKbOMPCBQWy6ipzjibPkCJnMqIzaPq/j9OcKMhGryuDB2Xdw/UPHrizwcL3lY1 S6tE7nPPDZWwP880RW2uKfHURD85h+iiJDX7I4dopM1l+Y8WykBi6Ot81T6fthbsVM5g tsLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=ubXqH4uoMGkv6TYgZNXwIIMcD8Tz4DSC4auG7SOnVSA=; b=LasO+r2FRMU+MiOpxMqyW3Ei9n+kWQCl1vooi1fymJoVBoQ9ssHVCz5PfcEHqDpPFW FGD6Nq4FY9h/KU8YBMPH+QpUxuGMWhO3Dj5HLJxXOh1Mq+C2dgfwdJRg0FJQzfhYbgpW SsBu+ECwnEd8IY9tm6EDSwYVek5jMLILg2WjhGTptge89m8WXMK/d7+P6GvIcvHfTOtw 56hCDfEyyRXax+0kNgIgpjoeEpzjKkEXBmwGizuMQ0Kl8knIeEplBjyDxJaCYdH+XLvA nX4bnTEHF5Q7drXjECAuhDhl/KEKU5/D2C8OElhf4dI0w9PR+aCd3BORtWJ3o7i1mZa6 SWFg== X-Gm-Message-State: ACrzQf0Gby4/f8HSNji7bBdsOxIeTrj9lO8ngjSjlvXToCKk6VNMz5GQ pYFsG9kHb428jvuGlgbQGeF56Q== X-Google-Smtp-Source: AMsMyM4Atp+q3+/oSVchtVKQt6hda6ORcAKIp9aWES+dyNiJPMKa/IU+kdY90/ETNJCtP84lRlfzUw== X-Received: by 2002:a05:6a00:21c2:b0:52b:ff44:6680 with SMTP id t2-20020a056a0021c200b0052bff446680mr18074795pfj.57.1663586580940; Mon, 19 Sep 2022 04:23:00 -0700 (PDT) Received: from performance-PowerEdge-T440.. ([103.97.165.210]) by smtp.googlemail.com with ESMTPSA id k29-20020aa7973d000000b00537ff911a89sm20101415pfg.105.2022.09.19.04.22.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Sep 2022 04:23:00 -0700 (PDT) From: Kautuk Consul To: Bharat Gooty , Rayagonda Kokatanur , Sean Anderson , Rick Chen , Leo , Simon Glass , Heinrich Schuchardt , Ilias Apalodimas , Alexandru Gagniuc , Philippe Reynes , Rasmus Villemoes , Stefan Roese , Loic Poulain , Bin Meng Cc: u-boot@lists.denx.de, Kautuk Consul Subject: [PATCH v3 1/3] lib: Add common semihosting library Date: Mon, 19 Sep 2022 16:52:41 +0530 Message-Id: <20220919112243.2758726-2-kconsul@ventanamicro.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220919112243.2758726-1-kconsul@ventanamicro.com> References: <20220919112243.2758726-1-kconsul@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean We factor out the arch-independent parts of the ARM semihosting implementation as a common library so that it can be shared with RISC-V. Signed-off-by: Kautuk Consul --- arch/arm/Kconfig | 46 --------- arch/arm/lib/semihosting.c | 181 +----------------------------------- include/semihosting.h | 11 +++ lib/Kconfig | 46 +++++++++ lib/Makefile | 2 + lib/semihosting.c | 186 +++++++++++++++++++++++++++++++++++++ 6 files changed, 246 insertions(+), 226 deletions(-) create mode 100644 lib/semihosting.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 82cd456f51..ee6a9fadd9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -413,52 +413,6 @@ config ARM_SMCCC This should be enabled if U-Boot needs to communicate with system firmware (for example, PSCI) according to SMCCC. -config SEMIHOSTING - bool "Support ARM semihosting" - help - Semihosting is a method for a target to communicate with a host - debugger. It uses special instructions which the debugger will trap - on and interpret. This allows U-Boot to read/write files, print to - the console, and execute arbitrary commands on the host system. - - Enabling this option will add support for reading and writing files - on the host system. If you don't have a debugger attached then trying - to do this will likely cause U-Boot to hang. Say 'n' if you are unsure. - -config SEMIHOSTING_FALLBACK - bool "Recover gracefully when semihosting fails" - depends on SEMIHOSTING && ARM64 - default y - help - Normally, if U-Boot makes a semihosting call and no debugger is - attached, then it will panic due to a synchronous abort - exception. This config adds an exception handler which will allow - U-Boot to recover. Say 'y' if unsure. - -config SPL_SEMIHOSTING - bool "Support ARM semihosting in SPL" - depends on SPL - help - Semihosting is a method for a target to communicate with a host - debugger. It uses special instructions which the debugger will trap - on and interpret. This allows U-Boot to read/write files, print to - the console, and execute arbitrary commands on the host system. - - Enabling this option will add support for reading and writing files - on the host system. If you don't have a debugger attached then trying - to do this will likely cause U-Boot to hang. Say 'n' if you are unsure. - -config SPL_SEMIHOSTING_FALLBACK - bool "Recover gracefully when semihosting fails in SPL" - depends on SPL_SEMIHOSTING && ARM64 - select ARMV8_SPL_EXCEPTION_VECTORS - default y - help - Normally, if U-Boot makes a semihosting call and no debugger is - attached, then it will panic due to a synchronous abort - exception. This config adds an exception handler which will allow - U-Boot to recover. Say 'y' if unsure. - config SYS_THUMB_BUILD bool "Build U-Boot using the Thumb instruction set" depends on !ARM64 diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index 01d652a6b8..11e7b85ee6 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -10,25 +10,11 @@ * available in silicon now, fastmodel usage makes less sense for them. */ #include -#include -#include - -#define SYSOPEN 0x01 -#define SYSCLOSE 0x02 -#define SYSWRITEC 0x03 -#define SYSWRITE0 0x04 -#define SYSWRITE 0x05 -#define SYSREAD 0x06 -#define SYSREADC 0x07 -#define SYSISERROR 0x08 -#define SYSSEEK 0x0A -#define SYSFLEN 0x0C -#define SYSERRNO 0x13 /* * Call the handler */ -static noinline long smh_trap(unsigned int sysnum, void *addr) +long smh_trap(unsigned int sysnum, void *addr) { register long result asm("r0"); #if defined(CONFIG_ARM64) @@ -41,168 +27,3 @@ static noinline long smh_trap(unsigned int sysnum, void *addr) #endif return result; } - -#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) -static bool _semihosting_enabled = true; -static bool try_semihosting = true; - -bool semihosting_enabled(void) -{ - if (try_semihosting) { - smh_trap(SYSERRNO, NULL); - try_semihosting = false; - } - - return _semihosting_enabled; -} - -void disable_semihosting(void) -{ - _semihosting_enabled = false; -} -#endif - -/** - * smh_errno() - Read the host's errno - * - * This gets the value of the host's errno and negates it. The host's errno may - * or may not be set, so only call this function if a previous semihosting call - * has failed. - * - * Return: a negative error value - */ -static int smh_errno(void) -{ - long ret = smh_trap(SYSERRNO, NULL); - - if (ret > 0 && ret < INT_MAX) - return -ret; - return -EIO; -} - -long smh_open(const char *fname, enum smh_open_mode mode) -{ - long fd; - struct smh_open_s { - const char *fname; - unsigned long mode; - size_t len; - } open; - - debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode); - - open.fname = fname; - open.len = strlen(fname); - open.mode = mode; - - /* Open the file on the host */ - fd = smh_trap(SYSOPEN, &open); - if (fd == -1) - return smh_errno(); - return fd; -} - -/** - * struct smg_rdwr_s - Arguments for read and write - * @fd: A file descriptor returned from smh_open() - * @memp: Pointer to a buffer of memory of at least @len bytes - * @len: The number of bytes to read or write - */ -struct smh_rdwr_s { - long fd; - void *memp; - size_t len; -}; - -long smh_read(long fd, void *memp, size_t len) -{ - long ret; - struct smh_rdwr_s read; - - debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len); - - read.fd = fd; - read.memp = memp; - read.len = len; - - ret = smh_trap(SYSREAD, &read); - if (ret < 0) - return smh_errno(); - return len - ret; -} - -long smh_write(long fd, const void *memp, size_t len, ulong *written) -{ - long ret; - struct smh_rdwr_s write; - - debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len); - - write.fd = fd; - write.memp = (void *)memp; - write.len = len; - - ret = smh_trap(SYSWRITE, &write); - *written = len - ret; - if (ret) - return smh_errno(); - return 0; -} - -long smh_close(long fd) -{ - long ret; - - debug("%s: fd %ld\n", __func__, fd); - - ret = smh_trap(SYSCLOSE, &fd); - if (ret == -1) - return smh_errno(); - return 0; -} - -long smh_flen(long fd) -{ - long ret; - - debug("%s: fd %ld\n", __func__, fd); - - ret = smh_trap(SYSFLEN, &fd); - if (ret == -1) - return smh_errno(); - return ret; -} - -long smh_seek(long fd, long pos) -{ - long ret; - struct smh_seek_s { - long fd; - long pos; - } seek; - - debug("%s: fd %ld pos %ld\n", __func__, fd, pos); - - seek.fd = fd; - seek.pos = pos; - - ret = smh_trap(SYSSEEK, &seek); - if (ret) - return smh_errno(); - return 0; -} - -int smh_getc(void) -{ - return smh_trap(SYSREADC, NULL); -} - -void smh_putc(char ch) -{ - smh_trap(SYSWRITEC, &ch); -} - -void smh_puts(const char *s) -{ - smh_trap(SYSWRITE0, (char *)s); -} diff --git a/include/semihosting.h b/include/semihosting.h index f1f73464e4..4e844cbad8 100644 --- a/include/semihosting.h +++ b/include/semihosting.h @@ -17,6 +17,17 @@ #define SMH_T32_SVC 0xDFAB #define SMH_T32_HLT 0xBABC +/** + * smh_trap() - ARCH-specific semihosting call. + * + * Semihosting library/driver can use this function to do the + * actual semihosting calls. + * + * Return: Error code defined by semihosting spec. + */ + +long smh_trap(unsigned int sysnum, void *addr); + #if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) /** * semihosting_enabled() - Determine whether semihosting is supported diff --git a/lib/Kconfig b/lib/Kconfig index 6121c80dc8..97920e7552 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -71,6 +71,52 @@ config HAVE_PRIVATE_LIBGCC config LIB_UUID bool +config SEMIHOSTING + bool "Support semihosting" + help + Semihosting is a method for a target to communicate with a host + debugger. It uses special instructions which the debugger will trap + on and interpret. This allows U-Boot to read/write files, print to + the console, and execute arbitrary commands on the host system. + + Enabling this option will add support for reading and writing files + on the host system. If you don't have a debugger attached then trying + to do this will likely cause U-Boot to hang. Say 'n' if you are unsure. + +config SEMIHOSTING_FALLBACK + bool "Recover gracefully when semihosting fails" + depends on SEMIHOSTING && ARM64 + default y + help + Normally, if U-Boot makes a semihosting call and no debugger is + attached, then it will panic due to a synchronous abort + exception. This config adds an exception handler which will allow + U-Boot to recover. Say 'y' if unsure. + +config SPL_SEMIHOSTING + bool "Support semihosting in SPL" + depends on SPL + help + Semihosting is a method for a target to communicate with a host + debugger. It uses special instructions which the debugger will trap + on and interpret. This allows U-Boot to read/write files, print to + the console, and execute arbitrary commands on the host system. + + Enabling this option will add support for reading and writing files + on the host system. If you don't have a debugger attached then trying + to do this will likely cause U-Boot to hang. Say 'n' if you are unsure. + +config SPL_SEMIHOSTING_FALLBACK + bool "Recover gracefully when semihosting fails in SPL" + depends on SPL_SEMIHOSTING && ARM64 + select ARMV8_SPL_EXCEPTION_VECTORS + default y + help + Normally, if U-Boot makes a semihosting call and no debugger is + attached, then it will panic due to a synchronous abort + exception. This config adds an exception handler which will allow + U-Boot to recover. Say 'y' if unsure. + config PRINTF bool default y diff --git a/lib/Makefile b/lib/Makefile index e3deb15287..134c4319cd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -145,6 +145,8 @@ obj-y += date.o obj-y += rtc-lib.o obj-$(CONFIG_LIB_ELF) += elf.o +obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o + # # Build a fast OID lookup registry from include/linux/oid_registry.h # diff --git a/lib/semihosting.c b/lib/semihosting.c new file mode 100644 index 0000000000..831774e356 --- /dev/null +++ b/lib/semihosting.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sean Anderson + * Copyright 2014 Broadcom Corporation + */ + +#include +#include +#include + +#define SYSOPEN 0x01 +#define SYSCLOSE 0x02 +#define SYSWRITEC 0x03 +#define SYSWRITE0 0x04 +#define SYSWRITE 0x05 +#define SYSREAD 0x06 +#define SYSREADC 0x07 +#define SYSISERROR 0x08 +#define SYSSEEK 0x0A +#define SYSFLEN 0x0C +#define SYSERRNO 0x13 + +#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) +static bool _semihosting_enabled = true; +static bool try_semihosting = true; + +bool semihosting_enabled(void) +{ + if (try_semihosting) { + smh_trap(SYSERRNO, NULL); + try_semihosting = false; + } + + return _semihosting_enabled; +} + +void disable_semihosting(void) +{ + _semihosting_enabled = false; +} +#endif + +/** + * smh_errno() - Read the host's errno + * + * This gets the value of the host's errno and negates it. The host's errno may + * or may not be set, so only call this function if a previous semihosting call + * has failed. + * + * Return: a negative error value + */ +static int smh_errno(void) +{ + long ret = smh_trap(SYSERRNO, NULL); + + if (ret > 0 && ret < INT_MAX) + return -ret; + return -EIO; +} + +long smh_open(const char *fname, enum smh_open_mode mode) +{ + long fd; + struct smh_open_s { + const char *fname; + unsigned long mode; + size_t len; + } open; + + debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode); + + open.fname = fname; + open.len = strlen(fname); + open.mode = mode; + + /* Open the file on the host */ + fd = smh_trap(SYSOPEN, &open); + if (fd == -1) + return smh_errno(); + return fd; +} + +/** + * struct smg_rdwr_s - Arguments for read and write + * @fd: A file descriptor returned from smh_open() + * @memp: Pointer to a buffer of memory of at least @len bytes + * @len: The number of bytes to read or write + */ +struct smh_rdwr_s { + long fd; + void *memp; + size_t len; +}; + +long smh_read(long fd, void *memp, size_t len) +{ + long ret; + struct smh_rdwr_s read; + + debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len); + + read.fd = fd; + read.memp = memp; + read.len = len; + + ret = smh_trap(SYSREAD, &read); + if (ret < 0) + return smh_errno(); + return len - ret; +} + +long smh_write(long fd, const void *memp, size_t len, ulong *written) +{ + long ret; + struct smh_rdwr_s write; + + debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len); + + write.fd = fd; + write.memp = (void *)memp; + write.len = len; + + ret = smh_trap(SYSWRITE, &write); + *written = len - ret; + if (ret) + return smh_errno(); + return 0; +} + +long smh_close(long fd) +{ + long ret; + + debug("%s: fd %ld\n", __func__, fd); + + ret = smh_trap(SYSCLOSE, &fd); + if (ret == -1) + return smh_errno(); + return 0; +} + +long smh_flen(long fd) +{ + long ret; + + debug("%s: fd %ld\n", __func__, fd); + + ret = smh_trap(SYSFLEN, &fd); + if (ret == -1) + return smh_errno(); + return ret; +} + +long smh_seek(long fd, long pos) +{ + long ret; + struct smh_seek_s { + long fd; + long pos; + } seek; + + debug("%s: fd %ld pos %ld\n", __func__, fd, pos); + + seek.fd = fd; + seek.pos = pos; + + ret = smh_trap(SYSSEEK, &seek); + if (ret) + return smh_errno(); + return 0; +} + +int smh_getc(void) +{ + return smh_trap(SYSREADC, NULL); +} + +void smh_putc(char ch) +{ + smh_trap(SYSWRITEC, &ch); +} + +void smh_puts(const char *s) +{ + smh_trap(SYSWRITE0, (char *)s); +} -- 2.34.1