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 "cpu.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/softmmu-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, target_ulong str, target_ulong tlen) 26 { 27 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 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 target_ulong tstr, target_ulong tlen) 55 { 56 int ret = validate_strlen(cs, tstr, tlen); 57 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 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, target_ulong addr, 75 const struct stat *s) 76 { 77 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 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 target_ulong fname, target_ulong 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 (uint64_t)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, target_ulong buf, target_ulong len) 154 { 155 gdb_do_syscall(complete, "read,%x,%lx,%lx", 156 (uint32_t)gf->hostfd, (uint64_t)buf, (uint64_t)len); 157 } 158 159 static void gdb_write(CPUState *cs, gdb_syscall_complete_cb complete, 160 GuestFD *gf, target_ulong buf, target_ulong len) 161 { 162 gdb_do_syscall(complete, "write,%x,%lx,%lx", 163 (uint32_t)gf->hostfd, (uint64_t)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, target_ulong addr) 181 { 182 gdb_do_syscall(complete, "fstat,%x,%lx", 183 (uint32_t)gf->hostfd, (uint64_t)addr); 184 } 185 186 static void gdb_stat(CPUState *cs, gdb_syscall_complete_cb complete, 187 target_ulong fname, target_ulong fname_len, 188 target_ulong 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 (uint64_t)fname, (uint32_t)len, (uint64_t)addr); 198 } 199 200 static void gdb_remove(CPUState *cs, gdb_syscall_complete_cb complete, 201 target_ulong fname, target_ulong 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", (uint64_t)fname, (uint32_t)len); 210 } 211 212 static void gdb_rename(CPUState *cs, gdb_syscall_complete_cb complete, 213 target_ulong oname, target_ulong oname_len, 214 target_ulong nname, target_ulong 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 (uint64_t)oname, (uint32_t)olen, 231 (uint64_t)nname, (uint32_t)nlen); 232 } 233 234 static void gdb_system(CPUState *cs, gdb_syscall_complete_cb complete, 235 target_ulong cmd, target_ulong 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", (uint64_t)cmd, (uint32_t)len); 244 } 245 246 static void gdb_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, 247 target_ulong tv_addr, target_ulong tz_addr) 248 { 249 gdb_do_syscall(complete, "gettimeofday,%lx,%lx", 250 (uint64_t)tv_addr, (uint64_t)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 target_ulong fname, target_ulong fname_len, 259 int gdb_flags, int mode) 260 { 261 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 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 complete(cs, -1, errno); 291 } else { 292 int guestfd = alloc_guestfd(); 293 associate_guestfd(guestfd, ret); 294 complete(cs, guestfd, 0); 295 } 296 unlock_user(p, fname, 0); 297 } 298 299 static void host_close(CPUState *cs, gdb_syscall_complete_cb complete, 300 GuestFD *gf) 301 { 302 /* 303 * Only close the underlying host fd if it's one we opened on behalf 304 * of the guest in SYS_OPEN. 305 */ 306 if (gf->hostfd != STDIN_FILENO && 307 gf->hostfd != STDOUT_FILENO && 308 gf->hostfd != STDERR_FILENO && 309 close(gf->hostfd) < 0) { 310 complete(cs, -1, errno); 311 } else { 312 complete(cs, 0, 0); 313 } 314 } 315 316 static void host_read(CPUState *cs, gdb_syscall_complete_cb complete, 317 GuestFD *gf, target_ulong buf, target_ulong len) 318 { 319 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 320 void *ptr = lock_user(VERIFY_WRITE, buf, len, 0); 321 ssize_t ret; 322 323 if (!ptr) { 324 complete(cs, -1, EFAULT); 325 return; 326 } 327 ret = RETRY_ON_EINTR(read(gf->hostfd, ptr, len)); 328 if (ret == -1) { 329 unlock_user(ptr, buf, 0); 330 complete(cs, -1, errno); 331 } else { 332 unlock_user(ptr, buf, ret); 333 complete(cs, ret, 0); 334 } 335 } 336 337 static void host_write(CPUState *cs, gdb_syscall_complete_cb complete, 338 GuestFD *gf, target_ulong buf, target_ulong len) 339 { 340 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 341 void *ptr = lock_user(VERIFY_READ, buf, len, 1); 342 ssize_t ret; 343 344 if (!ptr) { 345 complete(cs, -1, EFAULT); 346 return; 347 } 348 ret = write(gf->hostfd, ptr, len); 349 unlock_user(ptr, buf, 0); 350 complete(cs, ret, ret == -1 ? errno : 0); 351 } 352 353 static void host_lseek(CPUState *cs, gdb_syscall_complete_cb complete, 354 GuestFD *gf, int64_t off, int whence) 355 { 356 /* So far, all hosts use the same values. */ 357 QEMU_BUILD_BUG_ON(GDB_SEEK_SET != SEEK_SET); 358 QEMU_BUILD_BUG_ON(GDB_SEEK_CUR != SEEK_CUR); 359 QEMU_BUILD_BUG_ON(GDB_SEEK_END != SEEK_END); 360 361 off_t ret = off; 362 int err = 0; 363 364 if (ret == off) { 365 ret = lseek(gf->hostfd, ret, whence); 366 if (ret == -1) { 367 err = errno; 368 } 369 } else { 370 ret = -1; 371 err = EINVAL; 372 } 373 complete(cs, ret, err); 374 } 375 376 static void host_isatty(CPUState *cs, gdb_syscall_complete_cb complete, 377 GuestFD *gf) 378 { 379 int ret = isatty(gf->hostfd); 380 complete(cs, ret, ret ? 0 : errno); 381 } 382 383 static void host_flen(CPUState *cs, gdb_syscall_complete_cb complete, 384 GuestFD *gf) 385 { 386 struct stat buf; 387 388 if (fstat(gf->hostfd, &buf) < 0) { 389 complete(cs, -1, errno); 390 } else { 391 complete(cs, buf.st_size, 0); 392 } 393 } 394 395 static void host_fstat(CPUState *cs, gdb_syscall_complete_cb complete, 396 GuestFD *gf, target_ulong addr) 397 { 398 struct stat buf; 399 int ret; 400 401 ret = fstat(gf->hostfd, &buf); 402 if (ret) { 403 complete(cs, -1, errno); 404 return; 405 } 406 ret = copy_stat_to_user(cs, addr, &buf); 407 complete(cs, ret ? -1 : 0, ret ? -ret : 0); 408 } 409 410 static void host_stat(CPUState *cs, gdb_syscall_complete_cb complete, 411 target_ulong fname, target_ulong fname_len, 412 target_ulong addr) 413 { 414 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 415 struct stat buf; 416 char *name; 417 int ret, err; 418 419 ret = validate_lock_user_string(&name, cs, fname, fname_len); 420 if (ret < 0) { 421 complete(cs, -1, -ret); 422 return; 423 } 424 425 ret = stat(name, &buf); 426 if (ret) { 427 err = errno; 428 } else { 429 ret = copy_stat_to_user(cs, addr, &buf); 430 err = 0; 431 if (ret < 0) { 432 err = -ret; 433 ret = -1; 434 } 435 } 436 unlock_user(name, fname, 0); 437 complete(cs, ret, err); 438 } 439 440 static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete, 441 target_ulong fname, target_ulong fname_len) 442 { 443 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 444 char *p; 445 int ret; 446 447 ret = validate_lock_user_string(&p, cs, fname, fname_len); 448 if (ret < 0) { 449 complete(cs, -1, -ret); 450 return; 451 } 452 453 ret = remove(p); 454 unlock_user(p, fname, 0); 455 complete(cs, ret, ret ? errno : 0); 456 } 457 458 static void host_rename(CPUState *cs, gdb_syscall_complete_cb complete, 459 target_ulong oname, target_ulong oname_len, 460 target_ulong nname, target_ulong nname_len) 461 { 462 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 463 char *ostr, *nstr; 464 int ret; 465 466 ret = validate_lock_user_string(&ostr, cs, oname, oname_len); 467 if (ret < 0) { 468 complete(cs, -1, -ret); 469 return; 470 } 471 ret = validate_lock_user_string(&nstr, cs, nname, nname_len); 472 if (ret < 0) { 473 unlock_user(ostr, oname, 0); 474 complete(cs, -1, -ret); 475 return; 476 } 477 478 ret = rename(ostr, nstr); 479 unlock_user(ostr, oname, 0); 480 unlock_user(nstr, nname, 0); 481 complete(cs, ret, ret ? errno : 0); 482 } 483 484 static void host_system(CPUState *cs, gdb_syscall_complete_cb complete, 485 target_ulong cmd, target_ulong cmd_len) 486 { 487 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 488 char *p; 489 int ret; 490 491 ret = validate_lock_user_string(&p, cs, cmd, cmd_len); 492 if (ret < 0) { 493 complete(cs, -1, -ret); 494 return; 495 } 496 497 ret = system(p); 498 unlock_user(p, cmd, 0); 499 complete(cs, ret, ret == -1 ? errno : 0); 500 } 501 502 static void host_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, 503 target_ulong tv_addr, target_ulong tz_addr) 504 { 505 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 506 struct gdb_timeval *p; 507 int64_t rt; 508 509 /* GDB fails on non-null TZ, so be consistent. */ 510 if (tz_addr != 0) { 511 complete(cs, -1, EINVAL); 512 return; 513 } 514 515 p = lock_user(VERIFY_WRITE, tv_addr, sizeof(struct gdb_timeval), 0); 516 if (!p) { 517 complete(cs, -1, EFAULT); 518 return; 519 } 520 521 /* TODO: Like stat, gdb always produces big-endian results; match it. */ 522 rt = g_get_real_time(); 523 p->tv_sec = cpu_to_be32(rt / G_USEC_PER_SEC); 524 p->tv_usec = cpu_to_be64(rt % G_USEC_PER_SEC); 525 unlock_user(p, tv_addr, sizeof(struct gdb_timeval)); 526 } 527 528 #ifndef CONFIG_USER_ONLY 529 static void host_poll_one(CPUState *cs, gdb_syscall_complete_cb complete, 530 GuestFD *gf, GIOCondition cond, int timeout) 531 { 532 /* 533 * Since this is only used by xtensa in system mode, and stdio is 534 * handled through GuestFDConsole, and there are no semihosting 535 * system calls for sockets and the like, that means this descriptor 536 * must be a normal file. Normal files never block and are thus 537 * always ready. 538 */ 539 complete(cs, cond & (G_IO_IN | G_IO_OUT), 0); 540 } 541 #endif 542 543 /* 544 * Static file semihosting syscall implementations. 545 */ 546 547 static void staticfile_read(CPUState *cs, gdb_syscall_complete_cb complete, 548 GuestFD *gf, target_ulong buf, target_ulong len) 549 { 550 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 551 target_ulong rest = gf->staticfile.len - gf->staticfile.off; 552 void *ptr; 553 554 if (len > rest) { 555 len = rest; 556 } 557 ptr = lock_user(VERIFY_WRITE, buf, len, 0); 558 if (!ptr) { 559 complete(cs, -1, EFAULT); 560 return; 561 } 562 memcpy(ptr, gf->staticfile.data + gf->staticfile.off, len); 563 gf->staticfile.off += len; 564 unlock_user(ptr, buf, len); 565 complete(cs, len, 0); 566 } 567 568 static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete, 569 GuestFD *gf, int64_t off, int gdb_whence) 570 { 571 int64_t ret; 572 573 switch (gdb_whence) { 574 case GDB_SEEK_SET: 575 ret = off; 576 break; 577 case GDB_SEEK_CUR: 578 ret = gf->staticfile.off + off; 579 break; 580 case GDB_SEEK_END: 581 ret = gf->staticfile.len + off; 582 break; 583 default: 584 ret = -1; 585 break; 586 } 587 if (ret >= 0 && ret <= gf->staticfile.len) { 588 gf->staticfile.off = ret; 589 complete(cs, ret, 0); 590 } else { 591 complete(cs, -1, EINVAL); 592 } 593 } 594 595 static void staticfile_flen(CPUState *cs, gdb_syscall_complete_cb complete, 596 GuestFD *gf) 597 { 598 complete(cs, gf->staticfile.len, 0); 599 } 600 601 /* 602 * Console semihosting syscall implementations. 603 */ 604 605 static void console_read(CPUState *cs, gdb_syscall_complete_cb complete, 606 GuestFD *gf, target_ulong buf, target_ulong len) 607 { 608 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 609 char *ptr; 610 int ret; 611 612 ptr = lock_user(VERIFY_WRITE, buf, len, 0); 613 if (!ptr) { 614 complete(cs, -1, EFAULT); 615 return; 616 } 617 ret = qemu_semihosting_console_read(cs, ptr, len); 618 unlock_user(ptr, buf, ret); 619 complete(cs, ret, 0); 620 } 621 622 static void console_write(CPUState *cs, gdb_syscall_complete_cb complete, 623 GuestFD *gf, target_ulong buf, target_ulong len) 624 { 625 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 626 char *ptr = lock_user(VERIFY_READ, buf, len, 1); 627 int ret; 628 629 if (!ptr) { 630 complete(cs, -1, EFAULT); 631 return; 632 } 633 ret = qemu_semihosting_console_write(ptr, len); 634 unlock_user(ptr, buf, 0); 635 complete(cs, ret ? ret : -1, ret ? 0 : EIO); 636 } 637 638 static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete, 639 GuestFD *gf, target_ulong addr) 640 { 641 static const struct stat tty_buf = { 642 .st_mode = 020666, /* S_IFCHR, ugo+rw */ 643 .st_rdev = 5, /* makedev(5, 0) -- linux /dev/tty */ 644 }; 645 int ret; 646 647 ret = copy_stat_to_user(cs, addr, &tty_buf); 648 complete(cs, ret ? -1 : 0, ret ? -ret : 0); 649 } 650 651 #ifndef CONFIG_USER_ONLY 652 static void console_poll_one(CPUState *cs, gdb_syscall_complete_cb complete, 653 GuestFD *gf, GIOCondition cond, int timeout) 654 { 655 /* The semihosting console does not support urgent data or errors. */ 656 cond &= G_IO_IN | G_IO_OUT; 657 658 /* 659 * Since qemu_semihosting_console_write never blocks, we can 660 * consider output always ready -- leave G_IO_OUT alone. 661 * All that remains is to conditionally signal input ready. 662 * Since output ready causes an immediate return, only block 663 * for G_IO_IN alone. 664 * 665 * TODO: Implement proper timeout. For now, only support 666 * indefinite wait or immediate poll. 667 */ 668 if (cond == G_IO_IN && timeout < 0) { 669 qemu_semihosting_console_block_until_ready(cs); 670 /* We returned -- input must be ready. */ 671 } else if ((cond & G_IO_IN) && !qemu_semihosting_console_ready()) { 672 cond &= ~G_IO_IN; 673 } 674 675 complete(cs, cond, 0); 676 } 677 #endif 678 679 /* 680 * Syscall entry points. 681 */ 682 683 void semihost_sys_open(CPUState *cs, gdb_syscall_complete_cb complete, 684 target_ulong fname, target_ulong fname_len, 685 int gdb_flags, int mode) 686 { 687 if (use_gdb_syscalls()) { 688 gdb_open(cs, complete, fname, fname_len, gdb_flags, mode); 689 } else { 690 host_open(cs, complete, fname, fname_len, gdb_flags, mode); 691 } 692 } 693 694 void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd) 695 { 696 GuestFD *gf = get_guestfd(fd); 697 698 if (!gf) { 699 complete(cs, -1, EBADF); 700 return; 701 } 702 switch (gf->type) { 703 case GuestFDGDB: 704 gdb_close(cs, complete, gf); 705 break; 706 case GuestFDHost: 707 host_close(cs, complete, gf); 708 break; 709 case GuestFDStatic: 710 case GuestFDConsole: 711 complete(cs, 0, 0); 712 break; 713 default: 714 g_assert_not_reached(); 715 } 716 dealloc_guestfd(fd); 717 } 718 719 void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete, 720 GuestFD *gf, target_ulong buf, target_ulong len) 721 { 722 /* 723 * Bound length for 64-bit guests on 32-bit hosts, not overflowing ssize_t. 724 * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad 725 * idea to do this unconditionally. 726 */ 727 if (len > INT32_MAX) { 728 len = INT32_MAX; 729 } 730 switch (gf->type) { 731 case GuestFDGDB: 732 gdb_read(cs, complete, gf, buf, len); 733 break; 734 case GuestFDHost: 735 host_read(cs, complete, gf, buf, len); 736 break; 737 case GuestFDStatic: 738 staticfile_read(cs, complete, gf, buf, len); 739 break; 740 case GuestFDConsole: 741 console_read(cs, complete, gf, buf, len); 742 break; 743 default: 744 g_assert_not_reached(); 745 } 746 } 747 748 void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete, 749 int fd, target_ulong buf, target_ulong len) 750 { 751 GuestFD *gf = get_guestfd(fd); 752 753 if (gf) { 754 semihost_sys_read_gf(cs, complete, gf, buf, len); 755 } else { 756 complete(cs, -1, EBADF); 757 } 758 } 759 760 void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete, 761 GuestFD *gf, target_ulong buf, target_ulong len) 762 { 763 /* 764 * Bound length for 64-bit guests on 32-bit hosts, not overflowing ssize_t. 765 * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad 766 * idea to do this unconditionally. 767 */ 768 if (len > INT32_MAX) { 769 len = INT32_MAX; 770 } 771 switch (gf->type) { 772 case GuestFDGDB: 773 gdb_write(cs, complete, gf, buf, len); 774 break; 775 case GuestFDHost: 776 host_write(cs, complete, gf, buf, len); 777 break; 778 case GuestFDConsole: 779 console_write(cs, complete, gf, buf, len); 780 break; 781 case GuestFDStatic: 782 /* Static files are never open for writing: EBADF. */ 783 complete(cs, -1, EBADF); 784 break; 785 default: 786 g_assert_not_reached(); 787 } 788 } 789 790 void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete, 791 int fd, target_ulong buf, target_ulong len) 792 { 793 GuestFD *gf = get_guestfd(fd); 794 795 if (gf) { 796 semihost_sys_write_gf(cs, complete, gf, buf, len); 797 } else { 798 complete(cs, -1, EBADF); 799 } 800 } 801 802 void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete, 803 int fd, int64_t off, int gdb_whence) 804 { 805 GuestFD *gf = get_guestfd(fd); 806 807 if (!gf) { 808 complete(cs, -1, EBADF); 809 return; 810 } 811 switch (gf->type) { 812 case GuestFDGDB: 813 gdb_lseek(cs, complete, gf, off, gdb_whence); 814 return; 815 case GuestFDHost: 816 host_lseek(cs, complete, gf, off, gdb_whence); 817 break; 818 case GuestFDStatic: 819 staticfile_lseek(cs, complete, gf, off, gdb_whence); 820 break; 821 case GuestFDConsole: 822 complete(cs, -1, ESPIPE); 823 break; 824 default: 825 g_assert_not_reached(); 826 } 827 } 828 829 void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, int fd) 830 { 831 GuestFD *gf = get_guestfd(fd); 832 833 if (!gf) { 834 complete(cs, 0, EBADF); 835 return; 836 } 837 switch (gf->type) { 838 case GuestFDGDB: 839 gdb_isatty(cs, complete, gf); 840 break; 841 case GuestFDHost: 842 host_isatty(cs, complete, gf); 843 break; 844 case GuestFDStatic: 845 complete(cs, 0, ENOTTY); 846 break; 847 case GuestFDConsole: 848 complete(cs, 1, 0); 849 break; 850 default: 851 g_assert_not_reached(); 852 } 853 } 854 855 void semihost_sys_flen(CPUState *cs, gdb_syscall_complete_cb fstat_cb, 856 gdb_syscall_complete_cb flen_cb, int fd, 857 target_ulong fstat_addr) 858 { 859 GuestFD *gf = get_guestfd(fd); 860 861 if (!gf) { 862 flen_cb(cs, -1, EBADF); 863 return; 864 } 865 switch (gf->type) { 866 case GuestFDGDB: 867 gdb_fstat(cs, fstat_cb, gf, fstat_addr); 868 break; 869 case GuestFDHost: 870 host_flen(cs, flen_cb, gf); 871 break; 872 case GuestFDStatic: 873 staticfile_flen(cs, flen_cb, gf); 874 break; 875 case GuestFDConsole: 876 default: 877 g_assert_not_reached(); 878 } 879 } 880 881 void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete, 882 int fd, target_ulong addr) 883 { 884 GuestFD *gf = get_guestfd(fd); 885 886 if (!gf) { 887 complete(cs, -1, EBADF); 888 return; 889 } 890 switch (gf->type) { 891 case GuestFDGDB: 892 gdb_fstat(cs, complete, gf, addr); 893 break; 894 case GuestFDHost: 895 host_fstat(cs, complete, gf, addr); 896 break; 897 case GuestFDConsole: 898 console_fstat(cs, complete, gf, addr); 899 break; 900 case GuestFDStatic: 901 default: 902 g_assert_not_reached(); 903 } 904 } 905 906 void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete, 907 target_ulong fname, target_ulong fname_len, 908 target_ulong addr) 909 { 910 if (use_gdb_syscalls()) { 911 gdb_stat(cs, complete, fname, fname_len, addr); 912 } else { 913 host_stat(cs, complete, fname, fname_len, addr); 914 } 915 } 916 917 void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete, 918 target_ulong fname, target_ulong fname_len) 919 { 920 if (use_gdb_syscalls()) { 921 gdb_remove(cs, complete, fname, fname_len); 922 } else { 923 host_remove(cs, complete, fname, fname_len); 924 } 925 } 926 927 void semihost_sys_rename(CPUState *cs, gdb_syscall_complete_cb complete, 928 target_ulong oname, target_ulong oname_len, 929 target_ulong nname, target_ulong nname_len) 930 { 931 if (use_gdb_syscalls()) { 932 gdb_rename(cs, complete, oname, oname_len, nname, nname_len); 933 } else { 934 host_rename(cs, complete, oname, oname_len, nname, nname_len); 935 } 936 } 937 938 void semihost_sys_system(CPUState *cs, gdb_syscall_complete_cb complete, 939 target_ulong cmd, target_ulong cmd_len) 940 { 941 if (use_gdb_syscalls()) { 942 gdb_system(cs, complete, cmd, cmd_len); 943 } else { 944 host_system(cs, complete, cmd, cmd_len); 945 } 946 } 947 948 void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, 949 target_ulong tv_addr, target_ulong tz_addr) 950 { 951 if (use_gdb_syscalls()) { 952 gdb_gettimeofday(cs, complete, tv_addr, tz_addr); 953 } else { 954 host_gettimeofday(cs, complete, tv_addr, tz_addr); 955 } 956 } 957 958 #ifndef CONFIG_USER_ONLY 959 void semihost_sys_poll_one(CPUState *cs, gdb_syscall_complete_cb complete, 960 int fd, GIOCondition cond, int timeout) 961 { 962 GuestFD *gf = get_guestfd(fd); 963 964 if (!gf) { 965 complete(cs, G_IO_NVAL, 1); 966 return; 967 } 968 switch (gf->type) { 969 case GuestFDGDB: 970 complete(cs, G_IO_NVAL, 1); 971 break; 972 case GuestFDHost: 973 host_poll_one(cs, complete, gf, cond, timeout); 974 break; 975 case GuestFDConsole: 976 console_poll_one(cs, complete, gf, cond, timeout); 977 break; 978 case GuestFDStatic: 979 default: 980 g_assert_not_reached(); 981 } 982 } 983 #endif 984