xref: /qemu/target/mips/tcg/sysemu/mips-semi.c (revision 7ba6e53a)
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