1 /*
2  *  Arm "Angel" semihosting syscalls
3  *
4  *  Copyright (c) 2005, 2007 CodeSourcery.
5  *  Copyright (c) 2019 Linaro
6  *  Written by Paul Brook.
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  *  ARM Semihosting is documented in:
22  *     Semihosting for AArch32 and AArch64 Release 2.0
23  *     https://static.docs.arm.com/100863/0200/semihosting.pdf
24  */
25 
26 #include "qemu/osdep.h"
27 
28 #include "cpu.h"
29 #include "hw/semihosting/semihost.h"
30 #include "hw/semihosting/console.h"
31 #include "qemu/log.h"
32 #ifdef CONFIG_USER_ONLY
33 #include "qemu.h"
34 
35 #define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
36 #else
37 #include "exec/gdbstub.h"
38 #include "qemu/cutils.h"
39 #endif
40 
41 #define TARGET_SYS_OPEN        0x01
42 #define TARGET_SYS_CLOSE       0x02
43 #define TARGET_SYS_WRITEC      0x03
44 #define TARGET_SYS_WRITE0      0x04
45 #define TARGET_SYS_WRITE       0x05
46 #define TARGET_SYS_READ        0x06
47 #define TARGET_SYS_READC       0x07
48 #define TARGET_SYS_ISTTY       0x09
49 #define TARGET_SYS_SEEK        0x0a
50 #define TARGET_SYS_FLEN        0x0c
51 #define TARGET_SYS_TMPNAM      0x0d
52 #define TARGET_SYS_REMOVE      0x0e
53 #define TARGET_SYS_RENAME      0x0f
54 #define TARGET_SYS_CLOCK       0x10
55 #define TARGET_SYS_TIME        0x11
56 #define TARGET_SYS_SYSTEM      0x12
57 #define TARGET_SYS_ERRNO       0x13
58 #define TARGET_SYS_GET_CMDLINE 0x15
59 #define TARGET_SYS_HEAPINFO    0x16
60 #define TARGET_SYS_EXIT        0x18
61 #define TARGET_SYS_SYNCCACHE   0x19
62 #define TARGET_SYS_EXIT_EXTENDED 0x20
63 
64 /* ADP_Stopped_ApplicationExit is used for exit(0),
65  * anything else is implemented as exit(1) */
66 #define ADP_Stopped_ApplicationExit     (0x20026)
67 
68 #ifndef O_BINARY
69 #define O_BINARY 0
70 #endif
71 
72 #define GDB_O_RDONLY  0x000
73 #define GDB_O_WRONLY  0x001
74 #define GDB_O_RDWR    0x002
75 #define GDB_O_APPEND  0x008
76 #define GDB_O_CREAT   0x200
77 #define GDB_O_TRUNC   0x400
78 #define GDB_O_BINARY  0
79 
80 static int gdb_open_modeflags[12] = {
81     GDB_O_RDONLY,
82     GDB_O_RDONLY | GDB_O_BINARY,
83     GDB_O_RDWR,
84     GDB_O_RDWR | GDB_O_BINARY,
85     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
86     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
87     GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
88     GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
89     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
90     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
91     GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
92     GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
93 };
94 
95 static int open_modeflags[12] = {
96     O_RDONLY,
97     O_RDONLY | O_BINARY,
98     O_RDWR,
99     O_RDWR | O_BINARY,
100     O_WRONLY | O_CREAT | O_TRUNC,
101     O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
102     O_RDWR | O_CREAT | O_TRUNC,
103     O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
104     O_WRONLY | O_CREAT | O_APPEND,
105     O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
106     O_RDWR | O_CREAT | O_APPEND,
107     O_RDWR | O_CREAT | O_APPEND | O_BINARY
108 };
109 
110 typedef enum GuestFDType {
111     GuestFDUnused = 0,
112     GuestFDHost = 1,
113     GuestFDGDB = 2,
114     GuestFDFeatureFile = 3,
115 } GuestFDType;
116 
117 /*
118  * Guest file descriptors are integer indexes into an array of
119  * these structures (we will dynamically resize as necessary).
120  */
121 typedef struct GuestFD {
122     GuestFDType type;
123     union {
124         int hostfd;
125         target_ulong featurefile_offset;
126     };
127 } GuestFD;
128 
129 static GArray *guestfd_array;
130 
131 /*
132  * Allocate a new guest file descriptor and return it; if we
133  * couldn't allocate a new fd then return -1.
134  * This is a fairly simplistic implementation because we don't
135  * expect that most semihosting guest programs will make very
136  * heavy use of opening and closing fds.
137  */
alloc_guestfd(void)138 static int alloc_guestfd(void)
139 {
140     guint i;
141 
142     if (!guestfd_array) {
143         /* New entries zero-initialized, i.e. type GuestFDUnused */
144         guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
145     }
146 
147     for (i = 0; i < guestfd_array->len; i++) {
148         GuestFD *gf = &g_array_index(guestfd_array, GuestFD, i);
149 
150         if (gf->type == GuestFDUnused) {
151             return i;
152         }
153     }
154 
155     /* All elements already in use: expand the array */
156     g_array_set_size(guestfd_array, i + 1);
157     return i;
158 }
159 
160 /*
161  * Look up the guestfd in the data structure; return NULL
162  * for out of bounds, but don't check whether the slot is unused.
163  * This is used internally by the other guestfd functions.
164  */
do_get_guestfd(int guestfd)165 static GuestFD *do_get_guestfd(int guestfd)
166 {
167     if (!guestfd_array) {
168         return NULL;
169     }
170 
171     if (guestfd < 0 || guestfd >= guestfd_array->len) {
172         return NULL;
173     }
174 
175     return &g_array_index(guestfd_array, GuestFD, guestfd);
176 }
177 
178 /*
179  * Associate the specified guest fd (which must have been
180  * allocated via alloc_fd() and not previously used) with
181  * the specified host/gdb fd.
182  */
associate_guestfd(int guestfd,int hostfd)183 static void associate_guestfd(int guestfd, int hostfd)
184 {
185     GuestFD *gf = do_get_guestfd(guestfd);
186 
187     assert(gf);
188     gf->type = use_gdb_syscalls() ? GuestFDGDB : GuestFDHost;
189     gf->hostfd = hostfd;
190 }
191 
192 /*
193  * Deallocate the specified guest file descriptor. This doesn't
194  * close the host fd, it merely undoes the work of alloc_fd().
195  */
dealloc_guestfd(int guestfd)196 static void dealloc_guestfd(int guestfd)
197 {
198     GuestFD *gf = do_get_guestfd(guestfd);
199 
200     assert(gf);
201     gf->type = GuestFDUnused;
202 }
203 
204 /*
205  * Given a guest file descriptor, get the associated struct.
206  * If the fd is not valid, return NULL. This is the function
207  * used by the various semihosting calls to validate a handle
208  * from the guest.
209  * Note: calling alloc_guestfd() or dealloc_guestfd() will
210  * invalidate any GuestFD* obtained by calling this function.
211  */
get_guestfd(int guestfd)212 static GuestFD *get_guestfd(int guestfd)
213 {
214     GuestFD *gf = do_get_guestfd(guestfd);
215 
216     if (!gf || gf->type == GuestFDUnused) {
217         return NULL;
218     }
219     return gf;
220 }
221 
222 /*
223  * The semihosting API has no concept of its errno being thread-safe,
224  * as the API design predates SMP CPUs and was intended as a simple
225  * real-hardware set of debug functionality. For QEMU, we make the
226  * errno be per-thread in linux-user mode; in softmmu it is a simple
227  * global, and we assume that the guest takes care of avoiding any races.
228  */
229 #ifndef CONFIG_USER_ONLY
230 static target_ulong syscall_err;
231 
232 #include "exec/softmmu-semi.h"
233 #endif
234 
set_swi_errno(CPUARMState * env,uint32_t code)235 static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
236 {
237     if (code == (uint32_t)-1) {
238 #ifdef CONFIG_USER_ONLY
239         CPUState *cs = env_cpu(env);
240         TaskState *ts = cs->opaque;
241 
242         ts->swi_errno = errno;
243 #else
244         syscall_err = errno;
245 #endif
246     }
247     return code;
248 }
249 
get_swi_errno(CPUARMState * env)250 static inline uint32_t get_swi_errno(CPUARMState *env)
251 {
252 #ifdef CONFIG_USER_ONLY
253     CPUState *cs = env_cpu(env);
254     TaskState *ts = cs->opaque;
255 
256     return ts->swi_errno;
257 #else
258     return syscall_err;
259 #endif
260 }
261 
262 static target_ulong arm_semi_syscall_len;
263 
arm_semi_cb(CPUState * cs,target_ulong ret,target_ulong err)264 static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
265 {
266     ARMCPU *cpu = ARM_CPU(cs);
267     CPUARMState *env = &cpu->env;
268     target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
269 
270     if (ret == (target_ulong)-1) {
271         errno = err;
272         set_swi_errno(env, -1);
273         reg0 = ret;
274     } else {
275         /* Fixup syscalls that use nonstardard return conventions.  */
276         switch (reg0) {
277         case TARGET_SYS_WRITE:
278         case TARGET_SYS_READ:
279             reg0 = arm_semi_syscall_len - ret;
280             break;
281         case TARGET_SYS_SEEK:
282             reg0 = 0;
283             break;
284         default:
285             reg0 = ret;
286             break;
287         }
288     }
289     if (is_a64(env)) {
290         env->xregs[0] = reg0;
291     } else {
292         env->regs[0] = reg0;
293     }
294 }
295 
arm_flen_buf(ARMCPU * cpu)296 static target_ulong arm_flen_buf(ARMCPU *cpu)
297 {
298     /* Return an address in target memory of 64 bytes where the remote
299      * gdb should write its stat struct. (The format of this structure
300      * is defined by GDB's remote protocol and is not target-specific.)
301      * We put this on the guest's stack just below SP.
302      */
303     CPUARMState *env = &cpu->env;
304     target_ulong sp;
305 
306     if (is_a64(env)) {
307         sp = env->xregs[31];
308     } else {
309         sp = env->regs[13];
310     }
311 
312     return sp - 64;
313 }
314 
arm_semi_flen_cb(CPUState * cs,target_ulong ret,target_ulong err)315 static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
316 {
317     ARMCPU *cpu = ARM_CPU(cs);
318     CPUARMState *env = &cpu->env;
319     /* The size is always stored in big-endian order, extract
320        the value. We assume the size always fit in 32 bits.  */
321     uint32_t size;
322     cpu_memory_rw_debug(cs, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
323     size = be32_to_cpu(size);
324     if (is_a64(env)) {
325         env->xregs[0] = size;
326     } else {
327         env->regs[0] = size;
328     }
329     errno = err;
330     set_swi_errno(env, -1);
331 }
332 
333 static int arm_semi_open_guestfd;
334 
arm_semi_open_cb(CPUState * cs,target_ulong ret,target_ulong err)335 static void arm_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
336 {
337     ARMCPU *cpu = ARM_CPU(cs);
338     CPUARMState *env = &cpu->env;
339     if (ret == (target_ulong)-1) {
340         errno = err;
341         set_swi_errno(env, -1);
342         dealloc_guestfd(arm_semi_open_guestfd);
343     } else {
344         associate_guestfd(arm_semi_open_guestfd, ret);
345         ret = arm_semi_open_guestfd;
346     }
347 
348     if (is_a64(env)) {
349         env->xregs[0] = ret;
350     } else {
351         env->regs[0] = ret;
352     }
353 }
354 
arm_gdb_syscall(ARMCPU * cpu,gdb_syscall_complete_cb cb,const char * fmt,...)355 static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
356                                     const char *fmt, ...)
357 {
358     va_list va;
359     CPUARMState *env = &cpu->env;
360 
361     va_start(va, fmt);
362     gdb_do_syscallv(cb, fmt, va);
363     va_end(va);
364 
365     /*
366      * FIXME: in softmmu mode, the gdbstub will schedule our callback
367      * to occur, but will not actually call it to complete the syscall
368      * until after this function has returned and we are back in the
369      * CPU main loop. Therefore callers to this function must not
370      * do anything with its return value, because it is not necessarily
371      * the result of the syscall, but could just be the old value of X0.
372      * The only thing safe to do with this is that the callers of
373      * do_arm_semihosting() will write it straight back into X0.
374      * (In linux-user mode, the callback will have happened before
375      * gdb_do_syscallv() returns.)
376      *
377      * We should tidy this up so neither this function nor
378      * do_arm_semihosting() return a value, so the mistake of
379      * doing something with the return value is not possible to make.
380      */
381 
382     return is_a64(env) ? env->xregs[0] : env->regs[0];
383 }
384 
385 /*
386  * Types for functions implementing various semihosting calls
387  * for specific types of guest file descriptor. These must all
388  * do the work and return the required return value for the guest,
389  * setting the guest errno if appropriate.
390  */
391 typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
392 typedef uint32_t sys_writefn(ARMCPU *cpu, GuestFD *gf,
393                              target_ulong buf, uint32_t len);
394 typedef uint32_t sys_readfn(ARMCPU *cpu, GuestFD *gf,
395                             target_ulong buf, uint32_t len);
396 typedef uint32_t sys_isattyfn(ARMCPU *cpu, GuestFD *gf);
397 typedef uint32_t sys_seekfn(ARMCPU *cpu, GuestFD *gf,
398                             target_ulong offset);
399 typedef uint32_t sys_flenfn(ARMCPU *cpu, GuestFD *gf);
400 
host_closefn(ARMCPU * cpu,GuestFD * gf)401 static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
402 {
403     CPUARMState *env = &cpu->env;
404 
405     return set_swi_errno(env, close(gf->hostfd));
406 }
407 
host_writefn(ARMCPU * cpu,GuestFD * gf,target_ulong buf,uint32_t len)408 static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
409                              target_ulong buf, uint32_t len)
410 {
411     uint32_t ret;
412     CPUARMState *env = &cpu->env;
413     char *s = lock_user(VERIFY_READ, buf, len, 1);
414     if (!s) {
415         /* Return bytes not written on error */
416         return len;
417     }
418     ret = set_swi_errno(env, write(gf->hostfd, s, len));
419     unlock_user(s, buf, 0);
420     if (ret == (uint32_t)-1) {
421         ret = 0;
422     }
423     /* Return bytes not written */
424     return len - ret;
425 }
426 
host_readfn(ARMCPU * cpu,GuestFD * gf,target_ulong buf,uint32_t len)427 static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
428                             target_ulong buf, uint32_t len)
429 {
430     uint32_t ret;
431     CPUARMState *env = &cpu->env;
432     char *s = lock_user(VERIFY_WRITE, buf, len, 0);
433     if (!s) {
434         /* return bytes not read */
435         return len;
436     }
437     do {
438         ret = set_swi_errno(env, read(gf->hostfd, s, len));
439     } while (ret == -1 && errno == EINTR);
440     unlock_user(s, buf, len);
441     if (ret == (uint32_t)-1) {
442         ret = 0;
443     }
444     /* Return bytes not read */
445     return len - ret;
446 }
447 
host_isattyfn(ARMCPU * cpu,GuestFD * gf)448 static uint32_t host_isattyfn(ARMCPU *cpu, GuestFD *gf)
449 {
450     return isatty(gf->hostfd);
451 }
452 
host_seekfn(ARMCPU * cpu,GuestFD * gf,target_ulong offset)453 static uint32_t host_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
454 {
455     CPUARMState *env = &cpu->env;
456     uint32_t ret = set_swi_errno(env, lseek(gf->hostfd, offset, SEEK_SET));
457     if (ret == (uint32_t)-1) {
458         return -1;
459     }
460     return 0;
461 }
462 
host_flenfn(ARMCPU * cpu,GuestFD * gf)463 static uint32_t host_flenfn(ARMCPU *cpu, GuestFD *gf)
464 {
465     CPUARMState *env = &cpu->env;
466     struct stat buf;
467     uint32_t ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
468     if (ret == (uint32_t)-1) {
469         return -1;
470     }
471     return buf.st_size;
472 }
473 
gdb_closefn(ARMCPU * cpu,GuestFD * gf)474 static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
475 {
476     return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
477 }
478 
gdb_writefn(ARMCPU * cpu,GuestFD * gf,target_ulong buf,uint32_t len)479 static uint32_t gdb_writefn(ARMCPU *cpu, GuestFD *gf,
480                             target_ulong buf, uint32_t len)
481 {
482     arm_semi_syscall_len = len;
483     return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
484                            gf->hostfd, buf, len);
485 }
486 
gdb_readfn(ARMCPU * cpu,GuestFD * gf,target_ulong buf,uint32_t len)487 static uint32_t gdb_readfn(ARMCPU *cpu, GuestFD *gf,
488                            target_ulong buf, uint32_t len)
489 {
490     arm_semi_syscall_len = len;
491     return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
492                            gf->hostfd, buf, len);
493 }
494 
gdb_isattyfn(ARMCPU * cpu,GuestFD * gf)495 static uint32_t gdb_isattyfn(ARMCPU *cpu, GuestFD *gf)
496 {
497     return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", gf->hostfd);
498 }
499 
gdb_seekfn(ARMCPU * cpu,GuestFD * gf,target_ulong offset)500 static uint32_t gdb_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
501 {
502     return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
503                            gf->hostfd, offset);
504 }
505 
gdb_flenfn(ARMCPU * cpu,GuestFD * gf)506 static uint32_t gdb_flenfn(ARMCPU *cpu, GuestFD *gf)
507 {
508     return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
509                            gf->hostfd, arm_flen_buf(cpu));
510 }
511 
512 #define SHFB_MAGIC_0 0x53
513 #define SHFB_MAGIC_1 0x48
514 #define SHFB_MAGIC_2 0x46
515 #define SHFB_MAGIC_3 0x42
516 
517 /* Feature bits reportable in feature byte 0 */
518 #define SH_EXT_EXIT_EXTENDED (1 << 0)
519 #define SH_EXT_STDOUT_STDERR (1 << 1)
520 
521 static const uint8_t featurefile_data[] = {
522     SHFB_MAGIC_0,
523     SHFB_MAGIC_1,
524     SHFB_MAGIC_2,
525     SHFB_MAGIC_3,
526     SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
527 };
528 
init_featurefile_guestfd(int guestfd)529 static void init_featurefile_guestfd(int guestfd)
530 {
531     GuestFD *gf = do_get_guestfd(guestfd);
532 
533     assert(gf);
534     gf->type = GuestFDFeatureFile;
535     gf->featurefile_offset = 0;
536 }
537 
featurefile_closefn(ARMCPU * cpu,GuestFD * gf)538 static uint32_t featurefile_closefn(ARMCPU *cpu, GuestFD *gf)
539 {
540     /* Nothing to do */
541     return 0;
542 }
543 
featurefile_writefn(ARMCPU * cpu,GuestFD * gf,target_ulong buf,uint32_t len)544 static uint32_t featurefile_writefn(ARMCPU *cpu, GuestFD *gf,
545                                     target_ulong buf, uint32_t len)
546 {
547     /* This fd can never be open for writing */
548     CPUARMState *env = &cpu->env;
549 
550     errno = EBADF;
551     return set_swi_errno(env, -1);
552 }
553 
featurefile_readfn(ARMCPU * cpu,GuestFD * gf,target_ulong buf,uint32_t len)554 static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
555                                    target_ulong buf, uint32_t len)
556 {
557     uint32_t i;
558 #ifndef CONFIG_USER_ONLY
559     CPUARMState *env = &cpu->env;
560 #endif
561     char *s;
562 
563     s = lock_user(VERIFY_WRITE, buf, len, 0);
564     if (!s) {
565         return len;
566     }
567 
568     for (i = 0; i < len; i++) {
569         if (gf->featurefile_offset >= sizeof(featurefile_data)) {
570             break;
571         }
572         s[i] = featurefile_data[gf->featurefile_offset];
573         gf->featurefile_offset++;
574     }
575 
576     unlock_user(s, buf, len);
577 
578     /* Return number of bytes not read */
579     return len - i;
580 }
581 
featurefile_isattyfn(ARMCPU * cpu,GuestFD * gf)582 static uint32_t featurefile_isattyfn(ARMCPU *cpu, GuestFD *gf)
583 {
584     return 0;
585 }
586 
featurefile_seekfn(ARMCPU * cpu,GuestFD * gf,target_ulong offset)587 static uint32_t featurefile_seekfn(ARMCPU *cpu, GuestFD *gf,
588                                    target_ulong offset)
589 {
590     gf->featurefile_offset = offset;
591     return 0;
592 }
593 
featurefile_flenfn(ARMCPU * cpu,GuestFD * gf)594 static uint32_t featurefile_flenfn(ARMCPU *cpu, GuestFD *gf)
595 {
596     return sizeof(featurefile_data);
597 }
598 
599 typedef struct GuestFDFunctions {
600     sys_closefn *closefn;
601     sys_writefn *writefn;
602     sys_readfn *readfn;
603     sys_isattyfn *isattyfn;
604     sys_seekfn *seekfn;
605     sys_flenfn *flenfn;
606 } GuestFDFunctions;
607 
608 static const GuestFDFunctions guestfd_fns[] = {
609     [GuestFDHost] = {
610         .closefn = host_closefn,
611         .writefn = host_writefn,
612         .readfn = host_readfn,
613         .isattyfn = host_isattyfn,
614         .seekfn = host_seekfn,
615         .flenfn = host_flenfn,
616     },
617     [GuestFDGDB] = {
618         .closefn = gdb_closefn,
619         .writefn = gdb_writefn,
620         .readfn = gdb_readfn,
621         .isattyfn = gdb_isattyfn,
622         .seekfn = gdb_seekfn,
623         .flenfn = gdb_flenfn,
624     },
625     [GuestFDFeatureFile] = {
626         .closefn = featurefile_closefn,
627         .writefn = featurefile_writefn,
628         .readfn = featurefile_readfn,
629         .isattyfn = featurefile_isattyfn,
630         .seekfn = featurefile_seekfn,
631         .flenfn = featurefile_flenfn,
632     },
633 };
634 
635 /* Read the input value from the argument block; fail the semihosting
636  * call if the memory read fails.
637  */
638 #define GET_ARG(n) do {                                 \
639     if (is_a64(env)) {                                  \
640         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
641             errno = EFAULT;                             \
642             return set_swi_errno(env, -1);              \
643         }                                               \
644     } else {                                            \
645         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
646             errno = EFAULT;                             \
647             return set_swi_errno(env, -1);              \
648         }                                               \
649     }                                                   \
650 } while (0)
651 
652 #define SET_ARG(n, val)                                 \
653     (is_a64(env) ?                                      \
654      put_user_u64(val, args + (n) * 8) :                \
655      put_user_u32(val, args + (n) * 4))
656 
657 /*
658  * Do a semihosting call.
659  *
660  * The specification always says that the "return register" either
661  * returns a specific value or is corrupted, so we don't need to
662  * report to our caller whether we are returning a value or trying to
663  * leave the register unchanged. We use 0xdeadbeef as the return value
664  * when there isn't a defined return value for the call.
665  */
do_arm_semihosting(CPUARMState * env)666 target_ulong do_arm_semihosting(CPUARMState *env)
667 {
668     ARMCPU *cpu = env_archcpu(env);
669     CPUState *cs = env_cpu(env);
670     target_ulong args;
671     target_ulong arg0, arg1, arg2, arg3;
672     char * s;
673     int nr;
674     uint32_t ret;
675     uint32_t len;
676     GuestFD *gf;
677 
678     if (is_a64(env)) {
679         /* Note that the syscall number is in W0, not X0 */
680         nr = env->xregs[0] & 0xffffffffU;
681         args = env->xregs[1];
682     } else {
683         nr = env->regs[0];
684         args = env->regs[1];
685     }
686 
687     switch (nr) {
688     case TARGET_SYS_OPEN:
689     {
690         int guestfd;
691 
692         GET_ARG(0);
693         GET_ARG(1);
694         GET_ARG(2);
695         s = lock_user_string(arg0);
696         if (!s) {
697             errno = EFAULT;
698             return set_swi_errno(env, -1);
699         }
700         if (arg1 >= 12) {
701             unlock_user(s, arg0, 0);
702             errno = EINVAL;
703             return set_swi_errno(env, -1);
704         }
705 
706         guestfd = alloc_guestfd();
707         if (guestfd < 0) {
708             unlock_user(s, arg0, 0);
709             errno = EMFILE;
710             return set_swi_errno(env, -1);
711         }
712 
713         if (strcmp(s, ":tt") == 0) {
714             int result_fileno;
715 
716             /*
717              * We implement SH_EXT_STDOUT_STDERR, so:
718              *  open for read == stdin
719              *  open for write == stdout
720              *  open for append == stderr
721              */
722             if (arg1 < 4) {
723                 result_fileno = STDIN_FILENO;
724             } else if (arg1 < 8) {
725                 result_fileno = STDOUT_FILENO;
726             } else {
727                 result_fileno = STDERR_FILENO;
728             }
729             associate_guestfd(guestfd, result_fileno);
730             unlock_user(s, arg0, 0);
731             return guestfd;
732         }
733         if (strcmp(s, ":semihosting-features") == 0) {
734             unlock_user(s, arg0, 0);
735             /* We must fail opens for modes other than 0 ('r') or 1 ('rb') */
736             if (arg1 != 0 && arg1 != 1) {
737                 dealloc_guestfd(guestfd);
738                 errno = EACCES;
739                 return set_swi_errno(env, -1);
740             }
741             init_featurefile_guestfd(guestfd);
742             return guestfd;
743         }
744 
745         if (use_gdb_syscalls()) {
746             arm_semi_open_guestfd = guestfd;
747             ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
748                                   (int)arg2+1, gdb_open_modeflags[arg1]);
749         } else {
750             ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
751             if (ret == (uint32_t)-1) {
752                 dealloc_guestfd(guestfd);
753             } else {
754                 associate_guestfd(guestfd, ret);
755                 ret = guestfd;
756             }
757         }
758         unlock_user(s, arg0, 0);
759         return ret;
760     }
761     case TARGET_SYS_CLOSE:
762         GET_ARG(0);
763 
764         gf = get_guestfd(arg0);
765         if (!gf) {
766             errno = EBADF;
767             return set_swi_errno(env, -1);
768         }
769 
770         ret = guestfd_fns[gf->type].closefn(cpu, gf);
771         dealloc_guestfd(arg0);
772         return ret;
773     case TARGET_SYS_WRITEC:
774         qemu_semihosting_console_outc(env, args);
775         return 0xdeadbeef;
776     case TARGET_SYS_WRITE0:
777         return qemu_semihosting_console_outs(env, args);
778     case TARGET_SYS_WRITE:
779         GET_ARG(0);
780         GET_ARG(1);
781         GET_ARG(2);
782         len = arg2;
783 
784         gf = get_guestfd(arg0);
785         if (!gf) {
786             errno = EBADF;
787             return set_swi_errno(env, -1);
788         }
789 
790         return guestfd_fns[gf->type].writefn(cpu, gf, arg1, len);
791     case TARGET_SYS_READ:
792         GET_ARG(0);
793         GET_ARG(1);
794         GET_ARG(2);
795         len = arg2;
796 
797         gf = get_guestfd(arg0);
798         if (!gf) {
799             errno = EBADF;
800             return set_swi_errno(env, -1);
801         }
802 
803         return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
804     case TARGET_SYS_READC:
805         qemu_log_mask(LOG_UNIMP, "%s: SYS_READC not implemented", __func__);
806         return 0;
807     case TARGET_SYS_ISTTY:
808         GET_ARG(0);
809 
810         gf = get_guestfd(arg0);
811         if (!gf) {
812             errno = EBADF;
813             return set_swi_errno(env, -1);
814         }
815 
816         return guestfd_fns[gf->type].isattyfn(cpu, gf);
817     case TARGET_SYS_SEEK:
818         GET_ARG(0);
819         GET_ARG(1);
820 
821         gf = get_guestfd(arg0);
822         if (!gf) {
823             errno = EBADF;
824             return set_swi_errno(env, -1);
825         }
826 
827         return guestfd_fns[gf->type].seekfn(cpu, gf, arg1);
828     case TARGET_SYS_FLEN:
829         GET_ARG(0);
830 
831         gf = get_guestfd(arg0);
832         if (!gf) {
833             errno = EBADF;
834             return set_swi_errno(env, -1);
835         }
836 
837         return guestfd_fns[gf->type].flenfn(cpu, gf);
838     case TARGET_SYS_TMPNAM:
839         qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__);
840         return -1;
841     case TARGET_SYS_REMOVE:
842         GET_ARG(0);
843         GET_ARG(1);
844         if (use_gdb_syscalls()) {
845             ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
846                                   arg0, (int)arg1+1);
847         } else {
848             s = lock_user_string(arg0);
849             if (!s) {
850                 errno = EFAULT;
851                 return set_swi_errno(env, -1);
852             }
853             ret =  set_swi_errno(env, remove(s));
854             unlock_user(s, arg0, 0);
855         }
856         return ret;
857     case TARGET_SYS_RENAME:
858         GET_ARG(0);
859         GET_ARG(1);
860         GET_ARG(2);
861         GET_ARG(3);
862         if (use_gdb_syscalls()) {
863             return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
864                                    arg0, (int)arg1+1, arg2, (int)arg3+1);
865         } else {
866             char *s2;
867             s = lock_user_string(arg0);
868             s2 = lock_user_string(arg2);
869             if (!s || !s2) {
870                 errno = EFAULT;
871                 ret = set_swi_errno(env, -1);
872             } else {
873                 ret = set_swi_errno(env, rename(s, s2));
874             }
875             if (s2)
876                 unlock_user(s2, arg2, 0);
877             if (s)
878                 unlock_user(s, arg0, 0);
879             return ret;
880         }
881     case TARGET_SYS_CLOCK:
882         return clock() / (CLOCKS_PER_SEC / 100);
883     case TARGET_SYS_TIME:
884         return set_swi_errno(env, time(NULL));
885     case TARGET_SYS_SYSTEM:
886         GET_ARG(0);
887         GET_ARG(1);
888         if (use_gdb_syscalls()) {
889             return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
890                                    arg0, (int)arg1+1);
891         } else {
892             s = lock_user_string(arg0);
893             if (!s) {
894                 errno = EFAULT;
895                 return set_swi_errno(env, -1);
896             }
897             ret = set_swi_errno(env, system(s));
898             unlock_user(s, arg0, 0);
899             return ret;
900         }
901     case TARGET_SYS_ERRNO:
902         return get_swi_errno(env);
903     case TARGET_SYS_GET_CMDLINE:
904         {
905             /* Build a command-line from the original argv.
906              *
907              * The inputs are:
908              *     * arg0, pointer to a buffer of at least the size
909              *               specified in arg1.
910              *     * arg1, size of the buffer pointed to by arg0 in
911              *               bytes.
912              *
913              * The outputs are:
914              *     * arg0, pointer to null-terminated string of the
915              *               command line.
916              *     * arg1, length of the string pointed to by arg0.
917              */
918 
919             char *output_buffer;
920             size_t input_size;
921             size_t output_size;
922             int status = 0;
923 #if !defined(CONFIG_USER_ONLY)
924             const char *cmdline;
925 #else
926             TaskState *ts = cs->opaque;
927 #endif
928             GET_ARG(0);
929             GET_ARG(1);
930             input_size = arg1;
931             /* Compute the size of the output string.  */
932 #if !defined(CONFIG_USER_ONLY)
933             cmdline = semihosting_get_cmdline();
934             if (cmdline == NULL) {
935                 cmdline = ""; /* Default to an empty line. */
936             }
937             output_size = strlen(cmdline) + 1; /* Count terminating 0. */
938 #else
939             unsigned int i;
940 
941             output_size = ts->info->arg_end - ts->info->arg_start;
942             if (!output_size) {
943                 /*
944                  * We special-case the "empty command line" case (argc==0).
945                  * Just provide the terminating 0.
946                  */
947                 output_size = 1;
948             }
949 #endif
950 
951             if (output_size > input_size) {
952                 /* Not enough space to store command-line arguments.  */
953                 errno = E2BIG;
954                 return set_swi_errno(env, -1);
955             }
956 
957             /* Adjust the command-line length.  */
958             if (SET_ARG(1, output_size - 1)) {
959                 /* Couldn't write back to argument block */
960                 errno = EFAULT;
961                 return set_swi_errno(env, -1);
962             }
963 
964             /* Lock the buffer on the ARM side.  */
965             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
966             if (!output_buffer) {
967                 errno = EFAULT;
968                 return set_swi_errno(env, -1);
969             }
970 
971             /* Copy the command-line arguments.  */
972 #if !defined(CONFIG_USER_ONLY)
973             pstrcpy(output_buffer, output_size, cmdline);
974 #else
975             if (output_size == 1) {
976                 /* Empty command-line.  */
977                 output_buffer[0] = '\0';
978                 goto out;
979             }
980 
981             if (copy_from_user(output_buffer, ts->info->arg_start,
982                                output_size)) {
983                 errno = EFAULT;
984                 status = set_swi_errno(env, -1);
985                 goto out;
986             }
987 
988             /* Separate arguments by white spaces.  */
989             for (i = 0; i < output_size - 1; i++) {
990                 if (output_buffer[i] == 0) {
991                     output_buffer[i] = ' ';
992                 }
993             }
994         out:
995 #endif
996             /* Unlock the buffer on the ARM side.  */
997             unlock_user(output_buffer, arg0, output_size);
998 
999             return status;
1000         }
1001     case TARGET_SYS_HEAPINFO:
1002         {
1003             target_ulong retvals[4];
1004             target_ulong limit;
1005             int i;
1006 #ifdef CONFIG_USER_ONLY
1007             TaskState *ts = cs->opaque;
1008 #endif
1009 
1010             GET_ARG(0);
1011 
1012 #ifdef CONFIG_USER_ONLY
1013             /*
1014              * Some C libraries assume the heap immediately follows .bss, so
1015              * allocate it using sbrk.
1016              */
1017             if (!ts->heap_limit) {
1018                 abi_ulong ret;
1019 
1020                 ts->heap_base = do_brk(0);
1021                 limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
1022                 /* Try a big heap, and reduce the size if that fails.  */
1023                 for (;;) {
1024                     ret = do_brk(limit);
1025                     if (ret >= limit) {
1026                         break;
1027                     }
1028                     limit = (ts->heap_base >> 1) + (limit >> 1);
1029                 }
1030                 ts->heap_limit = limit;
1031             }
1032 
1033             retvals[0] = ts->heap_base;
1034             retvals[1] = ts->heap_limit;
1035             retvals[2] = ts->stack_base;
1036             retvals[3] = 0; /* Stack limit.  */
1037 #else
1038             limit = ram_size;
1039             /* TODO: Make this use the limit of the loaded application.  */
1040             retvals[0] = limit / 2;
1041             retvals[1] = limit;
1042             retvals[2] = limit; /* Stack base */
1043             retvals[3] = 0; /* Stack limit.  */
1044 #endif
1045 
1046             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
1047                 bool fail;
1048 
1049                 if (is_a64(env)) {
1050                     fail = put_user_u64(retvals[i], arg0 + i * 8);
1051                 } else {
1052                     fail = put_user_u32(retvals[i], arg0 + i * 4);
1053                 }
1054 
1055                 if (fail) {
1056                     /* Couldn't write back to argument block */
1057                     errno = EFAULT;
1058                     return set_swi_errno(env, -1);
1059                 }
1060             }
1061             return 0;
1062         }
1063     case TARGET_SYS_EXIT:
1064     case TARGET_SYS_EXIT_EXTENDED:
1065         if (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(env)) {
1066             /*
1067              * The A64 version of SYS_EXIT takes a parameter block,
1068              * so the application-exit type can return a subcode which
1069              * is the exit status code from the application.
1070              * SYS_EXIT_EXTENDED is an a new-in-v2.0 optional function
1071              * which allows A32/T32 guests to also provide a status code.
1072              */
1073             GET_ARG(0);
1074             GET_ARG(1);
1075 
1076             if (arg0 == ADP_Stopped_ApplicationExit) {
1077                 ret = arg1;
1078             } else {
1079                 ret = 1;
1080             }
1081         } else {
1082             /*
1083              * The A32/T32 version of SYS_EXIT specifies only
1084              * Stopped_ApplicationExit as normal exit, but does not
1085              * allow the guest to specify the exit status code.
1086              * Everything else is considered an error.
1087              */
1088             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
1089         }
1090         gdb_exit(env, ret);
1091         exit(ret);
1092     case TARGET_SYS_SYNCCACHE:
1093         /*
1094          * Clean the D-cache and invalidate the I-cache for the specified
1095          * virtual address range. This is a nop for us since we don't
1096          * implement caches. This is only present on A64.
1097          */
1098         if (is_a64(env)) {
1099             return 0;
1100         }
1101         /* fall through -- invalid for A32/T32 */
1102     default:
1103         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
1104         cpu_dump_state(cs, stderr, 0);
1105         abort();
1106     }
1107 }
1108