1ad520a97SPhilippe Mathieu-Daudé /* 2ad520a97SPhilippe Mathieu-Daudé * Unified Hosting Interface syscalls. 3ad520a97SPhilippe Mathieu-Daudé * 4ad520a97SPhilippe Mathieu-Daudé * Copyright (c) 2015 Imagination Technologies 5ad520a97SPhilippe Mathieu-Daudé * 6ad520a97SPhilippe Mathieu-Daudé * This library is free software; you can redistribute it and/or 7ad520a97SPhilippe Mathieu-Daudé * modify it under the terms of the GNU Lesser General Public 8ad520a97SPhilippe Mathieu-Daudé * License as published by the Free Software Foundation; either 9ad520a97SPhilippe Mathieu-Daudé * version 2.1 of the License, or (at your option) any later version. 10ad520a97SPhilippe Mathieu-Daudé * 11ad520a97SPhilippe Mathieu-Daudé * This library is distributed in the hope that it will be useful, 12ad520a97SPhilippe Mathieu-Daudé * but WITHOUT ANY WARRANTY; without even the implied warranty of 13ad520a97SPhilippe Mathieu-Daudé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14ad520a97SPhilippe Mathieu-Daudé * Lesser General Public License for more details. 15ad520a97SPhilippe Mathieu-Daudé * 16ad520a97SPhilippe Mathieu-Daudé * You should have received a copy of the GNU Lesser General Public 17ad520a97SPhilippe Mathieu-Daudé * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18ad520a97SPhilippe Mathieu-Daudé */ 19ad520a97SPhilippe Mathieu-Daudé 20ad520a97SPhilippe Mathieu-Daudé #include "qemu/osdep.h" 21ad520a97SPhilippe Mathieu-Daudé #include "cpu.h" 22ad520a97SPhilippe Mathieu-Daudé #include "qemu/log.h" 23c89a14adSRichard Henderson #include "semihosting/softmmu-uaccess.h" 24ad520a97SPhilippe Mathieu-Daudé #include "semihosting/semihost.h" 25ad520a97SPhilippe Mathieu-Daudé #include "semihosting/console.h" 268ec7e3c5SRichard Henderson #include "internal.h" 27ad520a97SPhilippe Mathieu-Daudé 28ad520a97SPhilippe Mathieu-Daudé typedef enum UHIOp { 29ad520a97SPhilippe Mathieu-Daudé UHI_exit = 1, 30ad520a97SPhilippe Mathieu-Daudé UHI_open = 2, 31ad520a97SPhilippe Mathieu-Daudé UHI_close = 3, 32ad520a97SPhilippe Mathieu-Daudé UHI_read = 4, 33ad520a97SPhilippe Mathieu-Daudé UHI_write = 5, 34ad520a97SPhilippe Mathieu-Daudé UHI_lseek = 6, 35ad520a97SPhilippe Mathieu-Daudé UHI_unlink = 7, 36ad520a97SPhilippe Mathieu-Daudé UHI_fstat = 8, 37ad520a97SPhilippe Mathieu-Daudé UHI_argc = 9, 38ad520a97SPhilippe Mathieu-Daudé UHI_argnlen = 10, 39ad520a97SPhilippe Mathieu-Daudé UHI_argn = 11, 40ad520a97SPhilippe Mathieu-Daudé UHI_plog = 13, 41ad520a97SPhilippe Mathieu-Daudé UHI_assert = 14, 42ad520a97SPhilippe Mathieu-Daudé UHI_pread = 19, 43ad520a97SPhilippe Mathieu-Daudé UHI_pwrite = 20, 44ad520a97SPhilippe Mathieu-Daudé UHI_link = 22 45ad520a97SPhilippe Mathieu-Daudé } UHIOp; 46ad520a97SPhilippe Mathieu-Daudé 47ad520a97SPhilippe Mathieu-Daudé typedef struct UHIStat { 48ad520a97SPhilippe Mathieu-Daudé int16_t uhi_st_dev; 49ad520a97SPhilippe Mathieu-Daudé uint16_t uhi_st_ino; 50ad520a97SPhilippe Mathieu-Daudé uint32_t uhi_st_mode; 51ad520a97SPhilippe Mathieu-Daudé uint16_t uhi_st_nlink; 52ad520a97SPhilippe Mathieu-Daudé uint16_t uhi_st_uid; 53ad520a97SPhilippe Mathieu-Daudé uint16_t uhi_st_gid; 54ad520a97SPhilippe Mathieu-Daudé int16_t uhi_st_rdev; 55ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_size; 56ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_atime; 57ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_spare1; 58ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_mtime; 59ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_spare2; 60ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_ctime; 61ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_spare3; 62ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_blksize; 63ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_blocks; 64ad520a97SPhilippe Mathieu-Daudé uint64_t uhi_st_spare4[2]; 65ad520a97SPhilippe Mathieu-Daudé } UHIStat; 66ad520a97SPhilippe Mathieu-Daudé 67ad520a97SPhilippe Mathieu-Daudé enum UHIOpenFlags { 68ad520a97SPhilippe Mathieu-Daudé UHIOpen_RDONLY = 0x0, 69ad520a97SPhilippe Mathieu-Daudé UHIOpen_WRONLY = 0x1, 70ad520a97SPhilippe Mathieu-Daudé UHIOpen_RDWR = 0x2, 71ad520a97SPhilippe Mathieu-Daudé UHIOpen_APPEND = 0x8, 72ad520a97SPhilippe Mathieu-Daudé UHIOpen_CREAT = 0x200, 73ad520a97SPhilippe Mathieu-Daudé UHIOpen_TRUNC = 0x400, 74ad520a97SPhilippe Mathieu-Daudé UHIOpen_EXCL = 0x800 75ad520a97SPhilippe Mathieu-Daudé }; 76ad520a97SPhilippe Mathieu-Daudé 777ba6e53aSRichard Henderson enum UHIErrno { 787ba6e53aSRichard Henderson UHI_EACCESS = 13, 797ba6e53aSRichard Henderson UHI_EAGAIN = 11, 807ba6e53aSRichard Henderson UHI_EBADF = 9, 817ba6e53aSRichard Henderson UHI_EBADMSG = 77, 827ba6e53aSRichard Henderson UHI_EBUSY = 16, 837ba6e53aSRichard Henderson UHI_ECONNRESET = 104, 847ba6e53aSRichard Henderson UHI_EEXIST = 17, 857ba6e53aSRichard Henderson UHI_EFBIG = 27, 867ba6e53aSRichard Henderson UHI_EINTR = 4, 877ba6e53aSRichard Henderson UHI_EINVAL = 22, 887ba6e53aSRichard Henderson UHI_EIO = 5, 897ba6e53aSRichard Henderson UHI_EISDIR = 21, 907ba6e53aSRichard Henderson UHI_ELOOP = 92, 917ba6e53aSRichard Henderson UHI_EMFILE = 24, 927ba6e53aSRichard Henderson UHI_EMLINK = 31, 937ba6e53aSRichard Henderson UHI_ENAMETOOLONG = 91, 947ba6e53aSRichard Henderson UHI_ENETDOWN = 115, 957ba6e53aSRichard Henderson UHI_ENETUNREACH = 114, 967ba6e53aSRichard Henderson UHI_ENFILE = 23, 977ba6e53aSRichard Henderson UHI_ENOBUFS = 105, 987ba6e53aSRichard Henderson UHI_ENOENT = 2, 997ba6e53aSRichard Henderson UHI_ENOMEM = 12, 1007ba6e53aSRichard Henderson UHI_ENOSPC = 28, 1017ba6e53aSRichard Henderson UHI_ENOSR = 63, 1027ba6e53aSRichard Henderson UHI_ENOTCONN = 128, 1037ba6e53aSRichard Henderson UHI_ENOTDIR = 20, 1047ba6e53aSRichard Henderson UHI_ENXIO = 6, 1057ba6e53aSRichard Henderson UHI_EOVERFLOW = 139, 1067ba6e53aSRichard Henderson UHI_EPERM = 1, 1077ba6e53aSRichard Henderson UHI_EPIPE = 32, 1087ba6e53aSRichard Henderson UHI_ERANGE = 34, 1097ba6e53aSRichard Henderson UHI_EROFS = 30, 1107ba6e53aSRichard Henderson UHI_ESPIPE = 29, 1117ba6e53aSRichard Henderson UHI_ETIMEDOUT = 116, 1127ba6e53aSRichard Henderson UHI_ETXTBSY = 26, 1137ba6e53aSRichard Henderson UHI_EWOULDBLOCK = 11, 1147ba6e53aSRichard Henderson UHI_EXDEV = 18, 1157ba6e53aSRichard Henderson }; 1167ba6e53aSRichard Henderson 117d859a77dSPhilippe Mathieu-Daudé static int errno_mips(int host_errno) 118d859a77dSPhilippe Mathieu-Daudé { 119ad520a97SPhilippe Mathieu-Daudé /* Errno values taken from asm-mips/errno.h */ 120d859a77dSPhilippe Mathieu-Daudé switch (host_errno) { 121d859a77dSPhilippe Mathieu-Daudé case 0: return 0; 122d859a77dSPhilippe Mathieu-Daudé case ENAMETOOLONG: return 78; 123ad520a97SPhilippe Mathieu-Daudé #ifdef EOVERFLOW 124d859a77dSPhilippe Mathieu-Daudé case EOVERFLOW: return 79; 125ad520a97SPhilippe Mathieu-Daudé #endif 126ad520a97SPhilippe Mathieu-Daudé #ifdef ELOOP 127d859a77dSPhilippe Mathieu-Daudé case ELOOP: return 90; 128ad520a97SPhilippe Mathieu-Daudé #endif 129d859a77dSPhilippe Mathieu-Daudé default: return EINVAL; 130ad520a97SPhilippe Mathieu-Daudé } 131ad520a97SPhilippe Mathieu-Daudé } 132ad520a97SPhilippe Mathieu-Daudé 133ad520a97SPhilippe Mathieu-Daudé static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src, 134ad520a97SPhilippe Mathieu-Daudé target_ulong vaddr) 135ad520a97SPhilippe Mathieu-Daudé { 136ad520a97SPhilippe Mathieu-Daudé hwaddr len = sizeof(struct UHIStat); 137ad520a97SPhilippe Mathieu-Daudé UHIStat *dst = lock_user(VERIFY_WRITE, vaddr, len, 0); 138ad520a97SPhilippe Mathieu-Daudé if (!dst) { 139ad520a97SPhilippe Mathieu-Daudé errno = EFAULT; 140ad520a97SPhilippe Mathieu-Daudé return -1; 141ad520a97SPhilippe Mathieu-Daudé } 142ad520a97SPhilippe Mathieu-Daudé 143ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_dev = tswap16(src->st_dev); 144ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_ino = tswap16(src->st_ino); 145ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_mode = tswap32(src->st_mode); 146ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_nlink = tswap16(src->st_nlink); 147ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_uid = tswap16(src->st_uid); 148ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_gid = tswap16(src->st_gid); 149ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_rdev = tswap16(src->st_rdev); 150ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_size = tswap64(src->st_size); 151ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_atime = tswap64(src->st_atime); 152ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_mtime = tswap64(src->st_mtime); 153ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_ctime = tswap64(src->st_ctime); 154ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32 155ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blksize = 0; 156ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blocks = 0; 157ad520a97SPhilippe Mathieu-Daudé #else 158ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blksize = tswap64(src->st_blksize); 159ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blocks = tswap64(src->st_blocks); 160ad520a97SPhilippe Mathieu-Daudé #endif 161ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, len); 162ad520a97SPhilippe Mathieu-Daudé return 0; 163ad520a97SPhilippe Mathieu-Daudé } 164ad520a97SPhilippe Mathieu-Daudé 165ad520a97SPhilippe Mathieu-Daudé static int get_open_flags(target_ulong target_flags) 166ad520a97SPhilippe Mathieu-Daudé { 167ad520a97SPhilippe Mathieu-Daudé int open_flags = 0; 168ad520a97SPhilippe Mathieu-Daudé 169ad520a97SPhilippe Mathieu-Daudé if (target_flags & UHIOpen_RDWR) { 170ad520a97SPhilippe Mathieu-Daudé open_flags |= O_RDWR; 171ad520a97SPhilippe Mathieu-Daudé } else if (target_flags & UHIOpen_WRONLY) { 172ad520a97SPhilippe Mathieu-Daudé open_flags |= O_WRONLY; 173ad520a97SPhilippe Mathieu-Daudé } else { 174ad520a97SPhilippe Mathieu-Daudé open_flags |= O_RDONLY; 175ad520a97SPhilippe Mathieu-Daudé } 176ad520a97SPhilippe Mathieu-Daudé 177ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_APPEND) ? O_APPEND : 0; 178ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_CREAT) ? O_CREAT : 0; 179ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_TRUNC) ? O_TRUNC : 0; 180ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_EXCL) ? O_EXCL : 0; 181ad520a97SPhilippe Mathieu-Daudé 182ad520a97SPhilippe Mathieu-Daudé return open_flags; 183ad520a97SPhilippe Mathieu-Daudé } 184ad520a97SPhilippe Mathieu-Daudé 185ad520a97SPhilippe Mathieu-Daudé static int write_to_file(CPUMIPSState *env, target_ulong fd, target_ulong vaddr, 186ad520a97SPhilippe Mathieu-Daudé target_ulong len, target_ulong offset) 187ad520a97SPhilippe Mathieu-Daudé { 188ad520a97SPhilippe Mathieu-Daudé int num_of_bytes; 189ad520a97SPhilippe Mathieu-Daudé void *dst = lock_user(VERIFY_READ, vaddr, len, 1); 190ad520a97SPhilippe Mathieu-Daudé if (!dst) { 191ad520a97SPhilippe Mathieu-Daudé errno = EFAULT; 192ad520a97SPhilippe Mathieu-Daudé return -1; 193ad520a97SPhilippe Mathieu-Daudé } 194ad520a97SPhilippe Mathieu-Daudé 195ad520a97SPhilippe Mathieu-Daudé if (offset) { 196ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32 197ad520a97SPhilippe Mathieu-Daudé num_of_bytes = 0; 198ad520a97SPhilippe Mathieu-Daudé #else 199ad520a97SPhilippe Mathieu-Daudé num_of_bytes = pwrite(fd, dst, len, offset); 200ad520a97SPhilippe Mathieu-Daudé #endif 201ad520a97SPhilippe Mathieu-Daudé } else { 202ad520a97SPhilippe Mathieu-Daudé num_of_bytes = write(fd, dst, len); 203ad520a97SPhilippe Mathieu-Daudé } 204ad520a97SPhilippe Mathieu-Daudé 205ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, 0); 206ad520a97SPhilippe Mathieu-Daudé return num_of_bytes; 207ad520a97SPhilippe Mathieu-Daudé } 208ad520a97SPhilippe Mathieu-Daudé 209ad520a97SPhilippe Mathieu-Daudé static int read_from_file(CPUMIPSState *env, target_ulong fd, 210ad520a97SPhilippe Mathieu-Daudé target_ulong vaddr, target_ulong len, 211ad520a97SPhilippe Mathieu-Daudé target_ulong offset) 212ad520a97SPhilippe Mathieu-Daudé { 213ad520a97SPhilippe Mathieu-Daudé int num_of_bytes; 214ad520a97SPhilippe Mathieu-Daudé void *dst = lock_user(VERIFY_WRITE, vaddr, len, 0); 215ad520a97SPhilippe Mathieu-Daudé if (!dst) { 216ad520a97SPhilippe Mathieu-Daudé errno = EFAULT; 217ad520a97SPhilippe Mathieu-Daudé return -1; 218ad520a97SPhilippe Mathieu-Daudé } 219ad520a97SPhilippe Mathieu-Daudé 220ad520a97SPhilippe Mathieu-Daudé if (offset) { 221ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32 222ad520a97SPhilippe Mathieu-Daudé num_of_bytes = 0; 223ad520a97SPhilippe Mathieu-Daudé #else 224ad520a97SPhilippe Mathieu-Daudé num_of_bytes = pread(fd, dst, len, offset); 225ad520a97SPhilippe Mathieu-Daudé #endif 226ad520a97SPhilippe Mathieu-Daudé } else { 227ad520a97SPhilippe Mathieu-Daudé num_of_bytes = read(fd, dst, len); 228ad520a97SPhilippe Mathieu-Daudé } 229ad520a97SPhilippe Mathieu-Daudé 230ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, len); 231ad520a97SPhilippe Mathieu-Daudé return num_of_bytes; 232ad520a97SPhilippe Mathieu-Daudé } 233ad520a97SPhilippe Mathieu-Daudé 234ad520a97SPhilippe Mathieu-Daudé static int copy_argn_to_target(CPUMIPSState *env, int arg_num, 235ad520a97SPhilippe Mathieu-Daudé target_ulong vaddr) 236ad520a97SPhilippe Mathieu-Daudé { 237ad520a97SPhilippe Mathieu-Daudé int strsize = strlen(semihosting_get_arg(arg_num)) + 1; 238ad520a97SPhilippe Mathieu-Daudé char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0); 239ad520a97SPhilippe Mathieu-Daudé if (!dst) { 240ad520a97SPhilippe Mathieu-Daudé return -1; 241ad520a97SPhilippe Mathieu-Daudé } 242ad520a97SPhilippe Mathieu-Daudé 243ad520a97SPhilippe Mathieu-Daudé strcpy(dst, semihosting_get_arg(arg_num)); 244ad520a97SPhilippe Mathieu-Daudé 245ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, strsize); 246ad520a97SPhilippe Mathieu-Daudé return 0; 247ad520a97SPhilippe Mathieu-Daudé } 248ad520a97SPhilippe Mathieu-Daudé 249ad520a97SPhilippe Mathieu-Daudé #define GET_TARGET_STRING(p, addr) \ 250ad520a97SPhilippe Mathieu-Daudé do { \ 251ad520a97SPhilippe Mathieu-Daudé p = lock_user_string(addr); \ 252ad520a97SPhilippe Mathieu-Daudé if (!p) { \ 253ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; \ 254ad520a97SPhilippe Mathieu-Daudé gpr[3] = EFAULT; \ 255ad520a97SPhilippe Mathieu-Daudé return; \ 256ad520a97SPhilippe Mathieu-Daudé } \ 257ad520a97SPhilippe Mathieu-Daudé } while (0) 258ad520a97SPhilippe Mathieu-Daudé 259ad520a97SPhilippe Mathieu-Daudé #define GET_TARGET_STRINGS_2(p, addr, p2, addr2) \ 260ad520a97SPhilippe Mathieu-Daudé do { \ 261ad520a97SPhilippe Mathieu-Daudé p = lock_user_string(addr); \ 262ad520a97SPhilippe Mathieu-Daudé if (!p) { \ 263ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; \ 264ad520a97SPhilippe Mathieu-Daudé gpr[3] = EFAULT; \ 265ad520a97SPhilippe Mathieu-Daudé return; \ 266ad520a97SPhilippe Mathieu-Daudé } \ 267ad520a97SPhilippe Mathieu-Daudé p2 = lock_user_string(addr2); \ 268ad520a97SPhilippe Mathieu-Daudé if (!p2) { \ 269ad520a97SPhilippe Mathieu-Daudé unlock_user(p, addr, 0); \ 270ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; \ 271ad520a97SPhilippe Mathieu-Daudé gpr[3] = EFAULT; \ 272ad520a97SPhilippe Mathieu-Daudé return; \ 273ad520a97SPhilippe Mathieu-Daudé } \ 274ad520a97SPhilippe Mathieu-Daudé } while (0) 275ad520a97SPhilippe Mathieu-Daudé 276ad520a97SPhilippe Mathieu-Daudé #define FREE_TARGET_STRING(p, gpr) \ 277ad520a97SPhilippe Mathieu-Daudé do { \ 278ad520a97SPhilippe Mathieu-Daudé unlock_user(p, gpr, 0); \ 279ad520a97SPhilippe Mathieu-Daudé } while (0) 280ad520a97SPhilippe Mathieu-Daudé 2818ec7e3c5SRichard Henderson void mips_semihosting(CPUMIPSState *env) 282ad520a97SPhilippe Mathieu-Daudé { 283ad520a97SPhilippe Mathieu-Daudé target_ulong *gpr = env->active_tc.gpr; 284ad520a97SPhilippe Mathieu-Daudé const UHIOp op = gpr[25]; 285ad520a97SPhilippe Mathieu-Daudé char *p, *p2; 286ad520a97SPhilippe Mathieu-Daudé 287ad520a97SPhilippe Mathieu-Daudé switch (op) { 288ad520a97SPhilippe Mathieu-Daudé case UHI_exit: 289ad520a97SPhilippe Mathieu-Daudé qemu_log("UHI(%d): exit(%d)\n", op, (int)gpr[4]); 290ad520a97SPhilippe Mathieu-Daudé exit(gpr[4]); 291ad520a97SPhilippe Mathieu-Daudé case UHI_open: 292ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRING(p, gpr[4]); 293ad520a97SPhilippe Mathieu-Daudé if (!strcmp("/dev/stdin", p)) { 294ad520a97SPhilippe Mathieu-Daudé gpr[2] = 0; 295ad520a97SPhilippe Mathieu-Daudé } else if (!strcmp("/dev/stdout", p)) { 296ad520a97SPhilippe Mathieu-Daudé gpr[2] = 1; 297ad520a97SPhilippe Mathieu-Daudé } else if (!strcmp("/dev/stderr", p)) { 298ad520a97SPhilippe Mathieu-Daudé gpr[2] = 2; 299ad520a97SPhilippe Mathieu-Daudé } else { 300ad520a97SPhilippe Mathieu-Daudé gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]); 301ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 302ad520a97SPhilippe Mathieu-Daudé } 303ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 304ad520a97SPhilippe Mathieu-Daudé break; 305ad520a97SPhilippe Mathieu-Daudé case UHI_close: 306ad520a97SPhilippe Mathieu-Daudé if (gpr[4] < 3) { 307ad520a97SPhilippe Mathieu-Daudé /* ignore closing stdin/stdout/stderr */ 308ad520a97SPhilippe Mathieu-Daudé gpr[2] = 0; 309ad520a97SPhilippe Mathieu-Daudé return; 310ad520a97SPhilippe Mathieu-Daudé } 311ad520a97SPhilippe Mathieu-Daudé gpr[2] = close(gpr[4]); 312ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 313ad520a97SPhilippe Mathieu-Daudé break; 314ad520a97SPhilippe Mathieu-Daudé case UHI_read: 315ad520a97SPhilippe Mathieu-Daudé gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], 0); 316ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 317ad520a97SPhilippe Mathieu-Daudé break; 318ad520a97SPhilippe Mathieu-Daudé case UHI_write: 319ad520a97SPhilippe Mathieu-Daudé gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], 0); 320ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 321ad520a97SPhilippe Mathieu-Daudé break; 322ad520a97SPhilippe Mathieu-Daudé case UHI_lseek: 323ad520a97SPhilippe Mathieu-Daudé gpr[2] = lseek(gpr[4], gpr[5], gpr[6]); 324ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 325ad520a97SPhilippe Mathieu-Daudé break; 326ad520a97SPhilippe Mathieu-Daudé case UHI_unlink: 327ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRING(p, gpr[4]); 328ad520a97SPhilippe Mathieu-Daudé gpr[2] = remove(p); 329ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 330ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 331ad520a97SPhilippe Mathieu-Daudé break; 332ad520a97SPhilippe Mathieu-Daudé case UHI_fstat: 333ad520a97SPhilippe Mathieu-Daudé { 334ad520a97SPhilippe Mathieu-Daudé struct stat sbuf; 335ad520a97SPhilippe Mathieu-Daudé memset(&sbuf, 0, sizeof(sbuf)); 336ad520a97SPhilippe Mathieu-Daudé gpr[2] = fstat(gpr[4], &sbuf); 337ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 338ad520a97SPhilippe Mathieu-Daudé if (gpr[2]) { 339ad520a97SPhilippe Mathieu-Daudé return; 340ad520a97SPhilippe Mathieu-Daudé } 341ad520a97SPhilippe Mathieu-Daudé gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]); 342ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 343ad520a97SPhilippe Mathieu-Daudé } 344ad520a97SPhilippe Mathieu-Daudé break; 345ad520a97SPhilippe Mathieu-Daudé case UHI_argc: 346ad520a97SPhilippe Mathieu-Daudé gpr[2] = semihosting_get_argc(); 347ad520a97SPhilippe Mathieu-Daudé break; 348ad520a97SPhilippe Mathieu-Daudé case UHI_argnlen: 349ad520a97SPhilippe Mathieu-Daudé if (gpr[4] >= semihosting_get_argc()) { 350ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; 351ad520a97SPhilippe Mathieu-Daudé return; 352ad520a97SPhilippe Mathieu-Daudé } 353ad520a97SPhilippe Mathieu-Daudé gpr[2] = strlen(semihosting_get_arg(gpr[4])); 354ad520a97SPhilippe Mathieu-Daudé break; 355ad520a97SPhilippe Mathieu-Daudé case UHI_argn: 356ad520a97SPhilippe Mathieu-Daudé if (gpr[4] >= semihosting_get_argc()) { 357ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; 358ad520a97SPhilippe Mathieu-Daudé return; 359ad520a97SPhilippe Mathieu-Daudé } 360ad520a97SPhilippe Mathieu-Daudé gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]); 361ad520a97SPhilippe Mathieu-Daudé break; 362ad520a97SPhilippe Mathieu-Daudé case UHI_plog: 363ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRING(p, gpr[4]); 364ad520a97SPhilippe Mathieu-Daudé p2 = strstr(p, "%d"); 365ad520a97SPhilippe Mathieu-Daudé if (p2) { 366ad520a97SPhilippe Mathieu-Daudé int char_num = p2 - p; 367ad520a97SPhilippe Mathieu-Daudé GString *s = g_string_new_len(p, char_num); 368ad520a97SPhilippe Mathieu-Daudé g_string_append_printf(s, "%d%s", (int)gpr[5], p2 + 2); 369ad520a97SPhilippe Mathieu-Daudé gpr[2] = qemu_semihosting_log_out(s->str, s->len); 370ad520a97SPhilippe Mathieu-Daudé g_string_free(s, true); 371ad520a97SPhilippe Mathieu-Daudé } else { 372ad520a97SPhilippe Mathieu-Daudé gpr[2] = qemu_semihosting_log_out(p, strlen(p)); 373ad520a97SPhilippe Mathieu-Daudé } 374ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 375ad520a97SPhilippe Mathieu-Daudé break; 376ad520a97SPhilippe Mathieu-Daudé case UHI_assert: 377ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); 378ad520a97SPhilippe Mathieu-Daudé printf("assertion '"); 379ad520a97SPhilippe Mathieu-Daudé printf("\"%s\"", p); 380ad520a97SPhilippe Mathieu-Daudé printf("': file \"%s\", line %d\n", p2, (int)gpr[6]); 381ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p2, gpr[5]); 382ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 383ad520a97SPhilippe Mathieu-Daudé abort(); 384ad520a97SPhilippe Mathieu-Daudé break; 385ad520a97SPhilippe Mathieu-Daudé case UHI_pread: 386ad520a97SPhilippe Mathieu-Daudé gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], gpr[7]); 387ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 388ad520a97SPhilippe Mathieu-Daudé break; 389ad520a97SPhilippe Mathieu-Daudé case UHI_pwrite: 390ad520a97SPhilippe Mathieu-Daudé gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], gpr[7]); 391ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 392ad520a97SPhilippe Mathieu-Daudé break; 393ad520a97SPhilippe Mathieu-Daudé #ifndef _WIN32 394ad520a97SPhilippe Mathieu-Daudé case UHI_link: 395ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); 396ad520a97SPhilippe Mathieu-Daudé gpr[2] = link(p, p2); 397ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 398ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p2, gpr[5]); 399ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 400ad520a97SPhilippe Mathieu-Daudé break; 401ad520a97SPhilippe Mathieu-Daudé #endif 402ad520a97SPhilippe Mathieu-Daudé default: 403ad520a97SPhilippe Mathieu-Daudé fprintf(stderr, "Unknown UHI operation %d\n", op); 404ad520a97SPhilippe Mathieu-Daudé abort(); 405ad520a97SPhilippe Mathieu-Daudé } 406ad520a97SPhilippe Mathieu-Daudé return; 407ad520a97SPhilippe Mathieu-Daudé } 408