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 "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 19 20 21 /* 22 * Validate or compute the length of the string (including terminator). 23 */ 24 static int validate_strlen(CPUState *cs, target_ulong str, target_ulong tlen) 25 { 26 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 27 char c; 28 29 if (tlen == 0) { 30 ssize_t slen = target_strlen(str); 31 32 if (slen < 0) { 33 return -EFAULT; 34 } 35 if (slen >= INT32_MAX) { 36 return -ENAMETOOLONG; 37 } 38 return slen + 1; 39 } 40 if (tlen > INT32_MAX) { 41 return -ENAMETOOLONG; 42 } 43 if (get_user_u8(c, str + tlen - 1)) { 44 return -EFAULT; 45 } 46 if (c != 0) { 47 return -EINVAL; 48 } 49 return tlen; 50 } 51 52 static int validate_lock_user_string(char **pstr, CPUState *cs, 53 target_ulong tstr, target_ulong tlen) 54 { 55 int ret = validate_strlen(cs, tstr, tlen); 56 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 57 char *str = NULL; 58 59 if (ret > 0) { 60 str = lock_user(VERIFY_READ, tstr, ret, true); 61 ret = str ? 0 : -EFAULT; 62 } 63 *pstr = str; 64 return ret; 65 } 66 67 /* 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. 72 */ 73 static int copy_stat_to_user(CPUState *cs, target_ulong addr, 74 const struct stat *s) 75 { 76 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 77 struct gdb_stat *p; 78 79 if (s->st_dev != (uint32_t)s->st_dev || 80 s->st_ino != (uint32_t)s->st_ino) { 81 return -EOVERFLOW; 82 } 83 84 p = lock_user(VERIFY_WRITE, addr, sizeof(struct gdb_stat), 0); 85 if (!p) { 86 return -EFAULT; 87 } 88 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); 108 109 unlock_user(p, addr, sizeof(struct gdb_stat)); 110 return 0; 111 } 112 113 /* 114 * GDB semihosting syscall implementations. 115 */ 116 117 static gdb_syscall_complete_cb gdb_open_complete; 118 119 static void gdb_open_cb(CPUState *cs, uint64_t ret, int err) 120 { 121 if (!err) { 122 int guestfd = alloc_guestfd(); 123 associate_guestfd(guestfd, ret); 124 ret = guestfd; 125 } 126 gdb_open_complete(cs, ret, err); 127 } 128 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) 132 { 133 int len = validate_strlen(cs, fname, fname_len); 134 if (len < 0) { 135 complete(cs, -1, -len); 136 return; 137 } 138 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); 142 } 143 144 static void gdb_close(CPUState *cs, gdb_syscall_complete_cb complete, 145 GuestFD *gf) 146 { 147 gdb_do_syscall(complete, "close,%x", (target_ulong)gf->hostfd); 148 } 149 150 static void gdb_read(CPUState *cs, gdb_syscall_complete_cb complete, 151 GuestFD *gf, target_ulong buf, target_ulong len) 152 { 153 gdb_do_syscall(complete, "read,%x,%x,%x", 154 (target_ulong)gf->hostfd, buf, len); 155 } 156 157 static void gdb_write(CPUState *cs, gdb_syscall_complete_cb complete, 158 GuestFD *gf, target_ulong buf, target_ulong len) 159 { 160 gdb_do_syscall(complete, "write,%x,%x,%x", 161 (target_ulong)gf->hostfd, buf, len); 162 } 163 164 static void gdb_lseek(CPUState *cs, gdb_syscall_complete_cb complete, 165 GuestFD *gf, int64_t off, int gdb_whence) 166 { 167 gdb_do_syscall(complete, "lseek,%x,%lx,%x", 168 (target_ulong)gf->hostfd, off, (target_ulong)gdb_whence); 169 } 170 171 static void gdb_isatty(CPUState *cs, gdb_syscall_complete_cb complete, 172 GuestFD *gf) 173 { 174 gdb_do_syscall(complete, "isatty,%x", (target_ulong)gf->hostfd); 175 } 176 177 static void gdb_fstat(CPUState *cs, gdb_syscall_complete_cb complete, 178 GuestFD *gf, target_ulong addr) 179 { 180 gdb_do_syscall(complete, "fstat,%x,%x", (target_ulong)gf->hostfd, addr); 181 } 182 183 static void gdb_stat(CPUState *cs, gdb_syscall_complete_cb complete, 184 target_ulong fname, target_ulong fname_len, 185 target_ulong addr) 186 { 187 int len = validate_strlen(cs, fname, fname_len); 188 if (len < 0) { 189 complete(cs, -1, -len); 190 return; 191 } 192 193 gdb_do_syscall(complete, "stat,%s,%x", fname, len, addr); 194 } 195 196 static void gdb_remove(CPUState *cs, gdb_syscall_complete_cb complete, 197 target_ulong fname, target_ulong fname_len) 198 { 199 int len = validate_strlen(cs, fname, fname_len); 200 if (len < 0) { 201 complete(cs, -1, -len); 202 return; 203 } 204 205 gdb_do_syscall(complete, "unlink,%s", fname, len); 206 } 207 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) 211 { 212 int olen, nlen; 213 214 olen = validate_strlen(cs, oname, oname_len); 215 if (olen < 0) { 216 complete(cs, -1, -olen); 217 return; 218 } 219 nlen = validate_strlen(cs, nname, nname_len); 220 if (nlen < 0) { 221 complete(cs, -1, -nlen); 222 return; 223 } 224 225 gdb_do_syscall(complete, "rename,%s,%s", oname, olen, nname, nlen); 226 } 227 228 static void gdb_system(CPUState *cs, gdb_syscall_complete_cb complete, 229 target_ulong cmd, target_ulong cmd_len) 230 { 231 int len = validate_strlen(cs, cmd, cmd_len); 232 if (len < 0) { 233 complete(cs, -1, -len); 234 return; 235 } 236 237 gdb_do_syscall(complete, "system,%s", cmd, len); 238 } 239 240 static void gdb_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, 241 target_ulong tv_addr, target_ulong tz_addr) 242 { 243 gdb_do_syscall(complete, "gettimeofday,%x,%x", tv_addr, tz_addr); 244 } 245 246 /* 247 * Host semihosting syscall implementations. 248 */ 249 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) 253 { 254 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 255 char *p; 256 int ret, host_flags = O_BINARY; 257 258 ret = validate_lock_user_string(&p, cs, fname, fname_len); 259 if (ret < 0) { 260 complete(cs, -1, -ret); 261 return; 262 } 263 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; 270 } 271 if (gdb_flags & GDB_O_CREAT) { 272 host_flags |= O_CREAT; 273 } 274 if (gdb_flags & GDB_O_TRUNC) { 275 host_flags |= O_TRUNC; 276 } 277 if (gdb_flags & GDB_O_EXCL) { 278 host_flags |= O_EXCL; 279 } 280 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); 288 } 289 unlock_user(p, fname, 0); 290 } 291 292 static void host_close(CPUState *cs, gdb_syscall_complete_cb complete, 293 GuestFD *gf) 294 { 295 /* 296 * Only close the underlying host fd if it's one we opened on behalf 297 * of the guest in SYS_OPEN. 298 */ 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); 306 } 307 } 308 309 static void host_read(CPUState *cs, gdb_syscall_complete_cb complete, 310 GuestFD *gf, target_ulong buf, target_ulong len) 311 { 312 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 313 void *ptr = lock_user(VERIFY_WRITE, buf, len, 0); 314 ssize_t ret; 315 316 if (!ptr) { 317 complete(cs, -1, EFAULT); 318 return; 319 } 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); 327 } 328 } 329 330 static void host_write(CPUState *cs, gdb_syscall_complete_cb complete, 331 GuestFD *gf, target_ulong buf, target_ulong len) 332 { 333 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 334 void *ptr = lock_user(VERIFY_READ, buf, len, 1); 335 ssize_t ret; 336 337 if (!ptr) { 338 complete(cs, -1, EFAULT); 339 return; 340 } 341 ret = write(gf->hostfd, ptr, len); 342 unlock_user(ptr, buf, 0); 343 complete(cs, ret, ret == -1 ? errno : 0); 344 } 345 346 static void host_lseek(CPUState *cs, gdb_syscall_complete_cb complete, 347 GuestFD *gf, int64_t off, int whence) 348 { 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); 353 354 off_t ret = off; 355 int err = 0; 356 357 if (ret == off) { 358 ret = lseek(gf->hostfd, ret, whence); 359 if (ret == -1) { 360 err = errno; 361 } 362 } else { 363 ret = -1; 364 err = EINVAL; 365 } 366 complete(cs, ret, err); 367 } 368 369 static void host_isatty(CPUState *cs, gdb_syscall_complete_cb complete, 370 GuestFD *gf) 371 { 372 int ret = isatty(gf->hostfd); 373 complete(cs, ret, ret ? 0 : errno); 374 } 375 376 static void host_flen(CPUState *cs, gdb_syscall_complete_cb complete, 377 GuestFD *gf) 378 { 379 struct stat buf; 380 381 if (fstat(gf->hostfd, &buf) < 0) { 382 complete(cs, -1, errno); 383 } else { 384 complete(cs, buf.st_size, 0); 385 } 386 } 387 388 static void host_fstat(CPUState *cs, gdb_syscall_complete_cb complete, 389 GuestFD *gf, target_ulong addr) 390 { 391 struct stat buf; 392 int ret; 393 394 ret = fstat(gf->hostfd, &buf); 395 if (ret) { 396 complete(cs, -1, errno); 397 return; 398 } 399 ret = copy_stat_to_user(cs, addr, &buf); 400 complete(cs, ret ? -1 : 0, ret ? -ret : 0); 401 } 402 403 static void host_stat(CPUState *cs, gdb_syscall_complete_cb complete, 404 target_ulong fname, target_ulong fname_len, 405 target_ulong addr) 406 { 407 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 408 struct stat buf; 409 char *name; 410 int ret, err; 411 412 ret = validate_lock_user_string(&name, cs, fname, fname_len); 413 if (ret < 0) { 414 complete(cs, -1, -ret); 415 return; 416 } 417 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; 427 } 428 } 429 unlock_user(name, fname, 0); 430 complete(cs, ret, err); 431 } 432 433 static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete, 434 target_ulong fname, target_ulong fname_len) 435 { 436 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 437 char *p; 438 int ret; 439 440 ret = validate_lock_user_string(&p, cs, fname, fname_len); 441 if (ret < 0) { 442 complete(cs, -1, -ret); 443 return; 444 } 445 446 ret = remove(p); 447 unlock_user(p, fname, 0); 448 complete(cs, ret, ret ? errno : 0); 449 } 450 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) 454 { 455 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 456 char *ostr, *nstr; 457 int ret; 458 459 ret = validate_lock_user_string(&ostr, cs, oname, oname_len); 460 if (ret < 0) { 461 complete(cs, -1, -ret); 462 return; 463 } 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; 469 } 470 471 ret = rename(ostr, nstr); 472 unlock_user(ostr, oname, 0); 473 unlock_user(nstr, nname, 0); 474 complete(cs, ret, ret ? errno : 0); 475 } 476 477 static void host_system(CPUState *cs, gdb_syscall_complete_cb complete, 478 target_ulong cmd, target_ulong cmd_len) 479 { 480 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 481 char *p; 482 int ret; 483 484 ret = validate_lock_user_string(&p, cs, cmd, cmd_len); 485 if (ret < 0) { 486 complete(cs, -1, -ret); 487 return; 488 } 489 490 ret = system(p); 491 unlock_user(p, cmd, 0); 492 complete(cs, ret, ret == -1 ? errno : 0); 493 } 494 495 static void host_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, 496 target_ulong tv_addr, target_ulong tz_addr) 497 { 498 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 499 struct gdb_timeval *p; 500 int64_t rt; 501 502 /* GDB fails on non-null TZ, so be consistent. */ 503 if (tz_addr != 0) { 504 complete(cs, -1, EINVAL); 505 return; 506 } 507 508 p = lock_user(VERIFY_WRITE, tv_addr, sizeof(struct gdb_timeval), 0); 509 if (!p) { 510 complete(cs, -1, EFAULT); 511 return; 512 } 513 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)); 519 } 520 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) 524 { 525 /* 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. 531 */ 532 complete(cs, cond & (G_IO_IN | G_IO_OUT), 0); 533 } 534 #endif 535 536 /* 537 * Static file semihosting syscall implementations. 538 */ 539 540 static void staticfile_read(CPUState *cs, gdb_syscall_complete_cb complete, 541 GuestFD *gf, target_ulong buf, target_ulong len) 542 { 543 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 544 target_ulong rest = gf->staticfile.len - gf->staticfile.off; 545 void *ptr; 546 547 if (len > rest) { 548 len = rest; 549 } 550 ptr = lock_user(VERIFY_WRITE, buf, len, 0); 551 if (!ptr) { 552 complete(cs, -1, EFAULT); 553 return; 554 } 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); 559 } 560 561 static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete, 562 GuestFD *gf, int64_t off, int gdb_whence) 563 { 564 int64_t ret; 565 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; 579 } 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); 585 } 586 } 587 588 static void staticfile_flen(CPUState *cs, gdb_syscall_complete_cb complete, 589 GuestFD *gf) 590 { 591 complete(cs, gf->staticfile.len, 0); 592 } 593 594 /* 595 * Console semihosting syscall implementations. 596 */ 597 598 static void console_read(CPUState *cs, gdb_syscall_complete_cb complete, 599 GuestFD *gf, target_ulong buf, target_ulong len) 600 { 601 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 602 char *ptr; 603 int ret; 604 605 ptr = lock_user(VERIFY_WRITE, buf, len, 0); 606 if (!ptr) { 607 complete(cs, -1, EFAULT); 608 return; 609 } 610 ret = qemu_semihosting_console_read(cs, ptr, len); 611 unlock_user(ptr, buf, ret); 612 complete(cs, ret, 0); 613 } 614 615 static void console_write(CPUState *cs, gdb_syscall_complete_cb complete, 616 GuestFD *gf, target_ulong buf, target_ulong len) 617 { 618 CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; 619 char *ptr = lock_user(VERIFY_READ, buf, len, 1); 620 int ret; 621 622 if (!ptr) { 623 complete(cs, -1, EFAULT); 624 return; 625 } 626 ret = qemu_semihosting_console_write(ptr, len); 627 unlock_user(ptr, buf, 0); 628 complete(cs, ret ? ret : -1, ret ? 0 : EIO); 629 } 630 631 static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete, 632 GuestFD *gf, target_ulong addr) 633 { 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 */ 637 }; 638 int ret; 639 640 ret = copy_stat_to_user(cs, addr, &tty_buf); 641 complete(cs, ret ? -1 : 0, ret ? -ret : 0); 642 } 643 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) 647 { 648 /* The semihosting console does not support urgent data or errors. */ 649 cond &= G_IO_IN | G_IO_OUT; 650 651 /* 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. 657 * 658 * TODO: Implement proper timeout. For now, only support 659 * indefinite wait or immediate poll. 660 */ 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; 666 } 667 668 complete(cs, cond, 0); 669 } 670 #endif 671 672 /* 673 * Syscall entry points. 674 */ 675 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) 679 { 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); 684 } 685 } 686 687 void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd) 688 { 689 GuestFD *gf = get_guestfd(fd); 690 691 if (!gf) { 692 complete(cs, -1, EBADF); 693 return; 694 } 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(); 708 } 709 dealloc_guestfd(fd); 710 } 711 712 void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete, 713 GuestFD *gf, target_ulong buf, target_ulong len) 714 { 715 /* 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. 719 */ 720 if (len > INT32_MAX) { 721 len = INT32_MAX; 722 } 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(); 738 } 739 } 740 741 void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete, 742 int fd, target_ulong buf, target_ulong len) 743 { 744 GuestFD *gf = get_guestfd(fd); 745 746 if (gf) { 747 semihost_sys_read_gf(cs, complete, gf, buf, len); 748 } else { 749 complete(cs, -1, EBADF); 750 } 751 } 752 753 void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete, 754 GuestFD *gf, target_ulong buf, target_ulong len) 755 { 756 /* 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. 760 */ 761 if (len > INT32_MAX) { 762 len = INT32_MAX; 763 } 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(); 780 } 781 } 782 783 void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete, 784 int fd, target_ulong buf, target_ulong len) 785 { 786 GuestFD *gf = get_guestfd(fd); 787 788 if (gf) { 789 semihost_sys_write_gf(cs, complete, gf, buf, len); 790 } else { 791 complete(cs, -1, EBADF); 792 } 793 } 794 795 void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete, 796 int fd, int64_t off, int gdb_whence) 797 { 798 GuestFD *gf = get_guestfd(fd); 799 800 if (!gf) { 801 complete(cs, -1, EBADF); 802 return; 803 } 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(); 819 } 820 } 821 822 void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, int fd) 823 { 824 GuestFD *gf = get_guestfd(fd); 825 826 if (!gf) { 827 complete(cs, 0, EBADF); 828 return; 829 } 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(); 845 } 846 } 847 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) 851 { 852 GuestFD *gf = get_guestfd(fd); 853 854 if (!gf) { 855 flen_cb(cs, -1, EBADF); 856 return; 857 } 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(); 871 } 872 } 873 874 void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete, 875 int fd, target_ulong addr) 876 { 877 GuestFD *gf = get_guestfd(fd); 878 879 if (!gf) { 880 complete(cs, -1, EBADF); 881 return; 882 } 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(); 896 } 897 } 898 899 void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete, 900 target_ulong fname, target_ulong fname_len, 901 target_ulong addr) 902 { 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); 907 } 908 } 909 910 void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete, 911 target_ulong fname, target_ulong fname_len) 912 { 913 if (use_gdb_syscalls()) { 914 gdb_remove(cs, complete, fname, fname_len); 915 } else { 916 host_remove(cs, complete, fname, fname_len); 917 } 918 } 919 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) 923 { 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); 928 } 929 } 930 931 void semihost_sys_system(CPUState *cs, gdb_syscall_complete_cb complete, 932 target_ulong cmd, target_ulong cmd_len) 933 { 934 if (use_gdb_syscalls()) { 935 gdb_system(cs, complete, cmd, cmd_len); 936 } else { 937 host_system(cs, complete, cmd, cmd_len); 938 } 939 } 940 941 void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, 942 target_ulong tv_addr, target_ulong tz_addr) 943 { 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); 948 } 949 } 950 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) 954 { 955 GuestFD *gf = get_guestfd(fd); 956 957 if (!gf) { 958 complete(cs, G_IO_NVAL, 1); 959 return; 960 } 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(); 974 } 975 } 976 #endif 977