9fe76bafef29c8ce8d5d86168c6b63ed44abd0f6
[fw/openocd] / src / target / semihosting_common.h
1 /***************************************************************************
2  *   Copyright (C) 2018 by Liviu Ionescu                                   *
3  *   <ilg@livius.net>                                                      *
4  *                                                                         *
5  *   Copyright (C) 2009 by Marvell Technology Group Ltd.                   *
6  *   Written by Nicolas Pitre <nico@marvell.com>                           *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
20  ***************************************************************************/
21
22 #ifndef OPENOCD_TARGET_SEMIHOSTING_COMMON_H
23 #define OPENOCD_TARGET_SEMIHOSTING_COMMON_H
24
25 #include <stdint.h>
26 #include <stdbool.h>
27 #include <time.h>
28 #include "helper/replacements.h"
29 #include <server/server.h>
30
31 /*
32  * According to:
33  * "Semihosting for AArch32 and AArch64, Release 2.0"
34  * https://static.docs.arm.com/100863/0200/semihosting.pdf
35  * from ARM Ltd.
36  *
37  * The available semihosting operation numbers passed in R0 are allocated
38  * as follows:
39  * - 0x00-0x31 Used by ARM.
40  * - 0x32-0xFF Reserved for future use by ARM.
41  * - 0x100-0x1FF Reserved for user applications. These are not used by ARM.
42  *   However, if you are writing your own SVC operations, you are advised
43  *   to use a different SVC number rather than using the semihosted
44  *   SVC number and these operation type numbers.
45  * - 0x200-0xFFFFFFFF Undefined and currently unused. It is recommended
46  *   that you do not use these.
47  */
48
49 enum semihosting_operation_numbers {
50         /*
51          * ARM semihosting operations, in lexicographic order.
52          */
53         SEMIHOSTING_ENTER_SVC = 0x17,   /* DEPRECATED */
54
55         SEMIHOSTING_SYS_CLOSE = 0x02,
56         SEMIHOSTING_SYS_CLOCK = 0x10,
57         SEMIHOSTING_SYS_ELAPSED = 0x30,
58         SEMIHOSTING_SYS_ERRNO = 0x13,
59         SEMIHOSTING_SYS_EXIT = 0x18,
60         SEMIHOSTING_SYS_EXIT_EXTENDED = 0x20,
61         SEMIHOSTING_SYS_FLEN = 0x0C,
62         SEMIHOSTING_SYS_GET_CMDLINE = 0x15,
63         SEMIHOSTING_SYS_HEAPINFO = 0x16,
64         SEMIHOSTING_SYS_ISERROR = 0x08,
65         SEMIHOSTING_SYS_ISTTY = 0x09,
66         SEMIHOSTING_SYS_OPEN = 0x01,
67         SEMIHOSTING_SYS_READ = 0x06,
68         SEMIHOSTING_SYS_READC = 0x07,
69         SEMIHOSTING_SYS_REMOVE = 0x0E,
70         SEMIHOSTING_SYS_RENAME = 0x0F,
71         SEMIHOSTING_SYS_SEEK = 0x0A,
72         SEMIHOSTING_SYS_SYSTEM = 0x12,
73         SEMIHOSTING_SYS_TICKFREQ = 0x31,
74         SEMIHOSTING_SYS_TIME = 0x11,
75         SEMIHOSTING_SYS_TMPNAM = 0x0D,
76         SEMIHOSTING_SYS_WRITE = 0x05,
77         SEMIHOSTING_SYS_WRITEC = 0x03,
78         SEMIHOSTING_SYS_WRITE0 = 0x04,
79         SEMIHOSTING_USER_CMD_0x100 = 0x100, /* First user cmd op code */
80         SEMIHOSTING_USER_CMD_0x107 = 0x107, /* Last supported user cmd op code */
81         SEMIHOSTING_USER_CMD_0x1FF = 0x1FF, /* Last user cmd op code */
82 };
83
84 /** Maximum allowed Tcl command segment length in bytes*/
85 #define SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH (1024 * 1024)
86
87 /*
88  * Codes used by SEMIHOSTING_SYS_EXIT (formerly
89  * SEMIHOSTING_REPORT_EXCEPTION).
90  * On 64-bits, the exit code is passed explicitly.
91  */
92 enum semihosting_reported_exceptions {
93         /* On 32 bits, use it for exit(0) */
94         ADP_STOPPED_APPLICATION_EXIT = ((2 << 16) + 38),
95         /* On 32 bits, use it for exit(1) */
96         ADP_STOPPED_RUN_TIME_ERROR = ((2 << 16) + 35),
97 };
98
99 enum semihosting_redirect_config {
100         SEMIHOSTING_REDIRECT_CFG_NONE,
101         SEMIHOSTING_REDIRECT_CFG_DEBUG,
102         SEMIHOSTING_REDIRECT_CFG_STDIO,
103         SEMIHOSTING_REDIRECT_CFG_ALL,
104 };
105
106 enum semihosting_result {
107         SEMIHOSTING_NONE,               /* Not halted for a semihosting call. */
108         SEMIHOSTING_HANDLED,    /* Call handled, and target was resumed. */
109         SEMIHOSTING_WAITING,    /* Call handled, target is halted waiting until we can resume. */
110         SEMIHOSTING_ERROR               /* Something went wrong. */
111 };
112
113 struct target;
114
115 /*
116  * A pointer to this structure was added to the target structure.
117  */
118 struct semihosting {
119
120         /** A flag reporting whether semihosting is active. */
121         bool is_active;
122
123         /** Semihosting STDIO file descriptors */
124         int stdin_fd, stdout_fd, stderr_fd;
125
126         /** redirection configuration, NONE by default */
127         enum semihosting_redirect_config redirect_cfg;
128
129         /** Handle to redirect semihosting print via tcp */
130         struct connection *tcp_connection;
131
132         /** A flag reporting whether semihosting fileio is active. */
133         bool is_fileio;
134
135         /** A flag reporting whether semihosting fileio operation is active. */
136         bool hit_fileio;
137
138         /** Most are resumable, except the two exit calls. */
139         bool is_resumable;
140
141         /**
142          * When SEMIHOSTING_SYS_EXIT is called outside a debug session,
143          * things are simple, the openocd process calls exit() and passes
144          * the value returned by the target.
145          * When SEMIHOSTING_SYS_EXIT is called during a debug session,
146          * by default execution returns to the debugger, leaving the
147          * debugger in a HALT state, similar to the state entered when
148          * encountering a break.
149          * In some use cases, it is useful to have SEMIHOSTING_SYS_EXIT
150          * return normally, as any semihosting call, and do not break
151          * to the debugger.
152          * The standard allows this to happen, but the condition
153          * to trigger it is a bit obscure ("by performing an RDI_Execute
154          * request or equivalent").
155          *
156          * To make the SEMIHOSTING_SYS_EXIT call return normally, enable
157          * this variable via the dedicated command (default: disabled).
158          */
159         bool has_resumable_exit;
160
161         /** The Target (hart) word size; 8 for 64-bits targets. */
162         size_t word_size_bytes;
163
164         /** The current semihosting operation (R0 on ARM). */
165         int op;
166
167         /** The current semihosting parameter (R1 or ARM). */
168         uint64_t param;
169
170         /**
171          * The current semihosting result to be returned to the application.
172          * Usually 0 for success, -1 for error,
173          * but sometimes a useful value, even a pointer.
174          */
175         int64_t result;
176
177         /** The value to be returned by semihosting SYS_ERRNO request. */
178         int sys_errno;
179
180         /** The semihosting command line to be passed to the target. */
181         char *cmdline;
182
183         /** The current time when 'execution starts' */
184         clock_t setup_time;
185
186         /** Base directory for semihosting I/O operations. */
187         char *basedir;
188
189         /**
190          * Target's extension of semihosting user commands.
191          * @returns ERROR_NOT_IMPLEMENTED when user command is not handled, otherwise
192          * sets semihosting->result and semihosting->sys_errno and returns ERROR_OK.
193          */
194         int (*user_command_extension)(struct target *target);
195
196         int (*setup)(struct target *target, int enable);
197         int (*post_result)(struct target *target);
198 };
199
200 int semihosting_common_init(struct target *target, void *setup,
201         void *post_result);
202 int semihosting_common(struct target *target);
203
204 /* utility functions which may also be used by semihosting extensions (custom vendor-defined syscalls) */
205 int semihosting_read_fields(struct target *target, size_t number,
206         uint8_t *fields);
207 int semihosting_write_fields(struct target *target, size_t number,
208         uint8_t *fields);
209 uint64_t semihosting_get_field(struct target *target, size_t index,
210         uint8_t *fields);
211 void semihosting_set_field(struct target *target, uint64_t value,
212         size_t index,
213         uint8_t *fields);
214
215 #endif  /* OPENOCD_TARGET_SEMIHOSTING_COMMON_H */