|
|
1.1 ! root 1: /* ! 2: * m68k/ColdFire Semihosting ssycall interface ! 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 <errno.h> ! 24: #include <fcntl.h> ! 25: #include <unistd.h> ! 26: #include <stdlib.h> ! 27: #include <stdio.h> ! 28: #include <sys/time.h> ! 29: #include <time.h> ! 30: ! 31: #include "qemu.h" ! 32: ! 33: #define HOSTED_EXIT 0 ! 34: #define HOSTED_PUTCHAR 1 /* Obsolete */ ! 35: #define HOSTED_OPEN 2 ! 36: #define HOSTED_CLOSE 3 ! 37: #define HOSTED_READ 4 ! 38: #define HOSTED_WRITE 5 ! 39: #define HOSTED_LSEEK 6 ! 40: #define HOSTED_RENAME 7 ! 41: #define HOSTED_UNLINK 8 ! 42: #define HOSTED_STAT 9 ! 43: #define HOSTED_FSTAT 10 ! 44: #define HOSTED_GETTIMEOFDAY 11 ! 45: #define HOSTED_ISATTY 12 ! 46: #define HOSTED_SYSTEM 13 ! 47: ! 48: typedef uint32_t gdb_mode_t; ! 49: typedef uint32_t gdb_time_t; ! 50: ! 51: struct m68k_gdb_stat { ! 52: uint32_t gdb_st_dev; /* device */ ! 53: uint32_t gdb_st_ino; /* inode */ ! 54: gdb_mode_t gdb_st_mode; /* protection */ ! 55: uint32_t gdb_st_nlink; /* number of hard links */ ! 56: uint32_t gdb_st_uid; /* user ID of owner */ ! 57: uint32_t gdb_st_gid; /* group ID of owner */ ! 58: uint32_t gdb_st_rdev; /* device type (if inode device) */ ! 59: uint64_t gdb_st_size; /* total size, in bytes */ ! 60: uint64_t gdb_st_blksize; /* blocksize for filesystem I/O */ ! 61: uint64_t gdb_st_blocks; /* number of blocks allocated */ ! 62: gdb_time_t gdb_st_atime; /* time of last access */ ! 63: gdb_time_t gdb_st_mtime; /* time of last modification */ ! 64: gdb_time_t gdb_st_ctime; /* time of last change */ ! 65: }; ! 66: ! 67: struct gdb_timeval { ! 68: gdb_time_t tv_sec; /* second */ ! 69: uint64_t tv_usec; /* microsecond */ ! 70: }; ! 71: ! 72: #define GDB_O_RDONLY 0x0 ! 73: #define GDB_O_WRONLY 0x1 ! 74: #define GDB_O_RDWR 0x2 ! 75: #define GDB_O_APPEND 0x8 ! 76: #define GDB_O_CREAT 0x200 ! 77: #define GDB_O_TRUNC 0x400 ! 78: #define GDB_O_EXCL 0x800 ! 79: ! 80: static int translate_openflags(int flags) ! 81: { ! 82: int hf; ! 83: ! 84: if (flags & GDB_O_WRONLY) ! 85: hf = O_WRONLY; ! 86: else if (flags & GDB_O_RDWR) ! 87: hf = O_RDWR; ! 88: else ! 89: hf = O_RDONLY; ! 90: ! 91: if (flags & GDB_O_APPEND) hf |= O_APPEND; ! 92: if (flags & GDB_O_CREAT) hf |= O_CREAT; ! 93: if (flags & GDB_O_TRUNC) hf |= O_TRUNC; ! 94: if (flags & GDB_O_EXCL) hf |= O_EXCL; ! 95: ! 96: return hf; ! 97: } ! 98: ! 99: static void translate_stat(struct m68k_gdb_stat *p, struct stat *s) ! 100: { ! 101: p->gdb_st_dev = tswap16(s->st_dev); ! 102: p->gdb_st_ino = tswap16(s->st_ino); ! 103: p->gdb_st_mode = tswap32(s->st_mode); ! 104: p->gdb_st_nlink = tswap16(s->st_nlink); ! 105: p->gdb_st_uid = tswap16(s->st_uid); ! 106: p->gdb_st_gid = tswap16(s->st_gid); ! 107: p->gdb_st_rdev = tswap16(s->st_rdev); ! 108: p->gdb_st_size = tswap32(s->st_size); ! 109: p->gdb_st_atime = tswap32(s->st_atime); ! 110: p->gdb_st_mtime = tswap32(s->st_mtime); ! 111: p->gdb_st_ctime = tswap32(s->st_ctime); ! 112: p->gdb_st_blksize = tswap32(s->st_blksize); ! 113: p->gdb_st_blocks = tswap32(s->st_blocks); ! 114: } ! 115: ! 116: static inline uint32_t check_err(CPUM68KState *env, uint32_t code) ! 117: { ! 118: if (code == (uint32_t)-1) { ! 119: env->sr |= CCF_C; ! 120: } else { ! 121: env->sr &= ~CCF_C; ! 122: env->dregs[0] = code; ! 123: } ! 124: return code; ! 125: } ! 126: ! 127: #define ARG(x) tswap32(args[x]) ! 128: void do_m68k_semihosting(CPUM68KState *env, int nr) ! 129: { ! 130: uint32_t *args; ! 131: ! 132: args = (uint32_t *)env->dregs[1]; ! 133: switch (nr) { ! 134: case HOSTED_EXIT: ! 135: exit(env->dregs[0]); ! 136: case HOSTED_OPEN: ! 137: /* Assume name is NULL terminated. */ ! 138: check_err(env, open((char *)ARG(0), translate_openflags(ARG(2)), ! 139: ARG(3))); ! 140: break; ! 141: case HOSTED_CLOSE: ! 142: { ! 143: /* Ignore attempts to close stdin/out/err. */ ! 144: int fd = ARG(0); ! 145: if (fd > 2) ! 146: check_err(env, close(fd)); ! 147: else ! 148: check_err(env, 0); ! 149: break; ! 150: } ! 151: case HOSTED_READ: ! 152: check_err(env, read(ARG(0), (void *)ARG(1), ARG(2))); ! 153: break; ! 154: case HOSTED_WRITE: ! 155: check_err(env, write(ARG(0), (void *)ARG(1), ARG(2))); ! 156: break; ! 157: case HOSTED_LSEEK: ! 158: { ! 159: uint64_t off; ! 160: off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32); ! 161: check_err(env, lseek(ARG(0), off, ARG(3))); ! 162: } ! 163: break; ! 164: case HOSTED_RENAME: ! 165: /* Assume names are NULL terminated. */ ! 166: check_err(env, rename((char *)ARG(0), (char *)ARG(2))); ! 167: break; ! 168: case HOSTED_UNLINK: ! 169: /* Assume name is NULL terminated. */ ! 170: check_err(env, unlink((char *)ARG(0))); ! 171: break; ! 172: case HOSTED_STAT: ! 173: /* Assume name is NULL terminated. */ ! 174: { ! 175: struct stat s; ! 176: int rc; ! 177: rc = check_err(env, stat((char *)ARG(0), &s)); ! 178: if (rc == 0) { ! 179: translate_stat((struct m68k_gdb_stat *)ARG(2), &s); ! 180: } ! 181: } ! 182: break; ! 183: case HOSTED_FSTAT: ! 184: { ! 185: struct stat s; ! 186: int rc; ! 187: rc = check_err(env, fstat(ARG(0), &s)); ! 188: if (rc == 0) { ! 189: translate_stat((struct m68k_gdb_stat *)ARG(1), &s); ! 190: } ! 191: } ! 192: break; ! 193: case HOSTED_GETTIMEOFDAY: ! 194: { ! 195: struct timeval tv; ! 196: struct gdb_timeval *p; ! 197: int rc; ! 198: rc = check_err(env, gettimeofday(&tv, NULL)); ! 199: if (rc != 0) { ! 200: p = (struct gdb_timeval *)ARG(0); ! 201: p->tv_sec = tswap32(tv.tv_sec); ! 202: p->tv_usec = tswap64(tv.tv_usec); ! 203: } ! 204: } ! 205: break; ! 206: case HOSTED_ISATTY: ! 207: check_err(env, isatty(ARG(0))); ! 208: break; ! 209: case HOSTED_SYSTEM: ! 210: /* Assume name is NULL terminated. */ ! 211: check_err(env, system((char *)ARG(0))); ! 212: break; ! 213: default: ! 214: cpu_abort(env, "Unsupported semihosting syscall %d\n", nr); ! 215: } ! 216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.