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