1 #include <syscall.h>
2 #include <stdio.h>
3 #include <errno.h>
4 #include <sys/stat.h>
5 
6 #include "fileio.h"
7 
8 #define SYS_ftruncate 3000
9 #define SYS_isatty 3001
10 
11 /* Set to 1 if we are running on hardware. The config instruction is
12  * always emulated on the simulator. The emulation code pokes this
13  * variable to 1.
14  */
15 extern int _hardware;
16 
17 /* _cpu_config==0 => Abel
18  * _cpu_config==1 => Zeta
19  * _cpu_config==2 => Phi
20  */
21 extern int _cpu_config;
22 
23 int _use_syscall;
24 
25 
26 extern int _syscall(int *foo, int ID, ...);
27 
28 extern int main(int argc, char **argv);
29 
30 static char *args[]={"dummy.exe"};
31 
32 extern void _init(void);
33 void _initIO(void);
34 
_premain()35 void __attribute__ ((weak)) _premain()
36 {
37 	int t;
38 	/* we only use syscalls w/Zeta */
39 	_use_syscall=(_cpu_config==1);
40 	_initIO();
41 
42 	_init();
43 	t=main(1, args);
44 	exit(t);
45 	for (;;);
46 }
47 
48 
49 /* NOTE!!!! compiled with -fomit-frame-pointer to make sure that 'status' has the
50  * correct value when breakpointing at _exit
51  */
_exit(int status)52 void __attribute__ ((weak)) _exit (int status)
53 {
54 	/* end of the universe, cause memory fault */
55 	__asm("breakpoint");
56 	for (;;);
57 }
58 
_zpu_interrupt(void)59 void __attribute__ ((weak)) _zpu_interrupt(void)
60 {
61 	/* not implemented in libgloss */
62 	__asm("breakpoint");
63 	for (;;);
64 }
65 
66 
67 int __attribute__ ((weak))
68 _DEFUN (write, (fd, buf, nbytes),
69        int fd _AND
70        char *buf _AND
71        int nbytes)
72 {
73 	if (_use_syscall)
74 	{
75 		int t;
76 		int result;
77 		result=_syscall(&t, SYS_write, fd, buf, nbytes);
78 		errno=t;
79 		return result;
80 	} else
81 	{
82 	  int i;
83 
84 	  for (i = 0; i < nbytes; i++) {
85 	    if (*(buf + i) == '\n') {
86 	      outbyte ('\r');
87 	    }
88 	    outbyte (*(buf + i));
89 	  }
90 	  return (nbytes);
91 	}
92 }
93 
94 
95 /*
96  * read  -- read bytes from the serial port. Ignore fd, since
97  *          we only have stdin.
98  */
99 int __attribute__ ((weak))
100 _DEFUN (read, (fd, buf, nbytes),
101        int fd _AND
102        char *buf _AND
103        int nbytes)
104 {
105 	if (_use_syscall)
106 	{
107 		int t;
108 		int result;
109 		result=_syscall(&t, SYS_read, fd, buf, nbytes);
110 		errno=t;
111 		return result;
112 	} else
113 	{
114 	  int i = 0;
115 
116 	  for (i = 0; i < nbytes; i++) {
117 		char t=inbyte();
118 
119 		if ((t!='\r')&&(t!='\n'))
120 		{
121 		    *(buf + i) = t;
122 		    outbyte(t); // echo
123 		} else
124 		{
125 	    	// terminate the line in the way expected by the libraries
126 		    *(buf + i) = '\n';
127 	    	i++;
128 		    outbyte('\r');
129 		    outbyte('\n');
130 	      break;
131 	    }
132 	  }
133 	  return (i);
134 	}
135 }
136 
137 
138 
139 /*
140  * open -- open a file descriptor. We don't have a filesystem, so
141  *         we return an error.
142  */
open(const char * buf,int flags,int mode,...)143 int __attribute__ ((weak)) open(const char *buf,
144        int flags,
145        int mode,
146        ...)
147 {
148 	if (_use_syscall)
149 	{
150 		int t;
151 		int result;
152 		result=_syscall(&t, SYS_open, buf, strlen(buf)+1, flags, mode);
153 		errno=t;
154 		return result;
155 	} else
156 	{
157 	  errno = EIO;
158 	  return (-1);
159 	}
160 }
161 
162 
163 
164 /*
165  * close -- We don't need to do anything, but pretend we did.
166  */
167 int __attribute__ ((weak))
168 _DEFUN (close ,(fd),
169        int fd)
170 {
171 	if (_use_syscall)
172 	{
173 		int t;
174 		int result;
175 		result=_syscall(&t, SYS_close, fd);
176 		errno=t;
177 		return result;
178 	} else
179 	{
180 	  return (0);
181 	}
182 }
183 
184 
185 
186 
187 int __attribute__ ((weak))
ftruncate(int file,off_t length)188 ftruncate (int file, off_t length)
189 {
190 	/*
191 	if (_use_syscall)
192 	{
193 		int t;
194 		int result;
195 		result=_syscall(&t, SYS_ftruncate, file, length);
196 		errno=t;
197 		return result;
198 	} else
199 	*/
200 	{
201 	  return -1;
202 	}
203 }
204 
205 
206 /*
207  * unlink -- since we have no file system,
208  *           we just return an error.
209  */
210 int __attribute__ ((weak))
211 _DEFUN (unlink, (path),
212         char * path)
213 {
214 	if (_use_syscall)
215 	{
216 		int t;
217 		int result;
218 		result=_syscall(&t, SYS_unlink, path, strlen(path)+1);
219 		errno=t;
220 		return result;
221 	} else
222 	{
223 	  errno = EIO;
224 	  return (-1);
225 	}
226 }
227 
228 
229 /*
230  * lseek --  Since a serial port is non-seekable, we return an error.
231  */
232 off_t __attribute__ ((weak))
233 _DEFUN (lseek, (fd,  offset, whence),
234        int fd _AND
235        off_t offset _AND
236        int whence)
237 {
238 	if (_use_syscall)
239 	{
240 		int t;
241 		int result;
242 		result=_syscall(&t, SYS_lseek, fd, offset, whence);
243 		errno=t;
244 		return result;
245 	} else
246 	{
247 	  errno = ESPIPE;
248 	  return ((off_t)-1);
249 	}
250 }
251 
252 /* we convert from bigendian to smallendian*/
conv(char * a,int len)253 static long conv(char *a, int len)
254 {
255 	long t=0;
256 	int i;
257 	for (i=0; i<len; i++)
258 	{
259 		t|=(((int)a[i])&0xff)<<((len-1-i)*8);
260 	}
261 	return t;
262 }
263 
convert(struct fio_stat * gdb_stat,struct stat * buf)264 static void convert(struct fio_stat *gdb_stat, struct stat *buf)
265 {
266 	memset(buf, 0, sizeof(*buf));
267 	buf->st_dev=conv(gdb_stat->fst_dev, sizeof(gdb_stat->fst_dev));
268 	buf->st_ino=conv(gdb_stat->fst_ino, sizeof(gdb_stat->fst_ino));
269 	buf->st_mode=conv(gdb_stat->fst_mode, sizeof(gdb_stat->fst_mode));
270 	buf->st_nlink=conv(gdb_stat->fst_nlink, sizeof(gdb_stat->fst_nlink));
271 	buf->st_uid=conv(gdb_stat->fst_uid, sizeof(gdb_stat->fst_uid));
272 	buf->st_gid=conv(gdb_stat->fst_gid, sizeof(gdb_stat->fst_gid));
273 	buf->st_rdev=conv(gdb_stat->fst_rdev, sizeof(gdb_stat->fst_rdev));
274 	buf->st_size=conv(gdb_stat->fst_size, sizeof(gdb_stat->fst_size));
275 #if 0
276 	conv_64(fio_ulong_t,  &gdb_stat->fst_blksize);
277 	conv_64(fio_ulong_t,  &gdb_stat->fst_blocks);
278 #endif
279 #if 0
280     conv_time(fst_atime;
281 	conv_time(fst_mtime;
282 	conv_time(fst_ctime;
283 #endif
284 }
285 
286 int __attribute__ ((weak))
287 _DEFUN (fstat, (fd, buf),
288        int fd _AND
289        struct stat *buf)
290 {
291 	if (_use_syscall)
292 	{
293 		int t;
294 		int result;
295 		struct fio_stat gdb_stat;
296 		result=_syscall(&t, SYS_fstat, fd, &gdb_stat);
297 		convert(&gdb_stat, buf);
298 		errno=t;
299 		return result;
300 	} else
301 	{
302 /*
303  * fstat -- Since we have no file system, we just return an error.
304  */
305 	  buf->st_mode = S_IFCHR;	/* Always pretend to be a tty */
306 	  buf->st_blksize = 0;
307 
308 	  return (0);
309 	}
310 }
311 
312 
313 int __attribute__ ((weak))
314 _DEFUN (stat, (path, buf),
315        const char *path _AND
316        struct stat *buf)
317 {
318 	if (_use_syscall)
319 	{
320 		int t;
321 		int result;
322 		struct fio_stat gdb_stat;
323 		result=_syscall(&t, SYS_stat, path, strlen(path)+1, &gdb_stat);
324 		convert(&gdb_stat, buf);
325 		errno=t;
326 		return result;
327 	} else
328 	{
329 	  errno = EIO;
330 	  return (-1);
331 	}
332 }
333 
334 
335 
336 int __attribute__ ((weak))
337 _DEFUN (isatty, (fd),
338        int fd)
339 {
340 	if (_use_syscall)
341 	{
342 		int t;
343 		int result;
344 		result=_syscall(&t, SYS_isatty, fd);
345 		errno=t;
346 		return result;
347 	} else
348 	{
349 		/*
350 		 * isatty -- returns 1 if connected to a terminal device,
351 		 *           returns 0 if not. Since we're hooked up to a
352 		 *           serial port, we'll say yes _AND return a 1.
353 		 */
354 	  return (1);
355 	}
356 }
357