1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "cpu.h"
15#include "exec/helper-proto.h"
16#include "qemu/log.h"
17#include "exec/softmmu-semi.h"
18
19enum {
20 TARGET_SYS_exit = 1,
21 TARGET_SYS_open = 2,
22 TARGET_SYS_close = 3,
23 TARGET_SYS_read = 4,
24 TARGET_SYS_write = 5,
25 TARGET_SYS_lseek = 6,
26 TARGET_SYS_fstat = 10,
27 TARGET_SYS_stat = 15,
28};
29
30enum {
31 NEWLIB_O_RDONLY = 0x0,
32 NEWLIB_O_WRONLY = 0x1,
33 NEWLIB_O_RDWR = 0x2,
34 NEWLIB_O_APPEND = 0x8,
35 NEWLIB_O_CREAT = 0x200,
36 NEWLIB_O_TRUNC = 0x400,
37 NEWLIB_O_EXCL = 0x800,
38};
39
40static int translate_openflags(int flags)
41{
42 int hf;
43
44 if (flags & NEWLIB_O_WRONLY) {
45 hf = O_WRONLY;
46 } else if (flags & NEWLIB_O_RDWR) {
47 hf = O_RDWR;
48 } else {
49 hf = O_RDONLY;
50 }
51
52 if (flags & NEWLIB_O_APPEND) {
53 hf |= O_APPEND;
54 }
55
56 if (flags & NEWLIB_O_CREAT) {
57 hf |= O_CREAT;
58 }
59
60 if (flags & NEWLIB_O_TRUNC) {
61 hf |= O_TRUNC;
62 }
63
64 if (flags & NEWLIB_O_EXCL) {
65 hf |= O_EXCL;
66 }
67
68 return hf;
69}
70
71struct newlib_stat {
72 int16_t newlib_st_dev;
73 uint16_t newlib_st_ino;
74 uint16_t newlib_st_mode;
75 uint16_t newlib_st_nlink;
76 uint16_t newlib_st_uid;
77 uint16_t newlib_st_gid;
78 int16_t newlib_st_rdev;
79 int32_t newlib_st_size;
80 int32_t newlib_st_atime;
81 uint32_t newlib_st_spare1;
82 int32_t newlib_st_mtime;
83 uint32_t newlib_st_spare2;
84 int32_t newlib_st_ctime;
85 uint32_t newlib_st_spare3;
86} QEMU_PACKED;
87
88static int translate_stat(CPULM32State *env, target_ulong addr,
89 struct stat *s)
90{
91 struct newlib_stat *p;
92
93 p = lock_user(VERIFY_WRITE, addr, sizeof(struct newlib_stat), 0);
94 if (!p) {
95 return 0;
96 }
97 p->newlib_st_dev = cpu_to_be16(s->st_dev);
98 p->newlib_st_ino = cpu_to_be16(s->st_ino);
99 p->newlib_st_mode = cpu_to_be16(s->st_mode);
100 p->newlib_st_nlink = cpu_to_be16(s->st_nlink);
101 p->newlib_st_uid = cpu_to_be16(s->st_uid);
102 p->newlib_st_gid = cpu_to_be16(s->st_gid);
103 p->newlib_st_rdev = cpu_to_be16(s->st_rdev);
104 p->newlib_st_size = cpu_to_be32(s->st_size);
105 p->newlib_st_atime = cpu_to_be32(s->st_atime);
106 p->newlib_st_mtime = cpu_to_be32(s->st_mtime);
107 p->newlib_st_ctime = cpu_to_be32(s->st_ctime);
108 unlock_user(p, addr, sizeof(struct newlib_stat));
109
110 return 1;
111}
112
113bool lm32_cpu_do_semihosting(CPUState *cs)
114{
115 LM32CPU *cpu = LM32_CPU(cs);
116 CPULM32State *env = &cpu->env;
117
118 int ret = -1;
119 target_ulong nr, arg0, arg1, arg2;
120 void *p;
121 struct stat s;
122
123 nr = env->regs[R_R8];
124 arg0 = env->regs[R_R1];
125 arg1 = env->regs[R_R2];
126 arg2 = env->regs[R_R3];
127
128 switch (nr) {
129 case TARGET_SYS_exit:
130
131 exit(arg0);
132
133 case TARGET_SYS_open:
134
135 p = lock_user_string(arg0);
136 if (!p) {
137 ret = -1;
138 } else {
139 ret = open(p, translate_openflags(arg2));
140 unlock_user(p, arg0, 0);
141 }
142 break;
143
144 case TARGET_SYS_read:
145
146 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
147 if (!p) {
148 ret = -1;
149 } else {
150 ret = read(arg0, p, arg2);
151 unlock_user(p, arg1, arg2);
152 }
153 break;
154
155 case TARGET_SYS_write:
156
157 p = lock_user(VERIFY_READ, arg1, arg2, 1);
158 if (!p) {
159 ret = -1;
160 } else {
161 ret = write(arg0, p, arg2);
162 unlock_user(p, arg1, 0);
163 }
164 break;
165
166 case TARGET_SYS_close:
167
168
169 if (arg0 > 2) {
170 ret = close(arg0);
171 } else {
172 ret = 0;
173 }
174 break;
175
176 case TARGET_SYS_lseek:
177
178 ret = lseek(arg0, arg1, arg2);
179 break;
180
181 case TARGET_SYS_stat:
182
183 p = lock_user_string(arg0);
184 if (!p) {
185 ret = -1;
186 } else {
187 ret = stat(p, &s);
188 unlock_user(p, arg0, 0);
189 if (translate_stat(env, arg1, &s) == 0) {
190 ret = -1;
191 }
192 }
193 break;
194
195 case TARGET_SYS_fstat:
196
197 ret = fstat(arg0, &s);
198 if (ret == 0) {
199 if (translate_stat(env, arg1, &s) == 0) {
200 ret = -1;
201 }
202 }
203 break;
204
205 default:
206
207 return false;
208 }
209
210 env->regs[R_R1] = ret;
211 return true;
212}
213