qemu/semihosting/syscalls.c
<<
>>
Prefs
   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 */
  25static 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
  53static 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 */
  74static 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
 118static gdb_syscall_complete_cb gdb_open_complete;
 119
 120static 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
 130static 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
 146static 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
 152static 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
 159static 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
 166static 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
 173static 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
 179static 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
 186static 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
 200static 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
 212static 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
 234static 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
 246static 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
 257static 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
 299static 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
 316static 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
 337static 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
 353static 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
 376static 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
 383static 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
 395static 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
 410static 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
 440static 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
 458static 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
 484static 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
 502static 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
 529static 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
 547static 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
 568static 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
 595static 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
 605static 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
 622static 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
 638static 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
 652static 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
 683void 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
 694void 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
 719void 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 overlowing 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
 748void 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
 760void 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 overlowing 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
 790void 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
 802void 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
 829void 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
 855void 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
 881void 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
 906void 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
 917void 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
 927void 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
 938void 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
 948void 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
 959void 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