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é 77d859a77dSPhilippe Mathieu-Daudé static int errno_mips(int host_errno) 78d859a77dSPhilippe Mathieu-Daudé { 79ad520a97SPhilippe Mathieu-Daudé /* Errno values taken from asm-mips/errno.h */ 80d859a77dSPhilippe Mathieu-Daudé switch (host_errno) { 81d859a77dSPhilippe Mathieu-Daudé case 0: return 0; 82d859a77dSPhilippe Mathieu-Daudé case ENAMETOOLONG: return 78; 83ad520a97SPhilippe Mathieu-Daudé #ifdef EOVERFLOW 84d859a77dSPhilippe Mathieu-Daudé case EOVERFLOW: return 79; 85ad520a97SPhilippe Mathieu-Daudé #endif 86ad520a97SPhilippe Mathieu-Daudé #ifdef ELOOP 87d859a77dSPhilippe Mathieu-Daudé case ELOOP: return 90; 88ad520a97SPhilippe Mathieu-Daudé #endif 89d859a77dSPhilippe Mathieu-Daudé default: return EINVAL; 90ad520a97SPhilippe Mathieu-Daudé } 91ad520a97SPhilippe Mathieu-Daudé } 92ad520a97SPhilippe Mathieu-Daudé 93ad520a97SPhilippe Mathieu-Daudé static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src, 94ad520a97SPhilippe Mathieu-Daudé target_ulong vaddr) 95ad520a97SPhilippe Mathieu-Daudé { 96ad520a97SPhilippe Mathieu-Daudé hwaddr len = sizeof(struct UHIStat); 97ad520a97SPhilippe Mathieu-Daudé UHIStat *dst = lock_user(VERIFY_WRITE, vaddr, len, 0); 98ad520a97SPhilippe Mathieu-Daudé if (!dst) { 99ad520a97SPhilippe Mathieu-Daudé errno = EFAULT; 100ad520a97SPhilippe Mathieu-Daudé return -1; 101ad520a97SPhilippe Mathieu-Daudé } 102ad520a97SPhilippe Mathieu-Daudé 103ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_dev = tswap16(src->st_dev); 104ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_ino = tswap16(src->st_ino); 105ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_mode = tswap32(src->st_mode); 106ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_nlink = tswap16(src->st_nlink); 107ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_uid = tswap16(src->st_uid); 108ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_gid = tswap16(src->st_gid); 109ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_rdev = tswap16(src->st_rdev); 110ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_size = tswap64(src->st_size); 111ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_atime = tswap64(src->st_atime); 112ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_mtime = tswap64(src->st_mtime); 113ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_ctime = tswap64(src->st_ctime); 114ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32 115ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blksize = 0; 116ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blocks = 0; 117ad520a97SPhilippe Mathieu-Daudé #else 118ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blksize = tswap64(src->st_blksize); 119ad520a97SPhilippe Mathieu-Daudé dst->uhi_st_blocks = tswap64(src->st_blocks); 120ad520a97SPhilippe Mathieu-Daudé #endif 121ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, len); 122ad520a97SPhilippe Mathieu-Daudé return 0; 123ad520a97SPhilippe Mathieu-Daudé } 124ad520a97SPhilippe Mathieu-Daudé 125ad520a97SPhilippe Mathieu-Daudé static int get_open_flags(target_ulong target_flags) 126ad520a97SPhilippe Mathieu-Daudé { 127ad520a97SPhilippe Mathieu-Daudé int open_flags = 0; 128ad520a97SPhilippe Mathieu-Daudé 129ad520a97SPhilippe Mathieu-Daudé if (target_flags & UHIOpen_RDWR) { 130ad520a97SPhilippe Mathieu-Daudé open_flags |= O_RDWR; 131ad520a97SPhilippe Mathieu-Daudé } else if (target_flags & UHIOpen_WRONLY) { 132ad520a97SPhilippe Mathieu-Daudé open_flags |= O_WRONLY; 133ad520a97SPhilippe Mathieu-Daudé } else { 134ad520a97SPhilippe Mathieu-Daudé open_flags |= O_RDONLY; 135ad520a97SPhilippe Mathieu-Daudé } 136ad520a97SPhilippe Mathieu-Daudé 137ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_APPEND) ? O_APPEND : 0; 138ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_CREAT) ? O_CREAT : 0; 139ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_TRUNC) ? O_TRUNC : 0; 140ad520a97SPhilippe Mathieu-Daudé open_flags |= (target_flags & UHIOpen_EXCL) ? O_EXCL : 0; 141ad520a97SPhilippe Mathieu-Daudé 142ad520a97SPhilippe Mathieu-Daudé return open_flags; 143ad520a97SPhilippe Mathieu-Daudé } 144ad520a97SPhilippe Mathieu-Daudé 145ad520a97SPhilippe Mathieu-Daudé static int write_to_file(CPUMIPSState *env, target_ulong fd, target_ulong vaddr, 146ad520a97SPhilippe Mathieu-Daudé target_ulong len, target_ulong offset) 147ad520a97SPhilippe Mathieu-Daudé { 148ad520a97SPhilippe Mathieu-Daudé int num_of_bytes; 149ad520a97SPhilippe Mathieu-Daudé void *dst = lock_user(VERIFY_READ, vaddr, len, 1); 150ad520a97SPhilippe Mathieu-Daudé if (!dst) { 151ad520a97SPhilippe Mathieu-Daudé errno = EFAULT; 152ad520a97SPhilippe Mathieu-Daudé return -1; 153ad520a97SPhilippe Mathieu-Daudé } 154ad520a97SPhilippe Mathieu-Daudé 155ad520a97SPhilippe Mathieu-Daudé if (offset) { 156ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32 157ad520a97SPhilippe Mathieu-Daudé num_of_bytes = 0; 158ad520a97SPhilippe Mathieu-Daudé #else 159ad520a97SPhilippe Mathieu-Daudé num_of_bytes = pwrite(fd, dst, len, offset); 160ad520a97SPhilippe Mathieu-Daudé #endif 161ad520a97SPhilippe Mathieu-Daudé } else { 162ad520a97SPhilippe Mathieu-Daudé num_of_bytes = write(fd, dst, len); 163ad520a97SPhilippe Mathieu-Daudé } 164ad520a97SPhilippe Mathieu-Daudé 165ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, 0); 166ad520a97SPhilippe Mathieu-Daudé return num_of_bytes; 167ad520a97SPhilippe Mathieu-Daudé } 168ad520a97SPhilippe Mathieu-Daudé 169ad520a97SPhilippe Mathieu-Daudé static int read_from_file(CPUMIPSState *env, target_ulong fd, 170ad520a97SPhilippe Mathieu-Daudé target_ulong vaddr, target_ulong len, 171ad520a97SPhilippe Mathieu-Daudé target_ulong offset) 172ad520a97SPhilippe Mathieu-Daudé { 173ad520a97SPhilippe Mathieu-Daudé int num_of_bytes; 174ad520a97SPhilippe Mathieu-Daudé void *dst = lock_user(VERIFY_WRITE, vaddr, len, 0); 175ad520a97SPhilippe Mathieu-Daudé if (!dst) { 176ad520a97SPhilippe Mathieu-Daudé errno = EFAULT; 177ad520a97SPhilippe Mathieu-Daudé return -1; 178ad520a97SPhilippe Mathieu-Daudé } 179ad520a97SPhilippe Mathieu-Daudé 180ad520a97SPhilippe Mathieu-Daudé if (offset) { 181ad520a97SPhilippe Mathieu-Daudé #ifdef _WIN32 182ad520a97SPhilippe Mathieu-Daudé num_of_bytes = 0; 183ad520a97SPhilippe Mathieu-Daudé #else 184ad520a97SPhilippe Mathieu-Daudé num_of_bytes = pread(fd, dst, len, offset); 185ad520a97SPhilippe Mathieu-Daudé #endif 186ad520a97SPhilippe Mathieu-Daudé } else { 187ad520a97SPhilippe Mathieu-Daudé num_of_bytes = read(fd, dst, len); 188ad520a97SPhilippe Mathieu-Daudé } 189ad520a97SPhilippe Mathieu-Daudé 190ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, len); 191ad520a97SPhilippe Mathieu-Daudé return num_of_bytes; 192ad520a97SPhilippe Mathieu-Daudé } 193ad520a97SPhilippe Mathieu-Daudé 194ad520a97SPhilippe Mathieu-Daudé static int copy_argn_to_target(CPUMIPSState *env, int arg_num, 195ad520a97SPhilippe Mathieu-Daudé target_ulong vaddr) 196ad520a97SPhilippe Mathieu-Daudé { 197ad520a97SPhilippe Mathieu-Daudé int strsize = strlen(semihosting_get_arg(arg_num)) + 1; 198ad520a97SPhilippe Mathieu-Daudé char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0); 199ad520a97SPhilippe Mathieu-Daudé if (!dst) { 200ad520a97SPhilippe Mathieu-Daudé return -1; 201ad520a97SPhilippe Mathieu-Daudé } 202ad520a97SPhilippe Mathieu-Daudé 203ad520a97SPhilippe Mathieu-Daudé strcpy(dst, semihosting_get_arg(arg_num)); 204ad520a97SPhilippe Mathieu-Daudé 205ad520a97SPhilippe Mathieu-Daudé unlock_user(dst, vaddr, strsize); 206ad520a97SPhilippe Mathieu-Daudé return 0; 207ad520a97SPhilippe Mathieu-Daudé } 208ad520a97SPhilippe Mathieu-Daudé 209ad520a97SPhilippe Mathieu-Daudé #define GET_TARGET_STRING(p, addr) \ 210ad520a97SPhilippe Mathieu-Daudé do { \ 211ad520a97SPhilippe Mathieu-Daudé p = lock_user_string(addr); \ 212ad520a97SPhilippe Mathieu-Daudé if (!p) { \ 213ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; \ 214ad520a97SPhilippe Mathieu-Daudé gpr[3] = EFAULT; \ 215ad520a97SPhilippe Mathieu-Daudé return; \ 216ad520a97SPhilippe Mathieu-Daudé } \ 217ad520a97SPhilippe Mathieu-Daudé } while (0) 218ad520a97SPhilippe Mathieu-Daudé 219ad520a97SPhilippe Mathieu-Daudé #define GET_TARGET_STRINGS_2(p, addr, p2, addr2) \ 220ad520a97SPhilippe Mathieu-Daudé do { \ 221ad520a97SPhilippe Mathieu-Daudé p = lock_user_string(addr); \ 222ad520a97SPhilippe Mathieu-Daudé if (!p) { \ 223ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; \ 224ad520a97SPhilippe Mathieu-Daudé gpr[3] = EFAULT; \ 225ad520a97SPhilippe Mathieu-Daudé return; \ 226ad520a97SPhilippe Mathieu-Daudé } \ 227ad520a97SPhilippe Mathieu-Daudé p2 = lock_user_string(addr2); \ 228ad520a97SPhilippe Mathieu-Daudé if (!p2) { \ 229ad520a97SPhilippe Mathieu-Daudé unlock_user(p, addr, 0); \ 230ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; \ 231ad520a97SPhilippe Mathieu-Daudé gpr[3] = EFAULT; \ 232ad520a97SPhilippe Mathieu-Daudé return; \ 233ad520a97SPhilippe Mathieu-Daudé } \ 234ad520a97SPhilippe Mathieu-Daudé } while (0) 235ad520a97SPhilippe Mathieu-Daudé 236ad520a97SPhilippe Mathieu-Daudé #define FREE_TARGET_STRING(p, gpr) \ 237ad520a97SPhilippe Mathieu-Daudé do { \ 238ad520a97SPhilippe Mathieu-Daudé unlock_user(p, gpr, 0); \ 239ad520a97SPhilippe Mathieu-Daudé } while (0) 240ad520a97SPhilippe Mathieu-Daudé 2418ec7e3c5SRichard Henderson void mips_semihosting(CPUMIPSState *env) 242ad520a97SPhilippe Mathieu-Daudé { 243ad520a97SPhilippe Mathieu-Daudé target_ulong *gpr = env->active_tc.gpr; 244ad520a97SPhilippe Mathieu-Daudé const UHIOp op = gpr[25]; 245ad520a97SPhilippe Mathieu-Daudé char *p, *p2; 246ad520a97SPhilippe Mathieu-Daudé 247ad520a97SPhilippe Mathieu-Daudé switch (op) { 248ad520a97SPhilippe Mathieu-Daudé case UHI_exit: 249ad520a97SPhilippe Mathieu-Daudé qemu_log("UHI(%d): exit(%d)\n", op, (int)gpr[4]); 250ad520a97SPhilippe Mathieu-Daudé exit(gpr[4]); 251ad520a97SPhilippe Mathieu-Daudé case UHI_open: 252ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRING(p, gpr[4]); 253ad520a97SPhilippe Mathieu-Daudé if (!strcmp("/dev/stdin", p)) { 254ad520a97SPhilippe Mathieu-Daudé gpr[2] = 0; 255ad520a97SPhilippe Mathieu-Daudé } else if (!strcmp("/dev/stdout", p)) { 256ad520a97SPhilippe Mathieu-Daudé gpr[2] = 1; 257ad520a97SPhilippe Mathieu-Daudé } else if (!strcmp("/dev/stderr", p)) { 258ad520a97SPhilippe Mathieu-Daudé gpr[2] = 2; 259ad520a97SPhilippe Mathieu-Daudé } else { 260ad520a97SPhilippe Mathieu-Daudé gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]); 261ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 262ad520a97SPhilippe Mathieu-Daudé } 263ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 264ad520a97SPhilippe Mathieu-Daudé break; 265ad520a97SPhilippe Mathieu-Daudé case UHI_close: 266ad520a97SPhilippe Mathieu-Daudé if (gpr[4] < 3) { 267ad520a97SPhilippe Mathieu-Daudé /* ignore closing stdin/stdout/stderr */ 268ad520a97SPhilippe Mathieu-Daudé gpr[2] = 0; 269ad520a97SPhilippe Mathieu-Daudé return; 270ad520a97SPhilippe Mathieu-Daudé } 271ad520a97SPhilippe Mathieu-Daudé gpr[2] = close(gpr[4]); 272ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 273ad520a97SPhilippe Mathieu-Daudé break; 274ad520a97SPhilippe Mathieu-Daudé case UHI_read: 275ad520a97SPhilippe Mathieu-Daudé gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], 0); 276ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 277ad520a97SPhilippe Mathieu-Daudé break; 278ad520a97SPhilippe Mathieu-Daudé case UHI_write: 279ad520a97SPhilippe Mathieu-Daudé gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], 0); 280ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 281ad520a97SPhilippe Mathieu-Daudé break; 282ad520a97SPhilippe Mathieu-Daudé case UHI_lseek: 283ad520a97SPhilippe Mathieu-Daudé gpr[2] = lseek(gpr[4], gpr[5], gpr[6]); 284ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 285ad520a97SPhilippe Mathieu-Daudé break; 286ad520a97SPhilippe Mathieu-Daudé case UHI_unlink: 287ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRING(p, gpr[4]); 288ad520a97SPhilippe Mathieu-Daudé gpr[2] = remove(p); 289ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 290ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 291ad520a97SPhilippe Mathieu-Daudé break; 292ad520a97SPhilippe Mathieu-Daudé case UHI_fstat: 293ad520a97SPhilippe Mathieu-Daudé { 294ad520a97SPhilippe Mathieu-Daudé struct stat sbuf; 295ad520a97SPhilippe Mathieu-Daudé memset(&sbuf, 0, sizeof(sbuf)); 296ad520a97SPhilippe Mathieu-Daudé gpr[2] = fstat(gpr[4], &sbuf); 297ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 298ad520a97SPhilippe Mathieu-Daudé if (gpr[2]) { 299ad520a97SPhilippe Mathieu-Daudé return; 300ad520a97SPhilippe Mathieu-Daudé } 301ad520a97SPhilippe Mathieu-Daudé gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]); 302ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 303ad520a97SPhilippe Mathieu-Daudé } 304ad520a97SPhilippe Mathieu-Daudé break; 305ad520a97SPhilippe Mathieu-Daudé case UHI_argc: 306ad520a97SPhilippe Mathieu-Daudé gpr[2] = semihosting_get_argc(); 307ad520a97SPhilippe Mathieu-Daudé break; 308ad520a97SPhilippe Mathieu-Daudé case UHI_argnlen: 309ad520a97SPhilippe Mathieu-Daudé if (gpr[4] >= semihosting_get_argc()) { 310ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; 311ad520a97SPhilippe Mathieu-Daudé return; 312ad520a97SPhilippe Mathieu-Daudé } 313ad520a97SPhilippe Mathieu-Daudé gpr[2] = strlen(semihosting_get_arg(gpr[4])); 314ad520a97SPhilippe Mathieu-Daudé break; 315ad520a97SPhilippe Mathieu-Daudé case UHI_argn: 316ad520a97SPhilippe Mathieu-Daudé if (gpr[4] >= semihosting_get_argc()) { 317ad520a97SPhilippe Mathieu-Daudé gpr[2] = -1; 318ad520a97SPhilippe Mathieu-Daudé return; 319ad520a97SPhilippe Mathieu-Daudé } 320ad520a97SPhilippe Mathieu-Daudé gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]); 321ad520a97SPhilippe Mathieu-Daudé break; 322ad520a97SPhilippe Mathieu-Daudé case UHI_plog: 323ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRING(p, gpr[4]); 324ad520a97SPhilippe Mathieu-Daudé p2 = strstr(p, "%d"); 325ad520a97SPhilippe Mathieu-Daudé if (p2) { 326ad520a97SPhilippe Mathieu-Daudé int char_num = p2 - p; 327ad520a97SPhilippe Mathieu-Daudé GString *s = g_string_new_len(p, char_num); 328ad520a97SPhilippe Mathieu-Daudé g_string_append_printf(s, "%d%s", (int)gpr[5], p2 + 2); 329ad520a97SPhilippe Mathieu-Daudé gpr[2] = qemu_semihosting_log_out(s->str, s->len); 330ad520a97SPhilippe Mathieu-Daudé g_string_free(s, true); 331ad520a97SPhilippe Mathieu-Daudé } else { 332ad520a97SPhilippe Mathieu-Daudé gpr[2] = qemu_semihosting_log_out(p, strlen(p)); 333ad520a97SPhilippe Mathieu-Daudé } 334ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 335ad520a97SPhilippe Mathieu-Daudé break; 336ad520a97SPhilippe Mathieu-Daudé case UHI_assert: 337ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); 338ad520a97SPhilippe Mathieu-Daudé printf("assertion '"); 339ad520a97SPhilippe Mathieu-Daudé printf("\"%s\"", p); 340ad520a97SPhilippe Mathieu-Daudé printf("': file \"%s\", line %d\n", p2, (int)gpr[6]); 341ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p2, gpr[5]); 342ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 343ad520a97SPhilippe Mathieu-Daudé abort(); 344ad520a97SPhilippe Mathieu-Daudé break; 345ad520a97SPhilippe Mathieu-Daudé case UHI_pread: 346ad520a97SPhilippe Mathieu-Daudé gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], gpr[7]); 347ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 348ad520a97SPhilippe Mathieu-Daudé break; 349ad520a97SPhilippe Mathieu-Daudé case UHI_pwrite: 350ad520a97SPhilippe Mathieu-Daudé gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], gpr[7]); 351ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 352ad520a97SPhilippe Mathieu-Daudé break; 353ad520a97SPhilippe Mathieu-Daudé #ifndef _WIN32 354ad520a97SPhilippe Mathieu-Daudé case UHI_link: 355ad520a97SPhilippe Mathieu-Daudé GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); 356ad520a97SPhilippe Mathieu-Daudé gpr[2] = link(p, p2); 357ad520a97SPhilippe Mathieu-Daudé gpr[3] = errno_mips(errno); 358ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p2, gpr[5]); 359ad520a97SPhilippe Mathieu-Daudé FREE_TARGET_STRING(p, gpr[4]); 360ad520a97SPhilippe Mathieu-Daudé break; 361ad520a97SPhilippe Mathieu-Daudé #endif 362ad520a97SPhilippe Mathieu-Daudé default: 363ad520a97SPhilippe Mathieu-Daudé fprintf(stderr, "Unknown UHI operation %d\n", op); 364ad520a97SPhilippe Mathieu-Daudé abort(); 365ad520a97SPhilippe Mathieu-Daudé } 366ad520a97SPhilippe Mathieu-Daudé return; 367ad520a97SPhilippe Mathieu-Daudé } 368