forked from OP-TEE/optee_os
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
core: kernel: Add semihosting functions
Semihosting is a mechanism that enables target to communicate and use I/O facilities on a host computer which is running a debugger, such as GDB. The I/O facilities include character {read|write} {from|to} the semihosting host side console or a file. In other words, OP-TEE OS can output log to the host side console or the host side file, if there is a semihosting host and OP-TEE OS requests the semihosting operations to that host. If CFG_SEMIHOSTING is enabled, some semihosting functions will be compiled into OP-TEE kernel, including: - semihosting_sys_readc() - semihosting_sys_writec() - semihosting_open() - semihosting_read() - semihosting_write() - semihosting_close() Note that the architectures which support semihosting should provide their implementation of __do_semihosting(), which performs semihosting instruction to raise the semihosting request. Signed-off-by: Alvin Chang <[email protected]> Reviewed-by: Etienne Carriere <[email protected]> Reviewed-by: Jerome Forissier <[email protected]> Reviewed-by: Jens Wiklander <[email protected]>
- Loading branch information
1 parent
f459d3c
commit 7e2a103
Showing
4 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* SPDX-License-Identifier: BSD-2-Clause */ | ||
/* | ||
* Copyright (c) 2024 Andes Technology Corporation | ||
*/ | ||
#ifndef __KERNEL_SEMIHOSTING_H | ||
#define __KERNEL_SEMIHOSTING_H | ||
|
||
#include <stddef.h> | ||
#include <stdint.h> | ||
#include <sys/fcntl.h> | ||
#include <util.h> | ||
|
||
/* Perform architecture-specific semihosting instructions. */ | ||
uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg); | ||
|
||
char semihosting_sys_readc(void); | ||
void semihosting_sys_writec(char c); | ||
int semihosting_open(const char *fname, int flags); | ||
size_t semihosting_read(int fd, void *ptr, size_t len); | ||
size_t semihosting_write(int fd, const void *ptr, size_t len); | ||
int semihosting_close(int fd); | ||
|
||
#endif /* __KERNEL_SEMIHOSTING_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// SPDX-License-Identifier: BSD-2-Clause | ||
/* | ||
* Copyright (c) 2024 Andes Technology Corporation | ||
*/ | ||
|
||
#include <kernel/semihosting.h> | ||
#include <string.h> | ||
|
||
/* | ||
* ARM and RISC-V have defined the standard way to perform | ||
* the semihosting operations. | ||
* - Operation codes and open modes are identical. | ||
* - The implementation of the low-level __do_semihosting() call is | ||
* architecture-specific. | ||
* - Arm semihosting interface: | ||
* https://developer.arm.com/documentation/dui0471/g/Semihosting/The-semihosting-interface | ||
* - RISC-V semihosting interface: | ||
* https://github.com/riscv-non-isa/riscv-semihosting/blob/main/binary-interface.adoc | ||
*/ | ||
|
||
/* An integer that specifies the file open mode */ | ||
enum semihosting_open_mode { | ||
SEMIHOSTING_OPEN_R = 0, | ||
SEMIHOSTING_OPEN_RB = 1, | ||
SEMIHOSTING_OPEN_RX = 2, | ||
SEMIHOSTING_OPEN_RXB = 3, | ||
SEMIHOSTING_OPEN_W = 4, | ||
SEMIHOSTING_OPEN_WB = 5, | ||
SEMIHOSTING_OPEN_WX = 6, | ||
SEMIHOSTING_OPEN_WXB = 7, | ||
SEMIHOSTING_OPEN_A = 8, | ||
SEMIHOSTING_OPEN_AB = 9, | ||
SEMIHOSTING_OPEN_AX = 10, | ||
SEMIHOSTING_OPEN_AXB = 11, | ||
}; | ||
|
||
enum semihosting_sys_ops { | ||
/* Regular operations */ | ||
SEMIHOSTING_SYS_OPEN = 0x01, | ||
SEMIHOSTING_SYS_CLOSE = 0x02, | ||
SEMIHOSTING_SYS_WRITEC = 0x03, | ||
SEMIHOSTING_SYS_WRITE = 0x05, | ||
SEMIHOSTING_SYS_READ = 0x06, | ||
SEMIHOSTING_SYS_READC = 0x07, | ||
}; | ||
|
||
struct semihosting_param_t { | ||
uintptr_t param0; | ||
uintptr_t param1; | ||
uintptr_t param2; | ||
}; | ||
|
||
/** | ||
* @brief Read one character byte from the semihosting host debug terminal | ||
* | ||
* @retval the character read from the semihosting host | ||
*/ | ||
char semihosting_sys_readc(void) | ||
{ | ||
return __do_semihosting(SEMIHOSTING_SYS_READC, 0); | ||
} | ||
|
||
/** | ||
* @brief Write one character byte to the semihosting host debug terminal | ||
* @param c: the character to be written | ||
*/ | ||
void semihosting_sys_writec(char c) | ||
{ | ||
__do_semihosting(SEMIHOSTING_SYS_WRITEC, (uintptr_t)&c); | ||
} | ||
|
||
/** | ||
* @brief Request the semihosting host to open a file on the host system | ||
* @param fname: the path or name of the file | ||
* @param flags: sys/fcntl.h standard flags to open the file with | ||
* | ||
* @retval nonzero if OK, or -1 if fails | ||
*/ | ||
int semihosting_open(const char *fname, int flags) | ||
{ | ||
int semi_open_flags = 0; | ||
const int flags_mask = O_RDONLY | O_WRONLY | O_RDWR | | ||
O_CREAT | O_TRUNC | O_APPEND; | ||
struct semihosting_param_t arg = { }; | ||
|
||
/* Convert the flags to semihosting open. */ | ||
switch (flags & flags_mask) { | ||
case O_RDONLY: /* 'r' */ | ||
semi_open_flags = SEMIHOSTING_OPEN_R; | ||
break; | ||
case O_WRONLY | O_CREAT | O_TRUNC: /* 'w' */ | ||
semi_open_flags = SEMIHOSTING_OPEN_W; | ||
break; | ||
case O_WRONLY | O_CREAT | O_APPEND: /* 'a' */ | ||
semi_open_flags = SEMIHOSTING_OPEN_A; | ||
break; | ||
case O_RDWR: /* 'r+' */ | ||
semi_open_flags = SEMIHOSTING_OPEN_RX; | ||
break; | ||
case O_RDWR | O_CREAT | O_TRUNC: /* 'w+' */ | ||
semi_open_flags = SEMIHOSTING_OPEN_WX; | ||
break; | ||
case O_RDWR | O_CREAT | O_APPEND: /* 'a+' */ | ||
semi_open_flags = SEMIHOSTING_OPEN_AX; | ||
break; | ||
default: | ||
return -1; | ||
} | ||
|
||
arg.param0 = (uintptr_t)fname; | ||
arg.param1 = semi_open_flags; | ||
arg.param2 = strlen(fname); | ||
|
||
return (int)__do_semihosting(SEMIHOSTING_SYS_OPEN, (uintptr_t)&arg); | ||
} | ||
|
||
/** | ||
* @brief Read data from a file on the semihosting host system | ||
* @param fd: a handle for a file previously opened | ||
* @param ptr: pointer to a buffer | ||
* @param len: the number of bytes to read to the buffer from the file | ||
* | ||
* @retval zero if OK, the same value as @len if fails, smaller value than @len | ||
* for partial success | ||
*/ | ||
size_t semihosting_read(int fd, void *ptr, size_t len) | ||
{ | ||
struct semihosting_param_t arg = { | ||
.param0 = fd, | ||
.param1 = (uintptr_t)ptr, | ||
.param2 = len | ||
}; | ||
|
||
return __do_semihosting(SEMIHOSTING_SYS_READ, (uintptr_t)&arg); | ||
} | ||
|
||
/** | ||
* @brief Write data into a file on the semihosting host system | ||
* @param fd: a handle for a file previously opened | ||
* @param ptr: pointer to a buffer | ||
* @param len: the number of bytes to be written from the buffer to the file | ||
* | ||
* @retval zero if OK, otherwise the number of bytes that are not written | ||
*/ | ||
size_t semihosting_write(int fd, const void *ptr, size_t len) | ||
{ | ||
struct semihosting_param_t arg = { | ||
.param0 = fd, | ||
.param1 = (uintptr_t)ptr, | ||
.param2 = len | ||
}; | ||
|
||
return __do_semihosting(SEMIHOSTING_SYS_WRITE, (uintptr_t)&arg); | ||
} | ||
|
||
/** | ||
* @brief Close a file on the semihosting host system | ||
* @param fd: a handle for a file previously opened | ||
* | ||
* @retval zero if OK, -1 if fails | ||
*/ | ||
int semihosting_close(int fd) | ||
{ | ||
struct semihosting_param_t arg = { | ||
.param0 = fd, | ||
}; | ||
|
||
return (int)__do_semihosting(SEMIHOSTING_SYS_CLOSE, (uintptr_t)&arg); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters