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