[PATCH v2 1/3] lib: Add common semihosting library
Sean Anderson
seanga2 at gmail.com
Sat Sep 17 19:39:51 CEST 2022
On 9/16/22 04:12, Kautuk Consul wrote:
> 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 <kconsul at ventanamicro.com>
> ---
> arch/arm/Kconfig | 2 +
> arch/arm/lib/semihosting.c | 179 +----------------------------------
> include/semihosting.h | 11 +++
> lib/Kconfig | 3 +
> lib/Makefile | 2 +
> lib/semihosting.c | 186 +++++++++++++++++++++++++++++++++++++
> 6 files changed, 205 insertions(+), 178 deletions(-)
> create mode 100644 lib/semihosting.c
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 82cd456f51..81440ff7ea 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -415,6 +415,7 @@ config ARM_SMCCC
>
> config SEMIHOSTING
> bool "Support ARM semihosting"
> + select LIB_SEMIHOSTING
> help
> Semihosting is a method for a target to communicate with a host
> debugger. It uses special instructions which the debugger will trap
> @@ -437,6 +438,7 @@ config SEMIHOSTING_FALLBACK
>
> config SPL_SEMIHOSTING
> bool "Support ARM semihosting in SPL"
> + select LIB_SEMIHOSTING
> depends on SPL
> help
> Semihosting is a method for a target to communicate with a host
Sorry if I wasn't clear enough last time. Both the code and these Kconfigs should be moved to a common location.
> diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c
> index 01d652a6b8..41bc5cd62b 100644
> --- a/arch/arm/lib/semihosting.c
> +++ b/arch/arm/lib/semihosting.c
> @@ -13,22 +13,10 @@
> #include <log.h>
> #include <semihosting.h>
>
> -#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 +29,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..f883676b91 100644
> --- a/include/semihosting.h
> +++ b/include/semihosting.h
> @@ -17,6 +17,17 @@
> #define SMH_T32_SVC 0xDFAB
> #define SMH_T32_HLT 0xBABC
>
> +/**
> + * semh_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..286d316110 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -71,6 +71,9 @@ config HAVE_PRIVATE_LIBGCC
> config LIB_UUID
> bool
>
> +config LIB_SEMIHOSTING
> + bool
> +
> config PRINTF
> bool
> default y
> diff --git a/lib/Makefile b/lib/Makefile
> index e3deb15287..96be8fe7e9 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_LIB_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 <sean.anderson at seco.com>
> + * Copyright 2014 Broadcom Corporation
> + */
> +
> +#include <common.h>
> +#include <log.h>
> +#include <semihosting.h>
> +
> +#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);
> +}
The rest looks fine.
--Sean
More information about the U-Boot
mailing list