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