master
c 984 lines 25.8 KB
Raw
1 /*
2 * Syscall implementations for semihosting.
3 *
4 * Copyright (c) 2022 Linaro
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "qemu/log.h"
11 #include "gdbstub/syscalls.h"
12 #include "semihosting/guestfd.h"
13 #include "semihosting/syscalls.h"
14 #include "semihosting/console.h"
15 #ifdef CONFIG_USER_ONLY
16 #include "qemu.h"
17 #else
18 #include "semihosting/uaccess.h"
19 #endif
20
21
22 /*
23 * Validate or compute the length of the string (including terminator).
24 */
25 static int validate_strlen(CPUState *cs, vaddr str, uint64_t tlen)
26 {
27 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
28 char c;
29
30 if (tlen == 0) {
31 ssize_t slen = target_strlen(str);
32
33 if (slen < 0) {
34 return -EFAULT;
35 }
36 if (slen >= INT32_MAX) {
37 return -ENAMETOOLONG;
38 }
39 return slen + 1;
40 }
41 if (tlen > INT32_MAX) {
42 return -ENAMETOOLONG;
43 }
44 if (get_user_u8(c, str + tlen - 1)) {
45 return -EFAULT;
46 }
47 if (c != 0) {
48 return -EINVAL;
49 }
50 return tlen;
51 }
52
53 static int validate_lock_user_string(char **pstr, CPUState *cs,
54 vaddr tstr, uint64_t tlen)
55 {
56 int ret = validate_strlen(cs, tstr, tlen);
57 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
58 char *str = NULL;
59
60 if (ret > 0) {
61 str = lock_user(VERIFY_READ, tstr, ret, true);
62 ret = str ? 0 : -EFAULT;
63 }
64 *pstr = str;
65 return ret;
66 }
67
68 /*
69 * TODO: Note that gdb always stores the stat structure big-endian.
70 * So far, that's ok, as the only two targets using this are also
71 * big-endian. Until we do something with gdb, also produce the
72 * same big-endian result from the host.
73 */
74 static int copy_stat_to_user(CPUState *cs, vaddr addr,
75 const struct stat *s)
76 {
77 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
78 struct gdb_stat *p;
79
80 if (s->st_dev != (uint32_t)s->st_dev ||
81 s->st_ino != (uint32_t)s->st_ino) {
82 return -EOVERFLOW;
83 }
84
85 p = lock_user(VERIFY_WRITE, addr, sizeof(struct gdb_stat), 0);
86 if (!p) {
87 return -EFAULT;
88 }
89
90 p->gdb_st_dev = cpu_to_be32(s->st_dev);
91 p->gdb_st_ino = cpu_to_be32(s->st_ino);
92 p->gdb_st_mode = cpu_to_be32(s->st_mode);
93 p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
94 p->gdb_st_uid = cpu_to_be32(s->st_uid);
95 p->gdb_st_gid = cpu_to_be32(s->st_gid);
96 p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
97 p->gdb_st_size = cpu_to_be64(s->st_size);
98 #ifdef _WIN32
99 /* Windows stat is missing some fields. */
100 p->gdb_st_blksize = 0;
101 p->gdb_st_blocks = 0;
102 #else
103 p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
104 p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
105 #endif
106 p->gdb_st_atime = cpu_to_be32(s->st_atime);
107 p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
108 p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
109
110 unlock_user(p, addr, sizeof(struct gdb_stat));
111 return 0;
112 }
113
114 /*
115 * GDB semihosting syscall implementations.
116 */
117
118 static gdb_syscall_complete_cb gdb_open_complete;
119
120 static void gdb_open_cb(CPUState *cs, uint64_t ret, int err)
121 {
122 if (!err) {
123 int guestfd = alloc_guestfd();
124 associate_guestfd(guestfd, ret);
125 ret = guestfd;
126 }
127 gdb_open_complete(cs, ret, err);
128 }
129
130 static void gdb_open(CPUState *cs, gdb_syscall_complete_cb complete,
131 vaddr fname, uint64_t fname_len,
132 int gdb_flags, int mode)
133 {
134 int len = validate_strlen(cs, fname, fname_len);
135 if (len < 0) {
136 complete(cs, -1, -len);
137 return;
138 }
139
140 gdb_open_complete = complete;
141 gdb_do_syscall(gdb_open_cb, "open,%s,%x,%x",
142 (vaddr)fname, (uint32_t)len,
143 (uint32_t)gdb_flags, (uint32_t)mode);
144 }
145
146 static void gdb_close(CPUState *cs, gdb_syscall_complete_cb complete,
147 GuestFD *gf)
148 {
149 gdb_do_syscall(complete, "close,%x", (uint32_t)gf->hostfd);
150 }
151
152 static void gdb_read(CPUState *cs, gdb_syscall_complete_cb complete,
153 GuestFD *gf, vaddr buf, uint64_t len)
154 {
155 gdb_do_syscall(complete, "read,%x,%lx,%lx",
156 (uint32_t)gf->hostfd, (vaddr)buf, (uint64_t)len);
157 }
158
159 static void gdb_write(CPUState *cs, gdb_syscall_complete_cb complete,
160 GuestFD *gf, vaddr buf, uint64_t len)
161 {
162 gdb_do_syscall(complete, "write,%x,%lx,%lx",
163 (uint32_t)gf->hostfd, (vaddr)buf, (uint64_t)len);
164 }
165
166 static void gdb_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
167 GuestFD *gf, int64_t off, int gdb_whence)
168 {
169 gdb_do_syscall(complete, "lseek,%x,%lx,%x",
170 (uint32_t)gf->hostfd, off, (uint32_t)gdb_whence);
171 }
172
173 static void gdb_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
174 GuestFD *gf)
175 {
176 gdb_do_syscall(complete, "isatty,%x", (uint32_t)gf->hostfd);
177 }
178
179 static void gdb_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
180 GuestFD *gf, vaddr addr)
181 {
182 gdb_do_syscall(complete, "fstat,%x,%lx",
183 (uint32_t)gf->hostfd, (vaddr)addr);
184 }
185
186 static void gdb_stat(CPUState *cs, gdb_syscall_complete_cb complete,
187 vaddr fname, uint64_t fname_len,
188 vaddr addr)
189 {
190 int len = validate_strlen(cs, fname, fname_len);
191 if (len < 0) {
192 complete(cs, -1, -len);
193 return;
194 }
195
196 gdb_do_syscall(complete, "stat,%s,%lx",
197 (vaddr)fname, (uint32_t)len, (vaddr)addr);
198 }
199
200 static void gdb_remove(CPUState *cs, gdb_syscall_complete_cb complete,
201 vaddr fname, uint64_t fname_len)
202 {
203 int len = validate_strlen(cs, fname, fname_len);
204 if (len < 0) {
205 complete(cs, -1, -len);
206 return;
207 }
208
209 gdb_do_syscall(complete, "unlink,%s", (vaddr)fname, (uint32_t)len);
210 }
211
212 static void gdb_rename(CPUState *cs, gdb_syscall_complete_cb complete,
213 vaddr oname, uint64_t oname_len,
214 vaddr nname, uint64_t nname_len)
215 {
216 int olen, nlen;
217
218 olen = validate_strlen(cs, oname, oname_len);
219 if (olen < 0) {
220 complete(cs, -1, -olen);
221 return;
222 }
223 nlen = validate_strlen(cs, nname, nname_len);
224 if (nlen < 0) {
225 complete(cs, -1, -nlen);
226 return;
227 }
228
229 gdb_do_syscall(complete, "rename,%s,%s",
230 (vaddr)oname, (uint32_t)olen,
231 (vaddr)nname, (uint32_t)nlen);
232 }
233
234 static void gdb_system(CPUState *cs, gdb_syscall_complete_cb complete,
235 vaddr cmd, uint64_t cmd_len)
236 {
237 int len = validate_strlen(cs, cmd, cmd_len);
238 if (len < 0) {
239 complete(cs, -1, -len);
240 return;
241 }
242
243 gdb_do_syscall(complete, "system,%s", (vaddr)cmd, (uint32_t)len);
244 }
245
246 static void gdb_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
247 vaddr tv_addr, vaddr tz_addr)
248 {
249 gdb_do_syscall(complete, "gettimeofday,%lx,%lx",
250 (vaddr)tv_addr, (vaddr)tz_addr);
251 }
252
253 /*
254 * Host semihosting syscall implementations.
255 */
256
257 static void host_open(CPUState *cs, gdb_syscall_complete_cb complete,
258 vaddr fname, uint64_t fname_len,
259 int gdb_flags, int mode)
260 {
261 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
262 char *p;
263 int ret, host_flags = O_BINARY;
264
265 ret = validate_lock_user_string(&p, cs, fname, fname_len);
266 if (ret < 0) {
267 complete(cs, -1, -ret);
268 return;
269 }
270
271 if (gdb_flags & GDB_O_WRONLY) {
272 host_flags |= O_WRONLY;
273 } else if (gdb_flags & GDB_O_RDWR) {
274 host_flags |= O_RDWR;
275 } else {
276 host_flags |= O_RDONLY;
277 }
278 if (gdb_flags & GDB_O_CREAT) {
279 host_flags |= O_CREAT;
280 }
281 if (gdb_flags & GDB_O_TRUNC) {
282 host_flags |= O_TRUNC;
283 }
284 if (gdb_flags & GDB_O_EXCL) {
285 host_flags |= O_EXCL;
286 }
287
288 ret = open(p, host_flags, mode);
289 if (ret < 0) {
290 qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to open %s\n", __func__, p);
291 complete(cs, -1, errno);
292 } else {
293 int guestfd = alloc_guestfd();
294 associate_guestfd(guestfd, ret);
295 complete(cs, guestfd, 0);
296 }
297 unlock_user(p, fname, 0);
298 }
299
300 static void host_close(CPUState *cs, gdb_syscall_complete_cb complete,
301 GuestFD *gf)
302 {
303 /*
304 * Only close the underlying host fd if it's one we opened on behalf
305 * of the guest in SYS_OPEN.
306 */
307 if (gf->hostfd != STDIN_FILENO &&
308 gf->hostfd != STDOUT_FILENO &&
309 gf->hostfd != STDERR_FILENO &&
310 close(gf->hostfd) < 0) {
311 complete(cs, -1, errno);
312 } else {
313 complete(cs, 0, 0);
314 }
315 }
316
317 static void host_read(CPUState *cs, gdb_syscall_complete_cb complete,
318 GuestFD *gf, vaddr buf, uint64_t len)
319 {
320 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
321 void *ptr = lock_user(VERIFY_WRITE, buf, len, 0);
322 ssize_t ret;
323
324 if (!ptr) {
325 complete(cs, -1, EFAULT);
326 return;
327 }
328 ret = RETRY_ON_EINTR(read(gf->hostfd, ptr, len));
329 if (ret == -1) {
330 unlock_user(ptr, buf, 0);
331 complete(cs, -1, errno);
332 } else {
333 unlock_user(ptr, buf, ret);
334 complete(cs, ret, 0);
335 }
336 }
337
338 static void host_write(CPUState *cs, gdb_syscall_complete_cb complete,
339 GuestFD *gf, vaddr buf, uint64_t len)
340 {
341 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
342 void *ptr = lock_user(VERIFY_READ, buf, len, 1);
343 ssize_t ret;
344
345 if (!ptr) {
346 complete(cs, -1, EFAULT);
347 return;
348 }
349 ret = write(gf->hostfd, ptr, len);
350 unlock_user(ptr, buf, 0);
351 complete(cs, ret, ret == -1 ? errno : 0);
352 }
353
354 static void host_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
355 GuestFD *gf, int64_t off, int whence)
356 {
357 /* So far, all hosts use the same values. */
358 QEMU_BUILD_BUG_ON(GDB_SEEK_SET != SEEK_SET);
359 QEMU_BUILD_BUG_ON(GDB_SEEK_CUR != SEEK_CUR);
360 QEMU_BUILD_BUG_ON(GDB_SEEK_END != SEEK_END);
361
362 off_t ret = off;
363 int err = 0;
364
365 if (ret == off) {
366 ret = lseek(gf->hostfd, ret, whence);
367 if (ret == -1) {
368 err = errno;
369 }
370 } else {
371 ret = -1;
372 err = EINVAL;
373 }
374 complete(cs, ret, err);
375 }
376
377 static void host_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
378 GuestFD *gf)
379 {
380 int ret = isatty(gf->hostfd);
381 complete(cs, ret, ret ? 0 : errno);
382 }
383
384 static void host_flen(CPUState *cs, gdb_syscall_complete_cb complete,
385 GuestFD *gf)
386 {
387 struct stat buf;
388
389 if (fstat(gf->hostfd, &buf) < 0) {
390 complete(cs, -1, errno);
391 } else {
392 complete(cs, buf.st_size, 0);
393 }
394 }
395
396 static void host_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
397 GuestFD *gf, vaddr addr)
398 {
399 struct stat buf;
400 int ret;
401
402 ret = fstat(gf->hostfd, &buf);
403 if (ret) {
404 complete(cs, -1, errno);
405 return;
406 }
407 ret = copy_stat_to_user(cs, addr, &buf);
408 complete(cs, ret ? -1 : 0, ret ? -ret : 0);
409 }
410
411 static void host_stat(CPUState *cs, gdb_syscall_complete_cb complete,
412 vaddr fname, uint64_t fname_len,
413 vaddr addr)
414 {
415 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
416 struct stat buf;
417 char *name;
418 int ret, err;
419
420 ret = validate_lock_user_string(&name, cs, fname, fname_len);
421 if (ret < 0) {
422 complete(cs, -1, -ret);
423 return;
424 }
425
426 ret = stat(name, &buf);
427 if (ret) {
428 err = errno;
429 } else {
430 ret = copy_stat_to_user(cs, addr, &buf);
431 err = 0;
432 if (ret < 0) {
433 err = -ret;
434 ret = -1;
435 }
436 }
437 unlock_user(name, fname, 0);
438 complete(cs, ret, err);
439 }
440
441 static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete,
442 vaddr fname, uint64_t fname_len)
443 {
444 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
445 char *p;
446 int ret;
447
448 ret = validate_lock_user_string(&p, cs, fname, fname_len);
449 if (ret < 0) {
450 complete(cs, -1, -ret);
451 return;
452 }
453
454 ret = remove(p);
455 unlock_user(p, fname, 0);
456 complete(cs, ret, ret ? errno : 0);
457 }
458
459 static void host_rename(CPUState *cs, gdb_syscall_complete_cb complete,
460 vaddr oname, uint64_t oname_len,
461 vaddr nname, uint64_t nname_len)
462 {
463 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
464 char *ostr, *nstr;
465 int ret;
466
467 ret = validate_lock_user_string(&ostr, cs, oname, oname_len);
468 if (ret < 0) {
469 complete(cs, -1, -ret);
470 return;
471 }
472 ret = validate_lock_user_string(&nstr, cs, nname, nname_len);
473 if (ret < 0) {
474 unlock_user(ostr, oname, 0);
475 complete(cs, -1, -ret);
476 return;
477 }
478
479 ret = rename(ostr, nstr);
480 unlock_user(ostr, oname, 0);
481 unlock_user(nstr, nname, 0);
482 complete(cs, ret, ret ? errno : 0);
483 }
484
485 static void host_system(CPUState *cs, gdb_syscall_complete_cb complete,
486 vaddr cmd, uint64_t cmd_len)
487 {
488 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
489 char *p;
490 int ret;
491
492 ret = validate_lock_user_string(&p, cs, cmd, cmd_len);
493 if (ret < 0) {
494 complete(cs, -1, -ret);
495 return;
496 }
497
498 ret = system(p);
499 unlock_user(p, cmd, 0);
500 complete(cs, ret, ret == -1 ? errno : 0);
501 }
502
503 static void host_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
504 vaddr tv_addr, vaddr tz_addr)
505 {
506 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
507 struct gdb_timeval *p;
508 int64_t rt;
509
510 /* GDB fails on non-null TZ, so be consistent. */
511 if (tz_addr != 0) {
512 complete(cs, -1, EINVAL);
513 return;
514 }
515
516 p = lock_user(VERIFY_WRITE, tv_addr, sizeof(struct gdb_timeval), 0);
517 if (!p) {
518 complete(cs, -1, EFAULT);
519 return;
520 }
521
522 /* TODO: Like stat, gdb always produces big-endian results; match it. */
523 rt = g_get_real_time();
524 p->tv_sec = cpu_to_be32(rt / G_USEC_PER_SEC);
525 p->tv_usec = cpu_to_be64(rt % G_USEC_PER_SEC);
526 unlock_user(p, tv_addr, sizeof(struct gdb_timeval));
527 }
528
529 #ifndef CONFIG_USER_ONLY
530 static void host_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
531 GuestFD *gf, GIOCondition cond, int timeout)
532 {
533 /*
534 * Since this is only used by xtensa in system mode, and stdio is
535 * handled through GuestFDConsole, and there are no semihosting
536 * system calls for sockets and the like, that means this descriptor
537 * must be a normal file. Normal files never block and are thus
538 * always ready.
539 */
540 complete(cs, cond & (G_IO_IN | G_IO_OUT), 0);
541 }
542 #endif
543
544 /*
545 * Static file semihosting syscall implementations.
546 */
547
548 static void staticfile_read(CPUState *cs, gdb_syscall_complete_cb complete,
549 GuestFD *gf, vaddr buf, uint64_t len)
550 {
551 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
552 uint64_t rest = gf->staticfile.len - gf->staticfile.off;
553 void *ptr;
554
555 if (len > rest) {
556 len = rest;
557 }
558 ptr = lock_user(VERIFY_WRITE, buf, len, 0);
559 if (!ptr) {
560 complete(cs, -1, EFAULT);
561 return;
562 }
563 memcpy(ptr, gf->staticfile.data + gf->staticfile.off, len);
564 gf->staticfile.off += len;
565 unlock_user(ptr, buf, len);
566 complete(cs, len, 0);
567 }
568
569 static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
570 GuestFD *gf, int64_t off, int gdb_whence)
571 {
572 int64_t ret;
573
574 switch (gdb_whence) {
575 case GDB_SEEK_SET:
576 ret = off;
577 break;
578 case GDB_SEEK_CUR:
579 ret = gf->staticfile.off + off;
580 break;
581 case GDB_SEEK_END:
582 ret = gf->staticfile.len + off;
583 break;
584 default:
585 ret = -1;
586 break;
587 }
588 if (ret >= 0 && ret <= gf->staticfile.len) {
589 gf->staticfile.off = ret;
590 complete(cs, ret, 0);
591 } else {
592 complete(cs, -1, EINVAL);
593 }
594 }
595
596 static void staticfile_flen(CPUState *cs, gdb_syscall_complete_cb complete,
597 GuestFD *gf)
598 {
599 complete(cs, gf->staticfile.len, 0);
600 }
601
602 /*
603 * Console semihosting syscall implementations.
604 */
605
606 static void console_read(CPUState *cs, gdb_syscall_complete_cb complete,
607 GuestFD *gf, vaddr buf, uint64_t len)
608 {
609 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
610 char *ptr;
611 int ret;
612
613 ptr = lock_user(VERIFY_WRITE, buf, len, 0);
614 if (!ptr) {
615 complete(cs, -1, EFAULT);
616 return;
617 }
618 ret = qemu_semihosting_console_read(cs, ptr, len);
619 unlock_user(ptr, buf, ret);
620 complete(cs, ret, 0);
621 }
622
623 static void console_write(CPUState *cs, gdb_syscall_complete_cb complete,
624 GuestFD *gf, vaddr buf, uint64_t len)
625 {
626 CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
627 char *ptr = lock_user(VERIFY_READ, buf, len, 1);
628 int ret;
629
630 if (!ptr) {
631 complete(cs, -1, EFAULT);
632 return;
633 }
634 ret = qemu_semihosting_console_write(ptr, len);
635 unlock_user(ptr, buf, 0);
636 complete(cs, ret ? ret : -1, ret ? 0 : EIO);
637 }
638
639 static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
640 GuestFD *gf, vaddr addr)
641 {
642 static const struct stat tty_buf = {
643 .st_mode = 020666, /* S_IFCHR, ugo+rw */
644 .st_rdev = 5, /* makedev(5, 0) -- linux /dev/tty */
645 };
646 int ret;
647
648 ret = copy_stat_to_user(cs, addr, &tty_buf);
649 complete(cs, ret ? -1 : 0, ret ? -ret : 0);
650 }
651
652 #ifndef CONFIG_USER_ONLY
653 static void console_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
654 GuestFD *gf, GIOCondition cond, int timeout)
655 {
656 /* The semihosting console does not support urgent data or errors. */
657 cond &= G_IO_IN | G_IO_OUT;
658
659 /*
660 * Since qemu_semihosting_console_write never blocks, we can
661 * consider output always ready -- leave G_IO_OUT alone.
662 * All that remains is to conditionally signal input ready.
663 * Since output ready causes an immediate return, only block
664 * for G_IO_IN alone.
665 *
666 * TODO: Implement proper timeout. For now, only support
667 * indefinite wait or immediate poll.
668 */
669 if (cond == G_IO_IN && timeout < 0) {
670 qemu_semihosting_console_block_until_ready(cs);
671 /* We returned -- input must be ready. */
672 } else if ((cond & G_IO_IN) && !qemu_semihosting_console_ready()) {
673 cond &= ~G_IO_IN;
674 }
675
676 complete(cs, cond, 0);
677 }
678 #endif
679
680 /*
681 * Syscall entry points.
682 */
683
684 void semihost_sys_open(CPUState *cs, gdb_syscall_complete_cb complete,
685 vaddr fname, uint64_t fname_len,
686 int gdb_flags, int mode)
687 {
688 if (use_gdb_syscalls()) {
689 gdb_open(cs, complete, fname, fname_len, gdb_flags, mode);
690 } else {
691 host_open(cs, complete, fname, fname_len, gdb_flags, mode);
692 }
693 }
694
695 void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
696 {
697 GuestFD *gf = get_guestfd(fd);
698
699 if (!gf) {
700 complete(cs, -1, EBADF);
701 return;
702 }
703 switch (gf->type) {
704 case GuestFDGDB:
705 gdb_close(cs, complete, gf);
706 break;
707 case GuestFDHost:
708 host_close(cs, complete, gf);
709 break;
710 case GuestFDStatic:
711 case GuestFDConsole:
712 complete(cs, 0, 0);
713 break;
714 default:
715 g_assert_not_reached();
716 }
717 dealloc_guestfd(fd);
718 }
719
720 void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete,
721 GuestFD *gf, vaddr buf, uint64_t len)
722 {
723 /*
724 * Bound length for 64-bit guests on 32-bit hosts, not overflowing ssize_t.
725 * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
726 * idea to do this unconditionally.
727 */
728 if (len > INT32_MAX) {
729 len = INT32_MAX;
730 }
731 switch (gf->type) {
732 case GuestFDGDB:
733 gdb_read(cs, complete, gf, buf, len);
734 break;
735 case GuestFDHost:
736 host_read(cs, complete, gf, buf, len);
737 break;
738 case GuestFDStatic:
739 staticfile_read(cs, complete, gf, buf, len);
740 break;
741 case GuestFDConsole:
742 console_read(cs, complete, gf, buf, len);
743 break;
744 default:
745 g_assert_not_reached();
746 }
747 }
748
749 void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete,
750 int fd, vaddr buf, uint64_t len)
751 {
752 GuestFD *gf = get_guestfd(fd);
753
754 if (gf) {
755 semihost_sys_read_gf(cs, complete, gf, buf, len);
756 } else {
757 complete(cs, -1, EBADF);
758 }
759 }
760
761 void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete,
762 GuestFD *gf, vaddr buf, uint64_t len)
763 {
764 /*
765 * Bound length for 64-bit guests on 32-bit hosts, not overflowing ssize_t.
766 * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
767 * idea to do this unconditionally.
768 */
769 if (len > INT32_MAX) {
770 len = INT32_MAX;
771 }
772 switch (gf->type) {
773 case GuestFDGDB:
774 gdb_write(cs, complete, gf, buf, len);
775 break;
776 case GuestFDHost:
777 host_write(cs, complete, gf, buf, len);
778 break;
779 case GuestFDConsole:
780 console_write(cs, complete, gf, buf, len);
781 break;
782 case GuestFDStatic:
783 /* Static files are never open for writing: EBADF. */
784 complete(cs, -1, EBADF);
785 break;
786 default:
787 g_assert_not_reached();
788 }
789 }
790
791 void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete,
792 int fd, vaddr buf, uint64_t len)
793 {
794 GuestFD *gf = get_guestfd(fd);
795
796 if (gf) {
797 semihost_sys_write_gf(cs, complete, gf, buf, len);
798 } else {
799 complete(cs, -1, EBADF);
800 }
801 }
802
803 void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
804 int fd, int64_t off, int gdb_whence)
805 {
806 GuestFD *gf = get_guestfd(fd);
807
808 if (!gf) {
809 complete(cs, -1, EBADF);
810 return;
811 }
812 switch (gf->type) {
813 case GuestFDGDB:
814 gdb_lseek(cs, complete, gf, off, gdb_whence);
815 return;
816 case GuestFDHost:
817 host_lseek(cs, complete, gf, off, gdb_whence);
818 break;
819 case GuestFDStatic:
820 staticfile_lseek(cs, complete, gf, off, gdb_whence);
821 break;
822 case GuestFDConsole:
823 complete(cs, -1, ESPIPE);
824 break;
825 default:
826 g_assert_not_reached();
827 }
828 }
829
830 void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
831 {
832 GuestFD *gf = get_guestfd(fd);
833
834 if (!gf) {
835 complete(cs, 0, EBADF);
836 return;
837 }
838 switch (gf->type) {
839 case GuestFDGDB:
840 gdb_isatty(cs, complete, gf);
841 break;
842 case GuestFDHost:
843 host_isatty(cs, complete, gf);
844 break;
845 case GuestFDStatic:
846 complete(cs, 0, ENOTTY);
847 break;
848 case GuestFDConsole:
849 complete(cs, 1, 0);
850 break;
851 default:
852 g_assert_not_reached();
853 }
854 }
855
856 void semihost_sys_flen(CPUState *cs, gdb_syscall_complete_cb fstat_cb,
857 gdb_syscall_complete_cb flen_cb, int fd,
858 vaddr fstat_addr)
859 {
860 GuestFD *gf = get_guestfd(fd);
861
862 if (!gf) {
863 flen_cb(cs, -1, EBADF);
864 return;
865 }
866 switch (gf->type) {
867 case GuestFDGDB:
868 gdb_fstat(cs, fstat_cb, gf, fstat_addr);
869 break;
870 case GuestFDHost:
871 host_flen(cs, flen_cb, gf);
872 break;
873 case GuestFDStatic:
874 staticfile_flen(cs, flen_cb, gf);
875 break;
876 case GuestFDConsole:
877 default:
878 g_assert_not_reached();
879 }
880 }
881
882 void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
883 int fd, vaddr addr)
884 {
885 GuestFD *gf = get_guestfd(fd);
886
887 if (!gf) {
888 complete(cs, -1, EBADF);
889 return;
890 }
891 switch (gf->type) {
892 case GuestFDGDB:
893 gdb_fstat(cs, complete, gf, addr);
894 break;
895 case GuestFDHost:
896 host_fstat(cs, complete, gf, addr);
897 break;
898 case GuestFDConsole:
899 console_fstat(cs, complete, gf, addr);
900 break;
901 case GuestFDStatic:
902 default:
903 g_assert_not_reached();
904 }
905 }
906
907 void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete,
908 vaddr fname, uint64_t fname_len,
909 vaddr addr)
910 {
911 if (use_gdb_syscalls()) {
912 gdb_stat(cs, complete, fname, fname_len, addr);
913 } else {
914 host_stat(cs, complete, fname, fname_len, addr);
915 }
916 }
917
918 void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete,
919 vaddr fname, uint64_t fname_len)
920 {
921 if (use_gdb_syscalls()) {
922 gdb_remove(cs, complete, fname, fname_len);
923 } else {
924 host_remove(cs, complete, fname, fname_len);
925 }
926 }
927
928 void semihost_sys_rename(CPUState *cs, gdb_syscall_complete_cb complete,
929 vaddr oname, uint64_t oname_len,
930 vaddr nname, uint64_t nname_len)
931 {
932 if (use_gdb_syscalls()) {
933 gdb_rename(cs, complete, oname, oname_len, nname, nname_len);
934 } else {
935 host_rename(cs, complete, oname, oname_len, nname, nname_len);
936 }
937 }
938
939 void semihost_sys_system(CPUState *cs, gdb_syscall_complete_cb complete,
940 vaddr cmd, uint64_t cmd_len)
941 {
942 if (use_gdb_syscalls()) {
943 gdb_system(cs, complete, cmd, cmd_len);
944 } else {
945 host_system(cs, complete, cmd, cmd_len);
946 }
947 }
948
949 void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
950 vaddr tv_addr, vaddr tz_addr)
951 {
952 if (use_gdb_syscalls()) {
953 gdb_gettimeofday(cs, complete, tv_addr, tz_addr);
954 } else {
955 host_gettimeofday(cs, complete, tv_addr, tz_addr);
956 }
957 }
958
959 #ifndef CONFIG_USER_ONLY
960 void semihost_sys_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
961 int fd, GIOCondition cond, int timeout)
962 {
963 GuestFD *gf = get_guestfd(fd);
964
965 if (!gf) {
966 complete(cs, G_IO_NVAL, 1);
967 return;
968 }
969 switch (gf->type) {
970 case GuestFDGDB:
971 complete(cs, G_IO_NVAL, 1);
972 break;
973 case GuestFDHost:
974 host_poll_one(cs, complete, gf, cond, timeout);
975 break;
976 case GuestFDConsole:
977 console_poll_one(cs, complete, gf, cond, timeout);
978 break;
979 case GuestFDStatic:
980 default:
981 g_assert_not_reached();
982 }
983 }
984 #endif