1 /* 2 * Semihosting support for systems modeled on the Arm "Angel" 3 * semihosting syscalls design. This includes Arm and RISC-V processors 4 * 5 * Copyright (c) 2005, 2007 CodeSourcery. 6 * Copyright (c) 2019 Linaro 7 * Written by Paul Brook. 8 * 9 * Copyright © 2020 by Keith Packard <keithp@keithp.com> 10 * Adapted for systems other than ARM, including RISC-V, by Keith Packard 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, see <http://www.gnu.org/licenses/>. 24 * 25 * ARM Semihosting is documented in: 26 * Semihosting for AArch32 and AArch64 Release 2.0 27 * https://static.docs.arm.com/100863/0200/semihosting.pdf 28 * 29 * RISC-V Semihosting is documented in: 30 * RISC-V Semihosting 31 * https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc 32 */ 33 34 #include "qemu/osdep.h" 35 #include "semihosting/semihost.h" 36 #include "semihosting/console.h" 37 #include "semihosting/common-semi.h" 38 #include "semihosting/guestfd.h" 39 #include "qemu/timer.h" 40 #include "exec/gdbstub.h" 41 42 #ifdef CONFIG_USER_ONLY 43 #include "qemu.h" 44 45 #define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024) 46 #else 47 #include "qemu/cutils.h" 48 #include "hw/loader.h" 49 #include "hw/boards.h" 50 #endif 51 52 #define TARGET_SYS_OPEN 0x01 53 #define TARGET_SYS_CLOSE 0x02 54 #define TARGET_SYS_WRITEC 0x03 55 #define TARGET_SYS_WRITE0 0x04 56 #define TARGET_SYS_WRITE 0x05 57 #define TARGET_SYS_READ 0x06 58 #define TARGET_SYS_READC 0x07 59 #define TARGET_SYS_ISERROR 0x08 60 #define TARGET_SYS_ISTTY 0x09 61 #define TARGET_SYS_SEEK 0x0a 62 #define TARGET_SYS_FLEN 0x0c 63 #define TARGET_SYS_TMPNAM 0x0d 64 #define TARGET_SYS_REMOVE 0x0e 65 #define TARGET_SYS_RENAME 0x0f 66 #define TARGET_SYS_CLOCK 0x10 67 #define TARGET_SYS_TIME 0x11 68 #define TARGET_SYS_SYSTEM 0x12 69 #define TARGET_SYS_ERRNO 0x13 70 #define TARGET_SYS_GET_CMDLINE 0x15 71 #define TARGET_SYS_HEAPINFO 0x16 72 #define TARGET_SYS_EXIT 0x18 73 #define TARGET_SYS_SYNCCACHE 0x19 74 #define TARGET_SYS_EXIT_EXTENDED 0x20 75 #define TARGET_SYS_ELAPSED 0x30 76 #define TARGET_SYS_TICKFREQ 0x31 77 78 /* ADP_Stopped_ApplicationExit is used for exit(0), 79 * anything else is implemented as exit(1) */ 80 #define ADP_Stopped_ApplicationExit (0x20026) 81 82 #ifndef O_BINARY 83 #define O_BINARY 0 84 #endif 85 86 static int gdb_open_modeflags[12] = { 87 GDB_O_RDONLY, 88 GDB_O_RDONLY, 89 GDB_O_RDWR, 90 GDB_O_RDWR, 91 GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC, 92 GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC, 93 GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC, 94 GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC, 95 GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND, 96 GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND, 97 GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND, 98 GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND, 99 }; 100 101 static int open_modeflags[12] = { 102 O_RDONLY, 103 O_RDONLY | O_BINARY, 104 O_RDWR, 105 O_RDWR | O_BINARY, 106 O_WRONLY | O_CREAT | O_TRUNC, 107 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 108 O_RDWR | O_CREAT | O_TRUNC, 109 O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 110 O_WRONLY | O_CREAT | O_APPEND, 111 O_WRONLY | O_CREAT | O_APPEND | O_BINARY, 112 O_RDWR | O_CREAT | O_APPEND, 113 O_RDWR | O_CREAT | O_APPEND | O_BINARY 114 }; 115 116 #ifndef CONFIG_USER_ONLY 117 118 /** 119 * common_semi_find_bases: find information about ram and heap base 120 * 121 * This function attempts to provide meaningful numbers for RAM and 122 * HEAP base addresses. The rambase is simply the lowest addressable 123 * RAM position. For the heapbase we ask the loader to scan the 124 * address space and the largest available gap by querying the "ROM" 125 * regions. 126 * 127 * Returns: a structure with the numbers we need. 128 */ 129 130 typedef struct LayoutInfo { 131 target_ulong rambase; 132 size_t ramsize; 133 hwaddr heapbase; 134 hwaddr heaplimit; 135 } LayoutInfo; 136 137 static bool find_ram_cb(Int128 start, Int128 len, const MemoryRegion *mr, 138 hwaddr offset_in_region, void *opaque) 139 { 140 LayoutInfo *info = (LayoutInfo *) opaque; 141 uint64_t size = int128_get64(len); 142 143 if (!mr->ram || mr->readonly) { 144 return false; 145 } 146 147 if (size > info->ramsize) { 148 info->rambase = int128_get64(start); 149 info->ramsize = size; 150 } 151 152 /* search exhaustively for largest RAM */ 153 return false; 154 } 155 156 static LayoutInfo common_semi_find_bases(CPUState *cs) 157 { 158 FlatView *fv; 159 LayoutInfo info = { 0, 0, 0, 0 }; 160 161 RCU_READ_LOCK_GUARD(); 162 163 fv = address_space_to_flatview(cs->as); 164 flatview_for_each_range(fv, find_ram_cb, &info); 165 166 /* 167 * If we have found the RAM lets iterate through the ROM blobs to 168 * work out the best place for the remainder of RAM and split it 169 * equally between stack and heap. 170 */ 171 if (info.rambase || info.ramsize > 0) { 172 RomGap gap = rom_find_largest_gap_between(info.rambase, info.ramsize); 173 info.heapbase = gap.base; 174 info.heaplimit = gap.base + gap.size; 175 } 176 177 return info; 178 } 179 180 #endif 181 182 #include "common-semi-target.h" 183 184 /* 185 * The semihosting API has no concept of its errno being thread-safe, 186 * as the API design predates SMP CPUs and was intended as a simple 187 * real-hardware set of debug functionality. For QEMU, we make the 188 * errno be per-thread in linux-user mode; in softmmu it is a simple 189 * global, and we assume that the guest takes care of avoiding any races. 190 */ 191 #ifndef CONFIG_USER_ONLY 192 static target_ulong syscall_err; 193 194 #include "semihosting/softmmu-uaccess.h" 195 #endif 196 197 static inline uint32_t get_swi_errno(CPUState *cs) 198 { 199 #ifdef CONFIG_USER_ONLY 200 TaskState *ts = cs->opaque; 201 202 return ts->swi_errno; 203 #else 204 return syscall_err; 205 #endif 206 } 207 208 static target_ulong common_semi_syscall_len; 209 210 static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err) 211 { 212 if (err) { 213 #ifdef CONFIG_USER_ONLY 214 TaskState *ts = cs->opaque; 215 ts->swi_errno = err; 216 #else 217 syscall_err = err; 218 #endif 219 } else { 220 /* Fixup syscalls that use nonstardard return conventions. */ 221 target_ulong reg0 = common_semi_arg(cs, 0); 222 switch (reg0) { 223 case TARGET_SYS_WRITE: 224 case TARGET_SYS_READ: 225 ret = common_semi_syscall_len - ret; 226 break; 227 case TARGET_SYS_SEEK: 228 ret = 0; 229 break; 230 default: 231 break; 232 } 233 } 234 common_semi_set_ret(cs, ret); 235 } 236 237 /* 238 * Return an address in target memory of 64 bytes where the remote 239 * gdb should write its stat struct. (The format of this structure 240 * is defined by GDB's remote protocol and is not target-specific.) 241 * We put this on the guest's stack just below SP. 242 */ 243 static target_ulong common_semi_flen_buf(CPUState *cs) 244 { 245 target_ulong sp = common_semi_stack_bottom(cs); 246 return sp - 64; 247 } 248 249 static void 250 common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err) 251 { 252 if (!err) { 253 /* The size is always stored in big-endian order, extract the value. */ 254 uint64_t size; 255 cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 256 offsetof(struct gdb_stat, gdb_st_size), 257 &size, 8, 0); 258 ret = be64_to_cpu(size); 259 } 260 common_semi_cb(cs, ret, err); 261 } 262 263 static int common_semi_open_guestfd; 264 265 static void 266 common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err) 267 { 268 if (err) { 269 dealloc_guestfd(common_semi_open_guestfd); 270 } else { 271 associate_guestfd(common_semi_open_guestfd, ret); 272 ret = common_semi_open_guestfd; 273 } 274 common_semi_cb(cs, ret, err); 275 } 276 277 /* 278 * Types for functions implementing various semihosting calls 279 * for specific types of guest file descriptor. These must all 280 * do the work and return the required return value to the guest 281 * via common_semi_cb. 282 */ 283 typedef void sys_closefn(CPUState *cs, GuestFD *gf); 284 typedef void sys_writefn(CPUState *cs, GuestFD *gf, 285 target_ulong buf, uint32_t len); 286 typedef void sys_readfn(CPUState *cs, GuestFD *gf, 287 target_ulong buf, uint32_t len); 288 typedef void sys_isattyfn(CPUState *cs, GuestFD *gf); 289 typedef void sys_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset); 290 typedef void sys_flenfn(CPUState *cs, GuestFD *gf); 291 292 static void host_closefn(CPUState *cs, GuestFD *gf) 293 { 294 int ret; 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 ret = 0; 303 } else { 304 ret = close(gf->hostfd); 305 } 306 common_semi_cb(cs, ret, ret ? errno : 0); 307 } 308 309 static void host_writefn(CPUState *cs, GuestFD *gf, 310 target_ulong buf, uint32_t len) 311 { 312 CPUArchState *env = cs->env_ptr; 313 uint32_t ret = 0; 314 char *s = lock_user(VERIFY_READ, buf, len, 1); 315 (void) env; /* Used in arm softmmu lock_user implicitly */ 316 if (s) { 317 ret = write(gf->hostfd, s, len); 318 unlock_user(s, buf, 0); 319 if (ret == (uint32_t)-1) { 320 ret = 0; 321 } 322 } 323 /* Return bytes not written, on error as well. */ 324 common_semi_cb(cs, len - ret, 0); 325 } 326 327 static void host_readfn(CPUState *cs, GuestFD *gf, 328 target_ulong buf, uint32_t len) 329 { 330 CPUArchState *env = cs->env_ptr; 331 uint32_t ret = 0; 332 char *s = lock_user(VERIFY_WRITE, buf, len, 0); 333 (void) env; /* Used in arm softmmu lock_user implicitly */ 334 if (s) { 335 do { 336 ret = read(gf->hostfd, s, len); 337 } while (ret == -1 && errno == EINTR); 338 unlock_user(s, buf, len); 339 if (ret == (uint32_t)-1) { 340 ret = 0; 341 } 342 } 343 /* Return bytes not read, on error as well. */ 344 common_semi_cb(cs, len - ret, 0); 345 } 346 347 static void host_isattyfn(CPUState *cs, GuestFD *gf) 348 { 349 common_semi_cb(cs, isatty(gf->hostfd), 0); 350 } 351 352 static void host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset) 353 { 354 off_t ret = lseek(gf->hostfd, offset, SEEK_SET); 355 common_semi_cb(cs, ret, ret == -1 ? errno : 0); 356 } 357 358 static void host_flenfn(CPUState *cs, GuestFD *gf) 359 { 360 struct stat buf; 361 362 if (fstat(gf->hostfd, &buf)) { 363 common_semi_cb(cs, -1, errno); 364 } else { 365 common_semi_cb(cs, buf.st_size, 0); 366 } 367 } 368 369 static void gdb_closefn(CPUState *cs, GuestFD *gf) 370 { 371 gdb_do_syscall(common_semi_cb, "close,%x", gf->hostfd); 372 } 373 374 static void gdb_writefn(CPUState *cs, GuestFD *gf, 375 target_ulong buf, uint32_t len) 376 { 377 common_semi_syscall_len = len; 378 gdb_do_syscall(common_semi_cb, "write,%x,%x,%x", gf->hostfd, buf, len); 379 } 380 381 static void gdb_readfn(CPUState *cs, GuestFD *gf, 382 target_ulong buf, uint32_t len) 383 { 384 common_semi_syscall_len = len; 385 gdb_do_syscall(common_semi_cb, "read,%x,%x,%x", gf->hostfd, buf, len); 386 } 387 388 static void gdb_isattyfn(CPUState *cs, GuestFD *gf) 389 { 390 gdb_do_syscall(common_semi_cb, "isatty,%x", gf->hostfd); 391 } 392 393 static void gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset) 394 { 395 gdb_do_syscall(common_semi_cb, "lseek,%x,%x,0", gf->hostfd, offset); 396 } 397 398 static void gdb_flenfn(CPUState *cs, GuestFD *gf) 399 { 400 gdb_do_syscall(common_semi_flen_cb, "fstat,%x,%x", 401 gf->hostfd, common_semi_flen_buf(cs)); 402 } 403 404 #define SHFB_MAGIC_0 0x53 405 #define SHFB_MAGIC_1 0x48 406 #define SHFB_MAGIC_2 0x46 407 #define SHFB_MAGIC_3 0x42 408 409 /* Feature bits reportable in feature byte 0 */ 410 #define SH_EXT_EXIT_EXTENDED (1 << 0) 411 #define SH_EXT_STDOUT_STDERR (1 << 1) 412 413 static const uint8_t featurefile_data[] = { 414 SHFB_MAGIC_0, 415 SHFB_MAGIC_1, 416 SHFB_MAGIC_2, 417 SHFB_MAGIC_3, 418 SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */ 419 }; 420 421 static void staticfile_closefn(CPUState *cs, GuestFD *gf) 422 { 423 /* Nothing to do */ 424 common_semi_cb(cs, 0, 0); 425 } 426 427 static void staticfile_writefn(CPUState *cs, GuestFD *gf, 428 target_ulong buf, uint32_t len) 429 { 430 /* This fd can never be open for writing */ 431 common_semi_cb(cs, -1, EBADF); 432 } 433 434 static void staticfile_readfn(CPUState *cs, GuestFD *gf, 435 target_ulong buf, uint32_t len) 436 { 437 CPUArchState *env = cs->env_ptr; 438 uint32_t i = 0; 439 char *s; 440 441 (void) env; /* Used in arm softmmu lock_user implicitly */ 442 s = lock_user(VERIFY_WRITE, buf, len, 0); 443 if (s) { 444 for (i = 0; i < len; i++) { 445 if (gf->staticfile.off >= gf->staticfile.len) { 446 break; 447 } 448 s[i] = gf->staticfile.data[gf->staticfile.off]; 449 gf->staticfile.off++; 450 } 451 unlock_user(s, buf, len); 452 } 453 454 /* Return number of bytes not read */ 455 common_semi_cb(cs, len - i, 0); 456 } 457 458 static void staticfile_isattyfn(CPUState *cs, GuestFD *gf) 459 { 460 common_semi_cb(cs, 0, 0); 461 } 462 463 static void staticfile_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset) 464 { 465 gf->staticfile.off = offset; 466 common_semi_cb(cs, 0, 0); 467 } 468 469 static void staticfile_flenfn(CPUState *cs, GuestFD *gf) 470 { 471 common_semi_cb(cs, gf->staticfile.len, 0); 472 } 473 474 typedef struct GuestFDFunctions { 475 sys_closefn *closefn; 476 sys_writefn *writefn; 477 sys_readfn *readfn; 478 sys_isattyfn *isattyfn; 479 sys_seekfn *seekfn; 480 sys_flenfn *flenfn; 481 } GuestFDFunctions; 482 483 static const GuestFDFunctions guestfd_fns[] = { 484 [GuestFDHost] = { 485 .closefn = host_closefn, 486 .writefn = host_writefn, 487 .readfn = host_readfn, 488 .isattyfn = host_isattyfn, 489 .seekfn = host_seekfn, 490 .flenfn = host_flenfn, 491 }, 492 [GuestFDGDB] = { 493 .closefn = gdb_closefn, 494 .writefn = gdb_writefn, 495 .readfn = gdb_readfn, 496 .isattyfn = gdb_isattyfn, 497 .seekfn = gdb_seekfn, 498 .flenfn = gdb_flenfn, 499 }, 500 [GuestFDStatic] = { 501 .closefn = staticfile_closefn, 502 .writefn = staticfile_writefn, 503 .readfn = staticfile_readfn, 504 .isattyfn = staticfile_isattyfn, 505 .seekfn = staticfile_seekfn, 506 .flenfn = staticfile_flenfn, 507 }, 508 }; 509 510 /* 511 * Read the input value from the argument block; fail the semihosting 512 * call if the memory read fails. Eventually we could use a generic 513 * CPUState helper function here. 514 */ 515 516 #define GET_ARG(n) do { \ 517 if (is_64bit_semihosting(env)) { \ 518 if (get_user_u64(arg ## n, args + (n) * 8)) { \ 519 goto do_fault; \ 520 } \ 521 } else { \ 522 if (get_user_u32(arg ## n, args + (n) * 4)) { \ 523 goto do_fault; \ 524 } \ 525 } \ 526 } while (0) 527 528 #define SET_ARG(n, val) \ 529 (is_64bit_semihosting(env) ? \ 530 put_user_u64(val, args + (n) * 8) : \ 531 put_user_u32(val, args + (n) * 4)) 532 533 534 /* 535 * Do a semihosting call. 536 * 537 * The specification always says that the "return register" either 538 * returns a specific value or is corrupted, so we don't need to 539 * report to our caller whether we are returning a value or trying to 540 * leave the register unchanged. We use 0xdeadbeef as the return value 541 * when there isn't a defined return value for the call. 542 */ 543 void do_common_semihosting(CPUState *cs) 544 { 545 CPUArchState *env = cs->env_ptr; 546 target_ulong args; 547 target_ulong arg0, arg1, arg2, arg3; 548 target_ulong ul_ret; 549 char * s; 550 int nr; 551 uint32_t ret; 552 uint32_t len; 553 GuestFD *gf; 554 int64_t elapsed; 555 556 (void) env; /* Used implicitly by arm lock_user macro */ 557 nr = common_semi_arg(cs, 0) & 0xffffffffU; 558 args = common_semi_arg(cs, 1); 559 560 switch (nr) { 561 case TARGET_SYS_OPEN: 562 { 563 int ret, err = 0; 564 int hostfd; 565 566 GET_ARG(0); 567 GET_ARG(1); 568 GET_ARG(2); 569 s = lock_user_string(arg0); 570 if (!s) { 571 goto do_fault; 572 } 573 if (arg1 >= 12) { 574 unlock_user(s, arg0, 0); 575 common_semi_cb(cs, -1, EINVAL); 576 break; 577 } 578 579 if (strcmp(s, ":tt") == 0) { 580 /* 581 * We implement SH_EXT_STDOUT_STDERR, so: 582 * open for read == stdin 583 * open for write == stdout 584 * open for append == stderr 585 */ 586 if (arg1 < 4) { 587 hostfd = STDIN_FILENO; 588 } else if (arg1 < 8) { 589 hostfd = STDOUT_FILENO; 590 } else { 591 hostfd = STDERR_FILENO; 592 } 593 ret = alloc_guestfd(); 594 associate_guestfd(ret, hostfd); 595 } else if (strcmp(s, ":semihosting-features") == 0) { 596 /* We must fail opens for modes other than 0 ('r') or 1 ('rb') */ 597 if (arg1 != 0 && arg1 != 1) { 598 ret = -1; 599 err = EACCES; 600 } else { 601 ret = alloc_guestfd(); 602 staticfile_guestfd(ret, featurefile_data, 603 sizeof(featurefile_data)); 604 } 605 } else if (use_gdb_syscalls()) { 606 unlock_user(s, arg0, 0); 607 common_semi_open_guestfd = alloc_guestfd(); 608 gdb_do_syscall(common_semi_open_cb, 609 "open,%s,%x,1a4", arg0, (int)arg2 + 1, 610 gdb_open_modeflags[arg1]); 611 break; 612 } else { 613 hostfd = open(s, open_modeflags[arg1], 0644); 614 if (hostfd < 0) { 615 ret = -1; 616 err = errno; 617 } else { 618 ret = alloc_guestfd(); 619 associate_guestfd(ret, hostfd); 620 } 621 } 622 unlock_user(s, arg0, 0); 623 common_semi_cb(cs, ret, err); 624 break; 625 } 626 627 case TARGET_SYS_CLOSE: 628 GET_ARG(0); 629 630 gf = get_guestfd(arg0); 631 if (!gf) { 632 goto do_badf; 633 } 634 guestfd_fns[gf->type].closefn(cs, gf); 635 dealloc_guestfd(arg0); 636 break; 637 638 case TARGET_SYS_WRITEC: 639 qemu_semihosting_console_outc(cs->env_ptr, args); 640 common_semi_set_ret(cs, 0xdeadbeef); 641 break; 642 643 case TARGET_SYS_WRITE0: 644 ret = qemu_semihosting_console_outs(cs->env_ptr, args); 645 common_semi_set_ret(cs, ret); 646 break; 647 648 case TARGET_SYS_WRITE: 649 GET_ARG(0); 650 GET_ARG(1); 651 GET_ARG(2); 652 len = arg2; 653 654 gf = get_guestfd(arg0); 655 if (!gf) { 656 goto do_badf; 657 } 658 guestfd_fns[gf->type].writefn(cs, gf, arg1, len); 659 break; 660 661 case TARGET_SYS_READ: 662 GET_ARG(0); 663 GET_ARG(1); 664 GET_ARG(2); 665 len = arg2; 666 667 gf = get_guestfd(arg0); 668 if (!gf) { 669 goto do_badf; 670 } 671 guestfd_fns[gf->type].readfn(cs, gf, arg1, len); 672 break; 673 674 case TARGET_SYS_READC: 675 ret = qemu_semihosting_console_inc(cs->env_ptr); 676 common_semi_set_ret(cs, ret); 677 break; 678 679 case TARGET_SYS_ISERROR: 680 GET_ARG(0); 681 common_semi_set_ret(cs, (target_long)arg0 < 0); 682 break; 683 684 case TARGET_SYS_ISTTY: 685 GET_ARG(0); 686 687 gf = get_guestfd(arg0); 688 if (!gf) { 689 goto do_badf; 690 } 691 guestfd_fns[gf->type].isattyfn(cs, gf); 692 break; 693 694 case TARGET_SYS_SEEK: 695 GET_ARG(0); 696 GET_ARG(1); 697 698 gf = get_guestfd(arg0); 699 if (!gf) { 700 goto do_badf; 701 } 702 guestfd_fns[gf->type].seekfn(cs, gf, arg1); 703 break; 704 705 case TARGET_SYS_FLEN: 706 GET_ARG(0); 707 708 gf = get_guestfd(arg0); 709 if (!gf) { 710 goto do_badf; 711 } 712 guestfd_fns[gf->type].flenfn(cs, gf); 713 break; 714 715 case TARGET_SYS_TMPNAM: 716 { 717 int len; 718 char *p; 719 720 GET_ARG(0); 721 GET_ARG(1); 722 GET_ARG(2); 723 len = asprintf(&s, "/tmp/qemu-%x%02x", getpid(), (int)arg1 & 0xff); 724 /* Make sure there's enough space in the buffer */ 725 if (len < 0 || len >= arg2) { 726 common_semi_set_ret(cs, -1); 727 break; 728 } 729 p = lock_user(VERIFY_WRITE, arg0, len, 0); 730 if (!p) { 731 goto do_fault; 732 } 733 memcpy(p, s, len + 1); 734 unlock_user(p, arg0, len); 735 free(s); 736 common_semi_set_ret(cs, 0); 737 break; 738 } 739 740 case TARGET_SYS_REMOVE: 741 GET_ARG(0); 742 GET_ARG(1); 743 if (use_gdb_syscalls()) { 744 gdb_do_syscall(common_semi_cb, "unlink,%s", 745 arg0, (int)arg1 + 1); 746 break; 747 } 748 s = lock_user_string(arg0); 749 if (!s) { 750 goto do_fault; 751 } 752 ret = remove(s); 753 unlock_user(s, arg0, 0); 754 common_semi_cb(cs, ret, ret ? errno : 0); 755 break; 756 757 case TARGET_SYS_RENAME: 758 GET_ARG(0); 759 GET_ARG(1); 760 GET_ARG(2); 761 GET_ARG(3); 762 if (use_gdb_syscalls()) { 763 gdb_do_syscall(common_semi_cb, "rename,%s,%s", 764 arg0, (int)arg1 + 1, arg2, (int)arg3 + 1); 765 } else { 766 char *s2; 767 768 s = lock_user_string(arg0); 769 if (!s) { 770 goto do_fault; 771 } 772 s2 = lock_user_string(arg2); 773 if (!s2) { 774 unlock_user(s, arg0, 0); 775 goto do_fault; 776 } 777 ret = rename(s, s2); 778 unlock_user(s2, arg2, 0); 779 unlock_user(s, arg0, 0); 780 common_semi_cb(cs, ret, ret ? errno : 0); 781 } 782 break; 783 784 case TARGET_SYS_CLOCK: 785 common_semi_set_ret(cs, clock() / (CLOCKS_PER_SEC / 100)); 786 break; 787 788 case TARGET_SYS_TIME: 789 ul_ret = time(NULL); 790 common_semi_cb(cs, ul_ret, ul_ret == -1 ? errno : 0); 791 break; 792 793 case TARGET_SYS_SYSTEM: 794 GET_ARG(0); 795 GET_ARG(1); 796 if (use_gdb_syscalls()) { 797 gdb_do_syscall(common_semi_cb, "system,%s", arg0, (int)arg1 + 1); 798 break; 799 } 800 s = lock_user_string(arg0); 801 if (!s) { 802 goto do_fault; 803 } 804 ret = system(s); 805 unlock_user(s, arg0, 0); 806 common_semi_cb(cs, ret, ret == -1 ? errno : 0); 807 break; 808 809 case TARGET_SYS_ERRNO: 810 common_semi_set_ret(cs, get_swi_errno(cs)); 811 break; 812 813 case TARGET_SYS_GET_CMDLINE: 814 { 815 /* Build a command-line from the original argv. 816 * 817 * The inputs are: 818 * * arg0, pointer to a buffer of at least the size 819 * specified in arg1. 820 * * arg1, size of the buffer pointed to by arg0 in 821 * bytes. 822 * 823 * The outputs are: 824 * * arg0, pointer to null-terminated string of the 825 * command line. 826 * * arg1, length of the string pointed to by arg0. 827 */ 828 829 char *output_buffer; 830 size_t input_size; 831 size_t output_size; 832 int status = 0; 833 #if !defined(CONFIG_USER_ONLY) 834 const char *cmdline; 835 #else 836 TaskState *ts = cs->opaque; 837 #endif 838 GET_ARG(0); 839 GET_ARG(1); 840 input_size = arg1; 841 /* Compute the size of the output string. */ 842 #if !defined(CONFIG_USER_ONLY) 843 cmdline = semihosting_get_cmdline(); 844 if (cmdline == NULL) { 845 cmdline = ""; /* Default to an empty line. */ 846 } 847 output_size = strlen(cmdline) + 1; /* Count terminating 0. */ 848 #else 849 unsigned int i; 850 851 output_size = ts->info->env_strings - ts->info->arg_strings; 852 if (!output_size) { 853 /* 854 * We special-case the "empty command line" case (argc==0). 855 * Just provide the terminating 0. 856 */ 857 output_size = 1; 858 } 859 #endif 860 861 if (output_size > input_size) { 862 /* Not enough space to store command-line arguments. */ 863 common_semi_cb(cs, -1, E2BIG); 864 break; 865 } 866 867 /* Adjust the command-line length. */ 868 if (SET_ARG(1, output_size - 1)) { 869 /* Couldn't write back to argument block */ 870 goto do_fault; 871 } 872 873 /* Lock the buffer on the ARM side. */ 874 output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0); 875 if (!output_buffer) { 876 goto do_fault; 877 } 878 879 /* Copy the command-line arguments. */ 880 #if !defined(CONFIG_USER_ONLY) 881 pstrcpy(output_buffer, output_size, cmdline); 882 #else 883 if (output_size == 1) { 884 /* Empty command-line. */ 885 output_buffer[0] = '\0'; 886 goto out; 887 } 888 889 if (copy_from_user(output_buffer, ts->info->arg_strings, 890 output_size)) { 891 unlock_user(output_buffer, arg0, 0); 892 goto do_fault; 893 } 894 895 /* Separate arguments by white spaces. */ 896 for (i = 0; i < output_size - 1; i++) { 897 if (output_buffer[i] == 0) { 898 output_buffer[i] = ' '; 899 } 900 } 901 out: 902 #endif 903 /* Unlock the buffer on the ARM side. */ 904 unlock_user(output_buffer, arg0, output_size); 905 common_semi_cb(cs, status, 0); 906 } 907 break; 908 909 case TARGET_SYS_HEAPINFO: 910 { 911 target_ulong retvals[4]; 912 int i; 913 #ifdef CONFIG_USER_ONLY 914 TaskState *ts = cs->opaque; 915 target_ulong limit; 916 #else 917 LayoutInfo info = common_semi_find_bases(cs); 918 #endif 919 920 GET_ARG(0); 921 922 #ifdef CONFIG_USER_ONLY 923 /* 924 * Some C libraries assume the heap immediately follows .bss, so 925 * allocate it using sbrk. 926 */ 927 if (!ts->heap_limit) { 928 abi_ulong ret; 929 930 ts->heap_base = do_brk(0); 931 limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE; 932 /* Try a big heap, and reduce the size if that fails. */ 933 for (;;) { 934 ret = do_brk(limit); 935 if (ret >= limit) { 936 break; 937 } 938 limit = (ts->heap_base >> 1) + (limit >> 1); 939 } 940 ts->heap_limit = limit; 941 } 942 943 retvals[0] = ts->heap_base; 944 retvals[1] = ts->heap_limit; 945 retvals[2] = ts->stack_base; 946 retvals[3] = 0; /* Stack limit. */ 947 #else 948 retvals[0] = info.heapbase; /* Heap Base */ 949 retvals[1] = info.heaplimit; /* Heap Limit */ 950 retvals[2] = info.heaplimit; /* Stack base */ 951 retvals[3] = info.heapbase; /* Stack limit. */ 952 #endif 953 954 for (i = 0; i < ARRAY_SIZE(retvals); i++) { 955 bool fail; 956 957 if (is_64bit_semihosting(env)) { 958 fail = put_user_u64(retvals[i], arg0 + i * 8); 959 } else { 960 fail = put_user_u32(retvals[i], arg0 + i * 4); 961 } 962 963 if (fail) { 964 /* Couldn't write back to argument block */ 965 goto do_fault; 966 } 967 } 968 common_semi_set_ret(cs, 0); 969 } 970 break; 971 972 case TARGET_SYS_EXIT: 973 case TARGET_SYS_EXIT_EXTENDED: 974 if (common_semi_sys_exit_extended(cs, nr)) { 975 /* 976 * The A64 version of SYS_EXIT takes a parameter block, 977 * so the application-exit type can return a subcode which 978 * is the exit status code from the application. 979 * SYS_EXIT_EXTENDED is an a new-in-v2.0 optional function 980 * which allows A32/T32 guests to also provide a status code. 981 */ 982 GET_ARG(0); 983 GET_ARG(1); 984 985 if (arg0 == ADP_Stopped_ApplicationExit) { 986 ret = arg1; 987 } else { 988 ret = 1; 989 } 990 } else { 991 /* 992 * The A32/T32 version of SYS_EXIT specifies only 993 * Stopped_ApplicationExit as normal exit, but does not 994 * allow the guest to specify the exit status code. 995 * Everything else is considered an error. 996 */ 997 ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1; 998 } 999 gdb_exit(ret); 1000 exit(ret); 1001 1002 case TARGET_SYS_ELAPSED: 1003 elapsed = get_clock() - clock_start; 1004 if (sizeof(target_ulong) == 8) { 1005 SET_ARG(0, elapsed); 1006 } else { 1007 SET_ARG(0, (uint32_t) elapsed); 1008 SET_ARG(1, (uint32_t) (elapsed >> 32)); 1009 } 1010 common_semi_set_ret(cs, 0); 1011 break; 1012 1013 case TARGET_SYS_TICKFREQ: 1014 /* qemu always uses nsec */ 1015 common_semi_set_ret(cs, 1000000000); 1016 break; 1017 1018 case TARGET_SYS_SYNCCACHE: 1019 /* 1020 * Clean the D-cache and invalidate the I-cache for the specified 1021 * virtual address range. This is a nop for us since we don't 1022 * implement caches. This is only present on A64. 1023 */ 1024 if (common_semi_has_synccache(env)) { 1025 common_semi_set_ret(cs, 0); 1026 break; 1027 } 1028 /* fall through */ 1029 default: 1030 fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr); 1031 cpu_dump_state(cs, stderr, 0); 1032 abort(); 1033 1034 do_badf: 1035 common_semi_cb(cs, -1, EBADF); 1036 break; 1037 do_fault: 1038 common_semi_cb(cs, -1, EFAULT); 1039 break; 1040 } 1041 } 1042