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