|
|
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: ! 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 *)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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.