Annotation of qemu/linux-user/arm-semi.c, revision 1.1.1.2

1.1       root        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: 
1.1.1.2 ! root       80: #define ARG(n) tget32(args + n * 4)
1.1       root       81: uint32_t do_arm_semihosting(CPUState *env)
                     82: {
1.1.1.2 ! root       83:     target_ulong args;
1.1       root       84:     char * s;
                     85:     int nr;
                     86:     uint32_t ret;
                     87:     TaskState *ts = env->opaque;
                     88: 
                     89:     nr = env->regs[0];
1.1.1.2 ! root       90:     args = env->regs[1];
1.1       root       91:     switch (nr) {
                     92:     case SYS_OPEN:
1.1.1.2 ! root       93:         s = (char *)g2h(ARG(0));
1.1       root       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:
1.1.1.2 ! root      106:         {
        !           107:           char c = tget8(args);
        !           108:           /* Write to debug console.  stderr is near enough.  */
        !           109:           return write(STDERR_FILENO, &c, 1);
        !           110:         }
1.1       root      111:     case SYS_WRITE0:
1.1.1.2 ! root      112:         s = lock_user_string(args);
        !           113:         ret = write(STDERR_FILENO, s, strlen(s));
        !           114:         unlock_user(s, args, 0);
        !           115:         return ret;
1.1       root      116:     case SYS_WRITE:
1.1.1.2 ! root      117:         ret = set_swi_errno(ts, write(ARG(0), g2h(ARG(1)), ARG(2)));
1.1       root      118:         if (ret == (uint32_t)-1)
                    119:             return -1;
                    120:         return ARG(2) - ret;
                    121:     case SYS_READ:
1.1.1.2 ! root      122:         ret = set_swi_errno(ts, read(ARG(0), g2h(ARG(1)), ARG(2)));
1.1       root      123:         if (ret == (uint32_t)-1)
                    124:             return -1;
                    125:         return ARG(2) - ret;
                    126:     case SYS_READC:
                    127:        /* XXX: Read from debug cosole. Not implemented.  */
                    128:         return 0;
                    129:     case SYS_ISTTY:
                    130:         return isatty(ARG(0));
                    131:     case SYS_SEEK:
                    132:         ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
                    133:        if (ret == (uint32_t)-1)
                    134:          return -1;
                    135:        return 0;
                    136:     case SYS_FLEN:
                    137:         {
                    138:             struct stat buf;
                    139:             ret = set_swi_errno(ts, fstat(ARG(0), &buf));
                    140:             if (ret == (uint32_t)-1)
                    141:                 return -1;
                    142:             return buf.st_size;
                    143:         }
                    144:     case SYS_TMPNAM:
                    145:         /* XXX: Not implemented.  */
                    146:         return -1;
                    147:     case SYS_REMOVE:
1.1.1.2 ! root      148:         return set_swi_errno(ts, remove((char *)g2h(ARG(0))));
1.1       root      149:     case SYS_RENAME:
1.1.1.2 ! root      150:         return set_swi_errno(ts, rename((char *)g2h(ARG(0)),
        !           151:                              (char *)g2h(ARG(2))));
1.1       root      152:     case SYS_CLOCK:
                    153:         return clock() / (CLOCKS_PER_SEC / 100);
                    154:     case SYS_TIME:
                    155:         return set_swi_errno(ts, time(NULL));
                    156:     case SYS_SYSTEM:
1.1.1.2 ! root      157:         return set_swi_errno(ts, system((char *)g2h(ARG(0))));
1.1       root      158:     case SYS_ERRNO:
                    159:         return ts->swi_errno;
                    160:     case SYS_GET_CMDLINE:
                    161:         /* XXX: Not implemented.  */
1.1.1.2 ! root      162:         s = (char *)g2h(ARG(0));
1.1       root      163:         *s = 0;
                    164:         return -1;
                    165:     case SYS_HEAPINFO:
                    166:         {
                    167:             uint32_t *ptr;
                    168:             uint32_t limit;
                    169: 
                    170:             /* Some C llibraries assume the heap immediately follows .bss, so
                    171:                allocate it using sbrk.  */
                    172:             if (!ts->heap_limit) {
                    173:                 long ret;
                    174: 
1.1.1.2 ! root      175:                 ts->heap_base = do_brk(0);
1.1       root      176:                 limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
                    177:                 /* Try a big heap, and reduce the size if that fails.  */
                    178:                 for (;;) {
1.1.1.2 ! root      179:                     ret = do_brk(limit);
1.1       root      180:                     if (ret != -1)
                    181:                         break;
                    182:                     limit = (ts->heap_base >> 1) + (limit >> 1);
                    183:                 }
                    184:                 ts->heap_limit = limit;
                    185:             }
                    186:               
1.1.1.2 ! root      187:             page_unprotect_range (ARG(0), 32);
        !           188:             ptr = (uint32_t *)g2h(ARG(0));
1.1       root      189:             ptr[0] = tswap32(ts->heap_base);
                    190:             ptr[1] = tswap32(ts->heap_limit);
                    191:             ptr[2] = tswap32(ts->stack_base);
                    192:             ptr[3] = tswap32(0); /* Stack limit.  */
                    193:             return 0;
                    194:         }
                    195:     case SYS_EXIT:
                    196:         exit(0);
                    197:     default:
                    198:         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
                    199:         cpu_dump_state(env, stderr, fprintf, 0);
                    200:         abort();
                    201:     }
                    202: }
                    203: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.