1 /*
2  * Copyright (c) 2022, Commonwealth Scientific and Industrial Research
3  * Organisation (CSIRO) ABN 41 687 119 230.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * Based on the ARM semihosting API from:
8  * https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst
9  *
10  * RISC-V semihosting also follows these conventions:
11  * https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
12  */
13 
14 /**
15  * @file
16  *
17  * @brief public Semihosting APIs based on ARM definitions.
18  * @defgroup semihost Semihosting APIs
19  * @ingroup os_services
20  * @{
21  */
22 
23 #ifndef ZEPHYR_INCLUDE_ARCH_COMMON_SEMIHOST_H_
24 #define ZEPHYR_INCLUDE_ARCH_COMMON_SEMIHOST_H_
25 
26 /** @brief Semihosting instructions */
27 enum semihost_instr {
28 	/*
29 	 * File I/O operations
30 	 */
31 
32 	/** Open a file or stream on the host system. */
33 	SEMIHOST_OPEN   = 0x01,
34 	/** Check whether a file is associated with a stream/terminal */
35 	SEMIHOST_ISTTY  = 0x09,
36 	/** Write to a file or stream. */
37 	SEMIHOST_WRITE  = 0x05,
38 	/** Read from a file at the current cursor position. */
39 	SEMIHOST_READ   = 0x06,
40 	/** Closes a file on the host which has been opened by SEMIHOST_OPEN. */
41 	SEMIHOST_CLOSE  = 0x02,
42 	/** Get the length of a file. */
43 	SEMIHOST_FLEN   = 0x0C,
44 	/** Set the file cursor to a given position in a file. */
45 	SEMIHOST_SEEK   = 0x0A,
46 	/** Get a temporary absolute file path to create a temporary file. */
47 	SEMIHOST_TMPNAM = 0x0D,
48 	/** Remove a file on the host system. Possibly insecure! */
49 	SEMIHOST_REMOVE = 0x0E,
50 	/** Rename a file on the host system. Possibly insecure! */
51 	SEMIHOST_RENAME = 0x0F,
52 
53 	/*
54 	 * Terminal I/O operations
55 	 */
56 
57 	/** Write one character to the debug terminal. */
58 	SEMIHOST_WRITEC         = 0x03,
59 	/** Write a NULL terminated string to the debug terminal. */
60 	SEMIHOST_WRITE0         = 0x04,
61 	/** Read one character from the debug terminal. */
62 	SEMIHOST_READC          = 0x07,
63 
64 	/*
65 	 * Time operations
66 	 */
67 	SEMIHOST_CLOCK          = 0x10,
68 	SEMIHOST_ELAPSED        = 0x30,
69 	SEMIHOST_TICKFREQ       = 0x31,
70 	SEMIHOST_TIME           = 0x11,
71 
72 	/*
73 	 * System/Misc. operations
74 	 */
75 
76 	/** Retrieve the errno variable from semihosting operations. */
77 	SEMIHOST_ERRNO          = 0x13,
78 	/** Get commandline parameters for the application to run with */
79 	SEMIHOST_GET_CMDLINE    = 0x15,
80 	SEMIHOST_HEAPINFO       = 0x16,
81 	SEMIHOST_ISERROR        = 0x08,
82 	SEMIHOST_SYSTEM         = 0x12
83 };
84 
85 /**
86  * @brief Modes to open a file with
87  *
88  * Behaviour corresponds to equivalent fopen strings.
89  * i.e. SEMIHOST_OPEN_RB_PLUS == "rb+"
90  */
91 enum semihost_open_mode {
92 	SEMIHOST_OPEN_R         = 0,
93 	SEMIHOST_OPEN_RB        = 1,
94 	SEMIHOST_OPEN_R_PLUS    = 2,
95 	SEMIHOST_OPEN_RB_PLUS   = 3,
96 	SEMIHOST_OPEN_W         = 4,
97 	SEMIHOST_OPEN_WB        = 5,
98 	SEMIHOST_OPEN_W_PLUS    = 6,
99 	SEMIHOST_OPEN_WB_PLUS   = 7,
100 	SEMIHOST_OPEN_A         = 8,
101 	SEMIHOST_OPEN_AB        = 9,
102 	SEMIHOST_OPEN_A_PLUS    = 10,
103 	SEMIHOST_OPEN_AB_PLUS   = 11,
104 };
105 
106 /**
107  * @brief Manually execute a semihosting instruction
108  *
109  * @param instr instruction code to run
110  * @param args instruction specific arguments
111  *
112  * @return integer return code of instruction
113  */
114 long semihost_exec(enum semihost_instr instr, void *args);
115 
116 /**
117  * @brief Read a byte from the console
118  *
119  * @return char byte read from the console.
120  */
121 char semihost_poll_in(void);
122 
123 /**
124  * @brief Write a byte to the console
125  *
126  * @param c byte to write to console
127  */
128 void semihost_poll_out(char c);
129 
130 /**
131  * @brief Open a file on the host system
132  *
133  * @param path file path to open. Can be absolute or relative to current
134  *             directory of the running process.
135  * @param mode value from @ref semihost_open_mode.
136  *
137  * @retval handle positive handle on success.
138  * @retval -1 on failure.
139  */
140 long semihost_open(const char *path, long mode);
141 
142 /**
143  * @brief Close a file
144  *
145  * @param fd handle returned by @ref semihost_open.
146  *
147  * @retval 0 on success.
148  * @retval -1 on failure.
149  */
150 long semihost_close(long fd);
151 
152 /**
153  * @brief Query the size of a file
154  *
155  * @param fd handle returned by @ref semihost_open.
156  *
157  * @retval positive file size on success.
158  * @retval -1 on failure.
159  */
160 long semihost_flen(long fd);
161 
162 /**
163  * @brief Seeks to an absolute position in a file.
164  *
165  * @param fd handle returned by @ref semihost_open.
166  * @param offset offset from the start of the file in bytes.
167  *
168  * @retval 0 on success.
169  * @retval -errno negative error code on failure.
170  */
171 long semihost_seek(long fd, long offset);
172 
173 /**
174  * @brief Read the contents of a file into a buffer.
175  *
176  * @param fd handle returned by @ref semihost_open.
177  * @param buf buffer to read data into.
178  * @param len number of bytes to read.
179  *
180  * @retval read number of bytes read on success.
181  * @retval -errno negative error code on failure.
182  */
183 long semihost_read(long fd, void *buf, long len);
184 
185 /**
186  * @brief Write the contents of a buffer into a file.
187  *
188  * @param fd handle returned by @ref semihost_open.
189  * @param buf buffer to write data from.
190  * @param len number of bytes to write.
191  *
192  * @retval 0 on success.
193  * @retval -errno negative error code on failure.
194  */
195 long semihost_write(long fd, const void *buf, long len);
196 
197 /**
198  * @}
199  */
200 
201 #endif /* ZEPHYR_INCLUDE_ARCH_COMMON_SEMIHOST_H_ */
202