mirror of
				https://github.com/riscv-software-src/opensbi
				synced 2025-11-04 05:50:22 +00:00 
			
		
		
		
	We fix the following semihosting compile error observed using LLVM:
lib/utils/serial/semihosting.c:158:12: error: result of comparison of constant -1 with expression of type 'char' is always true [-Werror,-Wtautological-constant-out-of-range-compare]
                ret = ch > -1 ? ch : -1;
                      ~~ ^ ~~
Fixes: 7f09fba86e43 ("lib: utils/serial: add semihosting support")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
		
	
			
		
			
				
	
	
		
			179 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * SPDX-License-Identifier: BSD-2-Clause
 | 
						|
 *
 | 
						|
 * Copyright (c) 2022 Ventana Micro Systems Inc.
 | 
						|
 *
 | 
						|
 * Authors:
 | 
						|
 *   Anup Patel <apatel@ventanamicro.com>
 | 
						|
 *   Kautuk Consul <kconsul@ventanamicro.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include <sbi/sbi_console.h>
 | 
						|
#include <sbi/sbi_string.h>
 | 
						|
#include <sbi/sbi_error.h>
 | 
						|
#include <sbi_utils/serial/semihosting.h>
 | 
						|
 | 
						|
#define SYSOPEN     0x01
 | 
						|
#define SYSWRITEC   0x03
 | 
						|
#define SYSREAD     0x06
 | 
						|
#define SYSREADC    0x07
 | 
						|
#define SYSERRNO	0x13
 | 
						|
 | 
						|
static long semihosting_trap(int sysnum, void *addr)
 | 
						|
{
 | 
						|
	register int ret asm ("a0") = sysnum;
 | 
						|
	register void *param0 asm ("a1") = addr;
 | 
						|
 | 
						|
	asm volatile (
 | 
						|
		"	.align 4\n"
 | 
						|
		"	.option push\n"
 | 
						|
		"	.option norvc\n"
 | 
						|
 | 
						|
		"	slli zero, zero, 0x1f\n"
 | 
						|
		"	ebreak\n"
 | 
						|
		"	srai zero, zero, 7\n"
 | 
						|
 | 
						|
		"	.option pop\n"
 | 
						|
		: "+r" (ret) : "r" (param0) : "memory");
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
static bool _semihosting_enabled = true;
 | 
						|
static bool try_semihosting = true;
 | 
						|
 | 
						|
bool semihosting_enabled(void)
 | 
						|
{
 | 
						|
	register int ret asm ("a0") = SYSERRNO;
 | 
						|
	register void *param0 asm ("a1") = NULL;
 | 
						|
	unsigned long tmp = 0;
 | 
						|
 | 
						|
	if (!try_semihosting)
 | 
						|
		return _semihosting_enabled;
 | 
						|
 | 
						|
	asm volatile (
 | 
						|
		"	.align 4\n"
 | 
						|
		"	.option push\n"
 | 
						|
		"	.option norvc\n"
 | 
						|
 | 
						|
		"	j _semihost_test_vector_next\n"
 | 
						|
		"	.align 4\n"
 | 
						|
		"_semihost_test_vector:\n"
 | 
						|
		"	csrr %[en], mepc\n"
 | 
						|
		"	addi %[en], %[en], 4\n"
 | 
						|
		"	csrw mepc, %[en]\n"
 | 
						|
		"	add %[en], zero, zero\n"
 | 
						|
		"	mret\n"
 | 
						|
		"_semihost_test_vector_next:\n"
 | 
						|
 | 
						|
		"	la %[tmp], _semihost_test_vector\n"
 | 
						|
		"	csrrw %[tmp], mtvec, %[tmp]\n"
 | 
						|
		"	.align 4\n"
 | 
						|
		"	slli zero, zero, 0x1f\n"
 | 
						|
		"	ebreak\n"
 | 
						|
		"	srai zero, zero, 7\n"
 | 
						|
		"	csrw mtvec, %[tmp]\n"
 | 
						|
 | 
						|
		"	.option pop\n"
 | 
						|
		: [tmp] "+r" (tmp), [en] "+r" (_semihosting_enabled),
 | 
						|
		  [ret] "+r" (ret)
 | 
						|
		: "r" (param0) : "memory");
 | 
						|
 | 
						|
	try_semihosting = false;
 | 
						|
	return _semihosting_enabled;
 | 
						|
}
 | 
						|
 | 
						|
static int semihosting_errno(void)
 | 
						|
{
 | 
						|
	long ret = semihosting_trap(SYSERRNO, NULL);
 | 
						|
 | 
						|
	if (ret > 0)
 | 
						|
		return -ret;
 | 
						|
	return SBI_EIO;
 | 
						|
}
 | 
						|
 | 
						|
static int semihosting_infd = SBI_ENODEV;
 | 
						|
 | 
						|
static long semihosting_open(const char *fname, enum semihosting_open_mode mode)
 | 
						|
{
 | 
						|
	long fd;
 | 
						|
	struct semihosting_open_s {
 | 
						|
		const char *fname;
 | 
						|
		unsigned long mode;
 | 
						|
		size_t len;
 | 
						|
	} open;
 | 
						|
 | 
						|
	open.fname = fname;
 | 
						|
	open.len = sbi_strlen(fname);
 | 
						|
	open.mode = mode;
 | 
						|
 | 
						|
	/* Open the file on the host */
 | 
						|
	fd = semihosting_trap(SYSOPEN, &open);
 | 
						|
	if (fd == -1)
 | 
						|
		return semihosting_errno();
 | 
						|
	return fd;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * struct semihosting_rdwr_s - Arguments for read and write
 | 
						|
 * @fd: A file descriptor returned from semihosting_open()
 | 
						|
 * @memp: Pointer to a buffer of memory of at least @len bytes
 | 
						|
 * @len: The number of bytes to read or write
 | 
						|
 */
 | 
						|
struct semihosting_rdwr_s {
 | 
						|
	long fd;
 | 
						|
	void *memp;
 | 
						|
	size_t len;
 | 
						|
};
 | 
						|
 | 
						|
static long semihosting_read(long fd, void *memp, size_t len)
 | 
						|
{
 | 
						|
	long ret;
 | 
						|
	struct semihosting_rdwr_s read;
 | 
						|
 | 
						|
	read.fd = fd;
 | 
						|
	read.memp = memp;
 | 
						|
	read.len = len;
 | 
						|
 | 
						|
	ret = semihosting_trap(SYSREAD, &read);
 | 
						|
	if (ret < 0)
 | 
						|
		return semihosting_errno();
 | 
						|
	return len - ret;
 | 
						|
}
 | 
						|
 | 
						|
/* clang-format on */
 | 
						|
 | 
						|
static void semihosting_putc(char ch)
 | 
						|
{
 | 
						|
	semihosting_trap(SYSWRITEC, &ch);
 | 
						|
}
 | 
						|
 | 
						|
static int semihosting_getc(void)
 | 
						|
{
 | 
						|
	char ch = 0;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (semihosting_infd < 0)  {
 | 
						|
		ret = semihosting_trap(SYSREADC, NULL);
 | 
						|
		ret = ret < 0 ? -1 : ret;
 | 
						|
	} else
 | 
						|
		ret = semihosting_read(semihosting_infd, &ch, 1) > 0 ? ch : -1;
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
static struct sbi_console_device semihosting_console = {
 | 
						|
	.name = "semihosting",
 | 
						|
	.console_putc = semihosting_putc,
 | 
						|
	.console_getc = semihosting_getc
 | 
						|
};
 | 
						|
 | 
						|
int semihosting_init(void)
 | 
						|
{
 | 
						|
	semihosting_infd = semihosting_open(":tt", MODE_READ);
 | 
						|
 | 
						|
	sbi_console_set_device(&semihosting_console);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 |