tests/tcg/s390x: Add cdsg.c
[qemu/armbru.git] / semihosting / syscalls.c
blobe89992cf904678ffcb47906837a11984b60b2ef7
1 /*
2 * Syscall implementations for semihosting.
4 * Copyright (c) 2022 Linaro
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
9 #include "qemu/osdep.h"
10 #include "exec/gdbstub.h"
11 #include "semihosting/guestfd.h"
12 #include "semihosting/syscalls.h"
13 #include "semihosting/console.h"
14 #ifdef CONFIG_USER_ONLY
15 #include "qemu.h"
16 #else
17 #include "semihosting/softmmu-uaccess.h"
18 #endif
22 * Validate or compute the length of the string (including terminator).
24 static int validate_strlen(CPUState *cs, target_ulong str, target_ulong tlen)
26 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
27 char c;
29 if (tlen == 0) {
30 ssize_t slen = target_strlen(str);
32 if (slen < 0) {
33 return -EFAULT;
35 if (slen >= INT32_MAX) {
36 return -ENAMETOOLONG;
38 return slen + 1;
40 if (tlen > INT32_MAX) {
41 return -ENAMETOOLONG;
43 if (get_user_u8(c, str + tlen - 1)) {
44 return -EFAULT;
46 if (c != 0) {
47 return -EINVAL;
49 return tlen;
52 static int validate_lock_user_string(char **pstr, CPUState *cs,
53 target_ulong tstr, target_ulong tlen)
55 int ret = validate_strlen(cs, tstr, tlen);
56 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
57 char *str = NULL;
59 if (ret > 0) {
60 str = lock_user(VERIFY_READ, tstr, ret, true);
61 ret = str ? 0 : -EFAULT;
63 *pstr = str;
64 return ret;
68 * TODO: Note that gdb always stores the stat structure big-endian.
69 * So far, that's ok, as the only two targets using this are also
70 * big-endian. Until we do something with gdb, also produce the
71 * same big-endian result from the host.
73 static int copy_stat_to_user(CPUState *cs, target_ulong addr,
74 const struct stat *s)
76 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
77 struct gdb_stat *p;
79 if (s->st_dev != (uint32_t)s->st_dev ||
80 s->st_ino != (uint32_t)s->st_ino) {
81 return -EOVERFLOW;
84 p = lock_user(VERIFY_WRITE, addr, sizeof(struct gdb_stat), 0);
85 if (!p) {
86 return -EFAULT;
89 p->gdb_st_dev = cpu_to_be32(s->st_dev);
90 p->gdb_st_ino = cpu_to_be32(s->st_ino);
91 p->gdb_st_mode = cpu_to_be32(s->st_mode);
92 p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
93 p->gdb_st_uid = cpu_to_be32(s->st_uid);
94 p->gdb_st_gid = cpu_to_be32(s->st_gid);
95 p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
96 p->gdb_st_size = cpu_to_be64(s->st_size);
97 #ifdef _WIN32
98 /* Windows stat is missing some fields. */
99 p->gdb_st_blksize = 0;
100 p->gdb_st_blocks = 0;
101 #else
102 p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
103 p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
104 #endif
105 p->gdb_st_atime = cpu_to_be32(s->st_atime);
106 p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
107 p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
109 unlock_user(p, addr, sizeof(struct gdb_stat));
110 return 0;
114 * GDB semihosting syscall implementations.
117 static gdb_syscall_complete_cb gdb_open_complete;
119 static void gdb_open_cb(CPUState *cs, uint64_t ret, int err)
121 if (!err) {
122 int guestfd = alloc_guestfd();
123 associate_guestfd(guestfd, ret);
124 ret = guestfd;
126 gdb_open_complete(cs, ret, err);
129 static void gdb_open(CPUState *cs, gdb_syscall_complete_cb complete,
130 target_ulong fname, target_ulong fname_len,
131 int gdb_flags, int mode)
133 int len = validate_strlen(cs, fname, fname_len);
134 if (len < 0) {
135 complete(cs, -1, -len);
136 return;
139 gdb_open_complete = complete;
140 gdb_do_syscall(gdb_open_cb, "open,%s,%x,%x",
141 fname, len, (target_ulong)gdb_flags, (target_ulong)mode);
144 static void gdb_close(CPUState *cs, gdb_syscall_complete_cb complete,
145 GuestFD *gf)
147 gdb_do_syscall(complete, "close,%x", (target_ulong)gf->hostfd);
150 static void gdb_read(CPUState *cs, gdb_syscall_complete_cb complete,
151 GuestFD *gf, target_ulong buf, target_ulong len)
153 gdb_do_syscall(complete, "read,%x,%x,%x",
154 (target_ulong)gf->hostfd, buf, len);
157 static void gdb_write(CPUState *cs, gdb_syscall_complete_cb complete,
158 GuestFD *gf, target_ulong buf, target_ulong len)
160 gdb_do_syscall(complete, "write,%x,%x,%x",
161 (target_ulong)gf->hostfd, buf, len);
164 static void gdb_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
165 GuestFD *gf, int64_t off, int gdb_whence)
167 gdb_do_syscall(complete, "lseek,%x,%lx,%x",
168 (target_ulong)gf->hostfd, off, (target_ulong)gdb_whence);
171 static void gdb_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
172 GuestFD *gf)
174 gdb_do_syscall(complete, "isatty,%x", (target_ulong)gf->hostfd);
177 static void gdb_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
178 GuestFD *gf, target_ulong addr)
180 gdb_do_syscall(complete, "fstat,%x,%x", (target_ulong)gf->hostfd, addr);
183 static void gdb_stat(CPUState *cs, gdb_syscall_complete_cb complete,
184 target_ulong fname, target_ulong fname_len,
185 target_ulong addr)
187 int len = validate_strlen(cs, fname, fname_len);
188 if (len < 0) {
189 complete(cs, -1, -len);
190 return;
193 gdb_do_syscall(complete, "stat,%s,%x", fname, len, addr);
196 static void gdb_remove(CPUState *cs, gdb_syscall_complete_cb complete,
197 target_ulong fname, target_ulong fname_len)
199 int len = validate_strlen(cs, fname, fname_len);
200 if (len < 0) {
201 complete(cs, -1, -len);
202 return;
205 gdb_do_syscall(complete, "unlink,%s", fname, len);
208 static void gdb_rename(CPUState *cs, gdb_syscall_complete_cb complete,
209 target_ulong oname, target_ulong oname_len,
210 target_ulong nname, target_ulong nname_len)
212 int olen, nlen;
214 olen = validate_strlen(cs, oname, oname_len);
215 if (olen < 0) {
216 complete(cs, -1, -olen);
217 return;
219 nlen = validate_strlen(cs, nname, nname_len);
220 if (nlen < 0) {
221 complete(cs, -1, -nlen);
222 return;
225 gdb_do_syscall(complete, "rename,%s,%s", oname, olen, nname, nlen);
228 static void gdb_system(CPUState *cs, gdb_syscall_complete_cb complete,
229 target_ulong cmd, target_ulong cmd_len)
231 int len = validate_strlen(cs, cmd, cmd_len);
232 if (len < 0) {
233 complete(cs, -1, -len);
234 return;
237 gdb_do_syscall(complete, "system,%s", cmd, len);
240 static void gdb_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
241 target_ulong tv_addr, target_ulong tz_addr)
243 gdb_do_syscall(complete, "gettimeofday,%x,%x", tv_addr, tz_addr);
247 * Host semihosting syscall implementations.
250 static void host_open(CPUState *cs, gdb_syscall_complete_cb complete,
251 target_ulong fname, target_ulong fname_len,
252 int gdb_flags, int mode)
254 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
255 char *p;
256 int ret, host_flags = O_BINARY;
258 ret = validate_lock_user_string(&p, cs, fname, fname_len);
259 if (ret < 0) {
260 complete(cs, -1, -ret);
261 return;
264 if (gdb_flags & GDB_O_WRONLY) {
265 host_flags |= O_WRONLY;
266 } else if (gdb_flags & GDB_O_RDWR) {
267 host_flags |= O_RDWR;
268 } else {
269 host_flags |= O_RDONLY;
271 if (gdb_flags & GDB_O_CREAT) {
272 host_flags |= O_CREAT;
274 if (gdb_flags & GDB_O_TRUNC) {
275 host_flags |= O_TRUNC;
277 if (gdb_flags & GDB_O_EXCL) {
278 host_flags |= O_EXCL;
281 ret = open(p, host_flags, mode);
282 if (ret < 0) {
283 complete(cs, -1, errno);
284 } else {
285 int guestfd = alloc_guestfd();
286 associate_guestfd(guestfd, ret);
287 complete(cs, guestfd, 0);
289 unlock_user(p, fname, 0);
292 static void host_close(CPUState *cs, gdb_syscall_complete_cb complete,
293 GuestFD *gf)
296 * Only close the underlying host fd if it's one we opened on behalf
297 * of the guest in SYS_OPEN.
299 if (gf->hostfd != STDIN_FILENO &&
300 gf->hostfd != STDOUT_FILENO &&
301 gf->hostfd != STDERR_FILENO &&
302 close(gf->hostfd) < 0) {
303 complete(cs, -1, errno);
304 } else {
305 complete(cs, 0, 0);
309 static void host_read(CPUState *cs, gdb_syscall_complete_cb complete,
310 GuestFD *gf, target_ulong buf, target_ulong len)
312 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
313 void *ptr = lock_user(VERIFY_WRITE, buf, len, 0);
314 ssize_t ret;
316 if (!ptr) {
317 complete(cs, -1, EFAULT);
318 return;
320 ret = RETRY_ON_EINTR(read(gf->hostfd, ptr, len));
321 if (ret == -1) {
322 unlock_user(ptr, buf, 0);
323 complete(cs, -1, errno);
324 } else {
325 unlock_user(ptr, buf, ret);
326 complete(cs, ret, 0);
330 static void host_write(CPUState *cs, gdb_syscall_complete_cb complete,
331 GuestFD *gf, target_ulong buf, target_ulong len)
333 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
334 void *ptr = lock_user(VERIFY_READ, buf, len, 1);
335 ssize_t ret;
337 if (!ptr) {
338 complete(cs, -1, EFAULT);
339 return;
341 ret = write(gf->hostfd, ptr, len);
342 unlock_user(ptr, buf, 0);
343 complete(cs, ret, ret == -1 ? errno : 0);
346 static void host_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
347 GuestFD *gf, int64_t off, int whence)
349 /* So far, all hosts use the same values. */
350 QEMU_BUILD_BUG_ON(GDB_SEEK_SET != SEEK_SET);
351 QEMU_BUILD_BUG_ON(GDB_SEEK_CUR != SEEK_CUR);
352 QEMU_BUILD_BUG_ON(GDB_SEEK_END != SEEK_END);
354 off_t ret = off;
355 int err = 0;
357 if (ret == off) {
358 ret = lseek(gf->hostfd, ret, whence);
359 if (ret == -1) {
360 err = errno;
362 } else {
363 ret = -1;
364 err = EINVAL;
366 complete(cs, ret, err);
369 static void host_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
370 GuestFD *gf)
372 int ret = isatty(gf->hostfd);
373 complete(cs, ret, ret ? 0 : errno);
376 static void host_flen(CPUState *cs, gdb_syscall_complete_cb complete,
377 GuestFD *gf)
379 struct stat buf;
381 if (fstat(gf->hostfd, &buf) < 0) {
382 complete(cs, -1, errno);
383 } else {
384 complete(cs, buf.st_size, 0);
388 static void host_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
389 GuestFD *gf, target_ulong addr)
391 struct stat buf;
392 int ret;
394 ret = fstat(gf->hostfd, &buf);
395 if (ret) {
396 complete(cs, -1, errno);
397 return;
399 ret = copy_stat_to_user(cs, addr, &buf);
400 complete(cs, ret ? -1 : 0, ret ? -ret : 0);
403 static void host_stat(CPUState *cs, gdb_syscall_complete_cb complete,
404 target_ulong fname, target_ulong fname_len,
405 target_ulong addr)
407 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
408 struct stat buf;
409 char *name;
410 int ret, err;
412 ret = validate_lock_user_string(&name, cs, fname, fname_len);
413 if (ret < 0) {
414 complete(cs, -1, -ret);
415 return;
418 ret = stat(name, &buf);
419 if (ret) {
420 err = errno;
421 } else {
422 ret = copy_stat_to_user(cs, addr, &buf);
423 err = 0;
424 if (ret < 0) {
425 err = -ret;
426 ret = -1;
429 unlock_user(name, fname, 0);
430 complete(cs, ret, err);
433 static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete,
434 target_ulong fname, target_ulong fname_len)
436 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
437 char *p;
438 int ret;
440 ret = validate_lock_user_string(&p, cs, fname, fname_len);
441 if (ret < 0) {
442 complete(cs, -1, -ret);
443 return;
446 ret = remove(p);
447 unlock_user(p, fname, 0);
448 complete(cs, ret, ret ? errno : 0);
451 static void host_rename(CPUState *cs, gdb_syscall_complete_cb complete,
452 target_ulong oname, target_ulong oname_len,
453 target_ulong nname, target_ulong nname_len)
455 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
456 char *ostr, *nstr;
457 int ret;
459 ret = validate_lock_user_string(&ostr, cs, oname, oname_len);
460 if (ret < 0) {
461 complete(cs, -1, -ret);
462 return;
464 ret = validate_lock_user_string(&nstr, cs, nname, nname_len);
465 if (ret < 0) {
466 unlock_user(ostr, oname, 0);
467 complete(cs, -1, -ret);
468 return;
471 ret = rename(ostr, nstr);
472 unlock_user(ostr, oname, 0);
473 unlock_user(nstr, nname, 0);
474 complete(cs, ret, ret ? errno : 0);
477 static void host_system(CPUState *cs, gdb_syscall_complete_cb complete,
478 target_ulong cmd, target_ulong cmd_len)
480 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
481 char *p;
482 int ret;
484 ret = validate_lock_user_string(&p, cs, cmd, cmd_len);
485 if (ret < 0) {
486 complete(cs, -1, -ret);
487 return;
490 ret = system(p);
491 unlock_user(p, cmd, 0);
492 complete(cs, ret, ret == -1 ? errno : 0);
495 static void host_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
496 target_ulong tv_addr, target_ulong tz_addr)
498 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
499 struct gdb_timeval *p;
500 int64_t rt;
502 /* GDB fails on non-null TZ, so be consistent. */
503 if (tz_addr != 0) {
504 complete(cs, -1, EINVAL);
505 return;
508 p = lock_user(VERIFY_WRITE, tv_addr, sizeof(struct gdb_timeval), 0);
509 if (!p) {
510 complete(cs, -1, EFAULT);
511 return;
514 /* TODO: Like stat, gdb always produces big-endian results; match it. */
515 rt = g_get_real_time();
516 p->tv_sec = cpu_to_be32(rt / G_USEC_PER_SEC);
517 p->tv_usec = cpu_to_be64(rt % G_USEC_PER_SEC);
518 unlock_user(p, tv_addr, sizeof(struct gdb_timeval));
521 #ifndef CONFIG_USER_ONLY
522 static void host_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
523 GuestFD *gf, GIOCondition cond, int timeout)
526 * Since this is only used by xtensa in system mode, and stdio is
527 * handled through GuestFDConsole, and there are no semihosting
528 * system calls for sockets and the like, that means this descriptor
529 * must be a normal file. Normal files never block and are thus
530 * always ready.
532 complete(cs, cond & (G_IO_IN | G_IO_OUT), 0);
534 #endif
537 * Static file semihosting syscall implementations.
540 static void staticfile_read(CPUState *cs, gdb_syscall_complete_cb complete,
541 GuestFD *gf, target_ulong buf, target_ulong len)
543 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
544 target_ulong rest = gf->staticfile.len - gf->staticfile.off;
545 void *ptr;
547 if (len > rest) {
548 len = rest;
550 ptr = lock_user(VERIFY_WRITE, buf, len, 0);
551 if (!ptr) {
552 complete(cs, -1, EFAULT);
553 return;
555 memcpy(ptr, gf->staticfile.data + gf->staticfile.off, len);
556 gf->staticfile.off += len;
557 unlock_user(ptr, buf, len);
558 complete(cs, len, 0);
561 static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
562 GuestFD *gf, int64_t off, int gdb_whence)
564 int64_t ret;
566 switch (gdb_whence) {
567 case GDB_SEEK_SET:
568 ret = off;
569 break;
570 case GDB_SEEK_CUR:
571 ret = gf->staticfile.off + off;
572 break;
573 case GDB_SEEK_END:
574 ret = gf->staticfile.len + off;
575 break;
576 default:
577 ret = -1;
578 break;
580 if (ret >= 0 && ret <= gf->staticfile.len) {
581 gf->staticfile.off = ret;
582 complete(cs, ret, 0);
583 } else {
584 complete(cs, -1, EINVAL);
588 static void staticfile_flen(CPUState *cs, gdb_syscall_complete_cb complete,
589 GuestFD *gf)
591 complete(cs, gf->staticfile.len, 0);
595 * Console semihosting syscall implementations.
598 static void console_read(CPUState *cs, gdb_syscall_complete_cb complete,
599 GuestFD *gf, target_ulong buf, target_ulong len)
601 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
602 char *ptr;
603 int ret;
605 ptr = lock_user(VERIFY_WRITE, buf, len, 0);
606 if (!ptr) {
607 complete(cs, -1, EFAULT);
608 return;
610 ret = qemu_semihosting_console_read(cs, ptr, len);
611 unlock_user(ptr, buf, ret);
612 complete(cs, ret, 0);
615 static void console_write(CPUState *cs, gdb_syscall_complete_cb complete,
616 GuestFD *gf, target_ulong buf, target_ulong len)
618 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
619 char *ptr = lock_user(VERIFY_READ, buf, len, 1);
620 int ret;
622 if (!ptr) {
623 complete(cs, -1, EFAULT);
624 return;
626 ret = qemu_semihosting_console_write(ptr, len);
627 unlock_user(ptr, buf, 0);
628 complete(cs, ret ? ret : -1, ret ? 0 : EIO);
631 static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
632 GuestFD *gf, target_ulong addr)
634 static const struct stat tty_buf = {
635 .st_mode = 020666, /* S_IFCHR, ugo+rw */
636 .st_rdev = 5, /* makedev(5, 0) -- linux /dev/tty */
638 int ret;
640 ret = copy_stat_to_user(cs, addr, &tty_buf);
641 complete(cs, ret ? -1 : 0, ret ? -ret : 0);
644 #ifndef CONFIG_USER_ONLY
645 static void console_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
646 GuestFD *gf, GIOCondition cond, int timeout)
648 /* The semihosting console does not support urgent data or errors. */
649 cond &= G_IO_IN | G_IO_OUT;
652 * Since qemu_semihosting_console_write never blocks, we can
653 * consider output always ready -- leave G_IO_OUT alone.
654 * All that remains is to conditionally signal input ready.
655 * Since output ready causes an immediate return, only block
656 * for G_IO_IN alone.
658 * TODO: Implement proper timeout. For now, only support
659 * indefinite wait or immediate poll.
661 if (cond == G_IO_IN && timeout < 0) {
662 qemu_semihosting_console_block_until_ready(cs);
663 /* We returned -- input must be ready. */
664 } else if ((cond & G_IO_IN) && !qemu_semihosting_console_ready()) {
665 cond &= ~G_IO_IN;
668 complete(cs, cond, 0);
670 #endif
673 * Syscall entry points.
676 void semihost_sys_open(CPUState *cs, gdb_syscall_complete_cb complete,
677 target_ulong fname, target_ulong fname_len,
678 int gdb_flags, int mode)
680 if (use_gdb_syscalls()) {
681 gdb_open(cs, complete, fname, fname_len, gdb_flags, mode);
682 } else {
683 host_open(cs, complete, fname, fname_len, gdb_flags, mode);
687 void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
689 GuestFD *gf = get_guestfd(fd);
691 if (!gf) {
692 complete(cs, -1, EBADF);
693 return;
695 switch (gf->type) {
696 case GuestFDGDB:
697 gdb_close(cs, complete, gf);
698 break;
699 case GuestFDHost:
700 host_close(cs, complete, gf);
701 break;
702 case GuestFDStatic:
703 case GuestFDConsole:
704 complete(cs, 0, 0);
705 break;
706 default:
707 g_assert_not_reached();
709 dealloc_guestfd(fd);
712 void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete,
713 GuestFD *gf, target_ulong buf, target_ulong len)
716 * Bound length for 64-bit guests on 32-bit hosts, not overlowing ssize_t.
717 * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
718 * idea to do this unconditionally.
720 if (len > INT32_MAX) {
721 len = INT32_MAX;
723 switch (gf->type) {
724 case GuestFDGDB:
725 gdb_read(cs, complete, gf, buf, len);
726 break;
727 case GuestFDHost:
728 host_read(cs, complete, gf, buf, len);
729 break;
730 case GuestFDStatic:
731 staticfile_read(cs, complete, gf, buf, len);
732 break;
733 case GuestFDConsole:
734 console_read(cs, complete, gf, buf, len);
735 break;
736 default:
737 g_assert_not_reached();
741 void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete,
742 int fd, target_ulong buf, target_ulong len)
744 GuestFD *gf = get_guestfd(fd);
746 if (gf) {
747 semihost_sys_read_gf(cs, complete, gf, buf, len);
748 } else {
749 complete(cs, -1, EBADF);
753 void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete,
754 GuestFD *gf, target_ulong buf, target_ulong len)
757 * Bound length for 64-bit guests on 32-bit hosts, not overlowing ssize_t.
758 * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
759 * idea to do this unconditionally.
761 if (len > INT32_MAX) {
762 len = INT32_MAX;
764 switch (gf->type) {
765 case GuestFDGDB:
766 gdb_write(cs, complete, gf, buf, len);
767 break;
768 case GuestFDHost:
769 host_write(cs, complete, gf, buf, len);
770 break;
771 case GuestFDConsole:
772 console_write(cs, complete, gf, buf, len);
773 break;
774 case GuestFDStatic:
775 /* Static files are never open for writing: EBADF. */
776 complete(cs, -1, EBADF);
777 break;
778 default:
779 g_assert_not_reached();
783 void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete,
784 int fd, target_ulong buf, target_ulong len)
786 GuestFD *gf = get_guestfd(fd);
788 if (gf) {
789 semihost_sys_write_gf(cs, complete, gf, buf, len);
790 } else {
791 complete(cs, -1, EBADF);
795 void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
796 int fd, int64_t off, int gdb_whence)
798 GuestFD *gf = get_guestfd(fd);
800 if (!gf) {
801 complete(cs, -1, EBADF);
802 return;
804 switch (gf->type) {
805 case GuestFDGDB:
806 gdb_lseek(cs, complete, gf, off, gdb_whence);
807 return;
808 case GuestFDHost:
809 host_lseek(cs, complete, gf, off, gdb_whence);
810 break;
811 case GuestFDStatic:
812 staticfile_lseek(cs, complete, gf, off, gdb_whence);
813 break;
814 case GuestFDConsole:
815 complete(cs, -1, ESPIPE);
816 break;
817 default:
818 g_assert_not_reached();
822 void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
824 GuestFD *gf = get_guestfd(fd);
826 if (!gf) {
827 complete(cs, 0, EBADF);
828 return;
830 switch (gf->type) {
831 case GuestFDGDB:
832 gdb_isatty(cs, complete, gf);
833 break;
834 case GuestFDHost:
835 host_isatty(cs, complete, gf);
836 break;
837 case GuestFDStatic:
838 complete(cs, 0, ENOTTY);
839 break;
840 case GuestFDConsole:
841 complete(cs, 1, 0);
842 break;
843 default:
844 g_assert_not_reached();
848 void semihost_sys_flen(CPUState *cs, gdb_syscall_complete_cb fstat_cb,
849 gdb_syscall_complete_cb flen_cb, int fd,
850 target_ulong fstat_addr)
852 GuestFD *gf = get_guestfd(fd);
854 if (!gf) {
855 flen_cb(cs, -1, EBADF);
856 return;
858 switch (gf->type) {
859 case GuestFDGDB:
860 gdb_fstat(cs, fstat_cb, gf, fstat_addr);
861 break;
862 case GuestFDHost:
863 host_flen(cs, flen_cb, gf);
864 break;
865 case GuestFDStatic:
866 staticfile_flen(cs, flen_cb, gf);
867 break;
868 case GuestFDConsole:
869 default:
870 g_assert_not_reached();
874 void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
875 int fd, target_ulong addr)
877 GuestFD *gf = get_guestfd(fd);
879 if (!gf) {
880 complete(cs, -1, EBADF);
881 return;
883 switch (gf->type) {
884 case GuestFDGDB:
885 gdb_fstat(cs, complete, gf, addr);
886 break;
887 case GuestFDHost:
888 host_fstat(cs, complete, gf, addr);
889 break;
890 case GuestFDConsole:
891 console_fstat(cs, complete, gf, addr);
892 break;
893 case GuestFDStatic:
894 default:
895 g_assert_not_reached();
899 void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete,
900 target_ulong fname, target_ulong fname_len,
901 target_ulong addr)
903 if (use_gdb_syscalls()) {
904 gdb_stat(cs, complete, fname, fname_len, addr);
905 } else {
906 host_stat(cs, complete, fname, fname_len, addr);
910 void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete,
911 target_ulong fname, target_ulong fname_len)
913 if (use_gdb_syscalls()) {
914 gdb_remove(cs, complete, fname, fname_len);
915 } else {
916 host_remove(cs, complete, fname, fname_len);
920 void semihost_sys_rename(CPUState *cs, gdb_syscall_complete_cb complete,
921 target_ulong oname, target_ulong oname_len,
922 target_ulong nname, target_ulong nname_len)
924 if (use_gdb_syscalls()) {
925 gdb_rename(cs, complete, oname, oname_len, nname, nname_len);
926 } else {
927 host_rename(cs, complete, oname, oname_len, nname, nname_len);
931 void semihost_sys_system(CPUState *cs, gdb_syscall_complete_cb complete,
932 target_ulong cmd, target_ulong cmd_len)
934 if (use_gdb_syscalls()) {
935 gdb_system(cs, complete, cmd, cmd_len);
936 } else {
937 host_system(cs, complete, cmd, cmd_len);
941 void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
942 target_ulong tv_addr, target_ulong tz_addr)
944 if (use_gdb_syscalls()) {
945 gdb_gettimeofday(cs, complete, tv_addr, tz_addr);
946 } else {
947 host_gettimeofday(cs, complete, tv_addr, tz_addr);
951 #ifndef CONFIG_USER_ONLY
952 void semihost_sys_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
953 int fd, GIOCondition cond, int timeout)
955 GuestFD *gf = get_guestfd(fd);
957 if (!gf) {
958 complete(cs, G_IO_NVAL, 1);
959 return;
961 switch (gf->type) {
962 case GuestFDGDB:
963 complete(cs, G_IO_NVAL, 1);
964 break;
965 case GuestFDHost:
966 host_poll_one(cs, complete, gf, cond, timeout);
967 break;
968 case GuestFDConsole:
969 console_poll_one(cs, complete, gf, cond, timeout);
970 break;
971 case GuestFDStatic:
972 default:
973 g_assert_not_reached();
976 #endif