Statistics
| Branch: | Revision:

root / linux-user / arm-semi.c @ 04d81be8

History | View | Annotate | Download (5.7 kB)

1
/*
2
 *  Arm "Angel" semihosting syscalls
3
 * 
4
 *  Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook.
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20

    
21
#include <sys/types.h>
22
#include <sys/stat.h>
23
#include <fcntl.h>
24
#include <unistd.h>
25
#include <stdlib.h>
26
#include <stdio.h>
27
#include <time.h>
28

    
29
#include "qemu.h"
30

    
31
#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
32

    
33
#define SYS_OPEN        0x01
34
#define SYS_CLOSE       0x02
35
#define SYS_WRITEC      0x03
36
#define SYS_WRITE0      0x04
37
#define SYS_WRITE       0x05
38
#define SYS_READ        0x06
39
#define SYS_READC       0x07
40
#define SYS_ISTTY       0x09
41
#define SYS_SEEK        0x0a
42
#define SYS_FLEN        0x0c
43
#define SYS_TMPNAM      0x0d
44
#define SYS_REMOVE      0x0e
45
#define SYS_RENAME      0x0f
46
#define SYS_CLOCK       0x10
47
#define SYS_TIME        0x11
48
#define SYS_SYSTEM      0x12
49
#define SYS_ERRNO       0x13
50
#define SYS_GET_CMDLINE 0x15
51
#define SYS_HEAPINFO    0x16
52
#define SYS_EXIT        0x18
53

    
54
#ifndef O_BINARY
55
#define O_BINARY 0
56
#endif
57

    
58
int open_modeflags[12] = {
59
    O_RDONLY,
60
    O_RDONLY | O_BINARY,
61
    O_RDWR,
62
    O_RDWR | O_BINARY,
63
    O_WRONLY | O_CREAT | O_TRUNC,
64
    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
65
    O_RDWR | O_CREAT | O_TRUNC,
66
    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
67
    O_WRONLY | O_CREAT | O_APPEND,
68
    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
69
    O_RDWR | O_CREAT | O_APPEND,
70
    O_RDWR | O_CREAT | O_APPEND | O_BINARY
71
};
72

    
73
static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
74
{
75
  if (code == (uint32_t)-1)
76
      ts->swi_errno = errno;
77
  return code;
78
}
79

    
80
#define ARG(x) tswap32(args[x])
81
uint32_t do_arm_semihosting(CPUState *env)
82
{
83
    uint32_t *args;
84
    char * s;
85
    int nr;
86
    uint32_t ret;
87
    TaskState *ts = env->opaque;
88

    
89
    nr = env->regs[0];
90
    args = (uint32_t *)env->regs[1];
91
    switch (nr) {
92
    case SYS_OPEN:
93
        s = (char *)ARG(0);
94
        if (ARG(1) >= 12)
95
          return (uint32_t)-1;
96
        if (strcmp(s, ":tt") == 0) {
97
            if (ARG(1) < 4)
98
                return STDIN_FILENO;
99
            else
100
                return STDOUT_FILENO;
101
        }
102
        return set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
103
    case SYS_CLOSE:
104
        return set_swi_errno(ts, close(ARG(0)));
105
    case SYS_WRITEC:
106
        /* Write to debug console.  stderr is near enough.  */
107
        return write(STDERR_FILENO, args, 1);
108
    case SYS_WRITE0:
109
        s = (char *)args;
110
        return write(STDERR_FILENO, s, strlen(s));
111
    case SYS_WRITE:
112
        ret = set_swi_errno(ts, write(ARG(0), (void *)ARG(1), ARG(2)));
113
        if (ret == (uint32_t)-1)
114
            return -1;
115
        return ARG(2) - ret;
116
    case SYS_READ:
117
        ret = set_swi_errno(ts, read(ARG(0), (void *)ARG(1), ARG(2)));
118
        if (ret == (uint32_t)-1)
119
            return -1;
120
        return ARG(2) - ret;
121
    case SYS_READC:
122
       /* XXX: Read from debug cosole. Not implemented.  */
123
        return 0;
124
    case SYS_ISTTY:
125
        return isatty(ARG(0));
126
    case SYS_SEEK:
127
        ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
128
        if (ret == (uint32_t)-1)
129
          return -1;
130
        return 0;
131
    case SYS_FLEN:
132
        {
133
            struct stat buf;
134
            ret = set_swi_errno(ts, fstat(ARG(0), &buf));
135
            if (ret == (uint32_t)-1)
136
                return -1;
137
            return buf.st_size;
138
        }
139
    case SYS_TMPNAM:
140
        /* XXX: Not implemented.  */
141
        return -1;
142
    case SYS_REMOVE:
143
        return set_swi_errno(ts, remove((char *)ARG(0)));
144
    case SYS_RENAME:
145
        return set_swi_errno(ts, rename((char *)ARG(0), (char *)ARG(2)));
146
    case SYS_CLOCK:
147
        return clock() / (CLOCKS_PER_SEC / 100);
148
    case SYS_TIME:
149
        return set_swi_errno(ts, time(NULL));
150
    case SYS_SYSTEM:
151
        return set_swi_errno(ts, system((char *)ARG(0)));
152
    case SYS_ERRNO:
153
        return ts->swi_errno;
154
    case SYS_GET_CMDLINE:
155
        /* XXX: Not implemented.  */
156
        s = (char *)ARG(0);
157
        *s = 0;
158
        return -1;
159
    case SYS_HEAPINFO:
160
        {
161
            uint32_t *ptr;
162
            uint32_t limit;
163

    
164
            /* Some C llibraries assume the heap immediately follows .bss, so
165
               allocate it using sbrk.  */
166
            if (!ts->heap_limit) {
167
                long ret;
168

    
169
                ts->heap_base = do_brk(NULL);
170
                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
171
                /* Try a big heap, and reduce the size if that fails.  */
172
                for (;;) {
173
                    ret = do_brk((char *)limit);
174
                    if (ret != -1)
175
                        break;
176
                    limit = (ts->heap_base >> 1) + (limit >> 1);
177
                }
178
                ts->heap_limit = limit;
179
            }
180
              
181
            ptr = (uint32_t *)tswap32(ARG(0));
182
            ptr[0] = tswap32(ts->heap_base);
183
            ptr[1] = tswap32(ts->heap_limit);
184
            ptr[2] = tswap32(ts->stack_base);
185
            ptr[3] = tswap32(0); /* Stack limit.  */
186
            return 0;
187
        }
188
    case SYS_EXIT:
189
        exit(0);
190
    default:
191
        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
192
        cpu_dump_state(env, stderr, fprintf, 0);
193
        abort();
194
    }
195
}
196