aboutsummaryrefslogtreecommitdiff
path: root/target-mips/mips-semi.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-mips/mips-semi.c')
-rw-r--r--target-mips/mips-semi.c374
1 files changed, 0 insertions, 374 deletions
diff --git a/target-mips/mips-semi.c b/target-mips/mips-semi.c
deleted file mode 100644
index a7aefbaefc..0000000000
--- a/target-mips/mips-semi.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Unified Hosting Interface syscalls.
- *
- * Copyright (c) 2015 Imagination Technologies
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "qemu/log.h"
-#include "exec/helper-proto.h"
-#include "exec/softmmu-semi.h"
-#include "exec/semihost.h"
-
-typedef enum UHIOp {
- UHI_exit = 1,
- UHI_open = 2,
- UHI_close = 3,
- UHI_read = 4,
- UHI_write = 5,
- UHI_lseek = 6,
- UHI_unlink = 7,
- UHI_fstat = 8,
- UHI_argc = 9,
- UHI_argnlen = 10,
- UHI_argn = 11,
- UHI_plog = 13,
- UHI_assert = 14,
- UHI_pread = 19,
- UHI_pwrite = 20,
- UHI_link = 22
-} UHIOp;
-
-typedef struct UHIStat {
- int16_t uhi_st_dev;
- uint16_t uhi_st_ino;
- uint32_t uhi_st_mode;
- uint16_t uhi_st_nlink;
- uint16_t uhi_st_uid;
- uint16_t uhi_st_gid;
- int16_t uhi_st_rdev;
- uint64_t uhi_st_size;
- uint64_t uhi_st_atime;
- uint64_t uhi_st_spare1;
- uint64_t uhi_st_mtime;
- uint64_t uhi_st_spare2;
- uint64_t uhi_st_ctime;
- uint64_t uhi_st_spare3;
- uint64_t uhi_st_blksize;
- uint64_t uhi_st_blocks;
- uint64_t uhi_st_spare4[2];
-} UHIStat;
-
-enum UHIOpenFlags {
- UHIOpen_RDONLY = 0x0,
- UHIOpen_WRONLY = 0x1,
- UHIOpen_RDWR = 0x2,
- UHIOpen_APPEND = 0x8,
- UHIOpen_CREAT = 0x200,
- UHIOpen_TRUNC = 0x400,
- UHIOpen_EXCL = 0x800
-};
-
-/* Errno values taken from asm-mips/errno.h */
-static uint16_t host_to_mips_errno[] = {
- [ENAMETOOLONG] = 78,
-#ifdef EOVERFLOW
- [EOVERFLOW] = 79,
-#endif
-#ifdef ELOOP
- [ELOOP] = 90,
-#endif
-};
-
-static int errno_mips(int err)
-{
- if (err < 0 || err >= ARRAY_SIZE(host_to_mips_errno)) {
- return EINVAL;
- } else if (host_to_mips_errno[err]) {
- return host_to_mips_errno[err];
- } else {
- return err;
- }
-}
-
-static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src,
- target_ulong vaddr)
-{
- hwaddr len = sizeof(struct UHIStat);
- UHIStat *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
- if (!dst) {
- errno = EFAULT;
- return -1;
- }
-
- dst->uhi_st_dev = tswap16(src->st_dev);
- dst->uhi_st_ino = tswap16(src->st_ino);
- dst->uhi_st_mode = tswap32(src->st_mode);
- dst->uhi_st_nlink = tswap16(src->st_nlink);
- dst->uhi_st_uid = tswap16(src->st_uid);
- dst->uhi_st_gid = tswap16(src->st_gid);
- dst->uhi_st_rdev = tswap16(src->st_rdev);
- dst->uhi_st_size = tswap64(src->st_size);
- dst->uhi_st_atime = tswap64(src->st_atime);
- dst->uhi_st_mtime = tswap64(src->st_mtime);
- dst->uhi_st_ctime = tswap64(src->st_ctime);
-#ifdef _WIN32
- dst->uhi_st_blksize = 0;
- dst->uhi_st_blocks = 0;
-#else
- dst->uhi_st_blksize = tswap64(src->st_blksize);
- dst->uhi_st_blocks = tswap64(src->st_blocks);
-#endif
- unlock_user(dst, vaddr, len);
- return 0;
-}
-
-static int get_open_flags(target_ulong target_flags)
-{
- int open_flags = 0;
-
- if (target_flags & UHIOpen_RDWR) {
- open_flags |= O_RDWR;
- } else if (target_flags & UHIOpen_WRONLY) {
- open_flags |= O_WRONLY;
- } else {
- open_flags |= O_RDONLY;
- }
-
- open_flags |= (target_flags & UHIOpen_APPEND) ? O_APPEND : 0;
- open_flags |= (target_flags & UHIOpen_CREAT) ? O_CREAT : 0;
- open_flags |= (target_flags & UHIOpen_TRUNC) ? O_TRUNC : 0;
- open_flags |= (target_flags & UHIOpen_EXCL) ? O_EXCL : 0;
-
- return open_flags;
-}
-
-static int write_to_file(CPUMIPSState *env, target_ulong fd, target_ulong vaddr,
- target_ulong len, target_ulong offset)
-{
- int num_of_bytes;
- void *dst = lock_user(VERIFY_READ, vaddr, len, 1);
- if (!dst) {
- errno = EFAULT;
- return -1;
- }
-
- if (offset) {
-#ifdef _WIN32
- num_of_bytes = 0;
-#else
- num_of_bytes = pwrite(fd, dst, len, offset);
-#endif
- } else {
- num_of_bytes = write(fd, dst, len);
- }
-
- unlock_user(dst, vaddr, 0);
- return num_of_bytes;
-}
-
-static int read_from_file(CPUMIPSState *env, target_ulong fd,
- target_ulong vaddr, target_ulong len,
- target_ulong offset)
-{
- int num_of_bytes;
- void *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
- if (!dst) {
- errno = EFAULT;
- return -1;
- }
-
- if (offset) {
-#ifdef _WIN32
- num_of_bytes = 0;
-#else
- num_of_bytes = pread(fd, dst, len, offset);
-#endif
- } else {
- num_of_bytes = read(fd, dst, len);
- }
-
- unlock_user(dst, vaddr, len);
- return num_of_bytes;
-}
-
-static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
- target_ulong vaddr)
-{
- int strsize = strlen(semihosting_get_arg(arg_num)) + 1;
- char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0);
- if (!dst) {
- return -1;
- }
-
- strcpy(dst, semihosting_get_arg(arg_num));
-
- unlock_user(dst, vaddr, strsize);
- return 0;
-}
-
-#define GET_TARGET_STRING(p, addr) \
- do { \
- p = lock_user_string(addr); \
- if (!p) { \
- gpr[2] = -1; \
- gpr[3] = EFAULT; \
- goto uhi_done; \
- } \
- } while (0)
-
-#define GET_TARGET_STRINGS_2(p, addr, p2, addr2) \
- do { \
- p = lock_user_string(addr); \
- if (!p) { \
- gpr[2] = -1; \
- gpr[3] = EFAULT; \
- goto uhi_done; \
- } \
- p2 = lock_user_string(addr2); \
- if (!p2) { \
- unlock_user(p, addr, 0); \
- gpr[2] = -1; \
- gpr[3] = EFAULT; \
- goto uhi_done; \
- } \
- } while (0)
-
-#define FREE_TARGET_STRING(p, gpr) \
- do { \
- unlock_user(p, gpr, 0); \
- } while (0)
-
-void helper_do_semihosting(CPUMIPSState *env)
-{
- target_ulong *gpr = env->active_tc.gpr;
- const UHIOp op = gpr[25];
- char *p, *p2;
-
- switch (op) {
- case UHI_exit:
- qemu_log("UHI(%d): exit(%d)\n", op, (int)gpr[4]);
- exit(gpr[4]);
- case UHI_open:
- GET_TARGET_STRING(p, gpr[4]);
- if (!strcmp("/dev/stdin", p)) {
- gpr[2] = 0;
- } else if (!strcmp("/dev/stdout", p)) {
- gpr[2] = 1;
- } else if (!strcmp("/dev/stderr", p)) {
- gpr[2] = 2;
- } else {
- gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]);
- gpr[3] = errno_mips(errno);
- }
- FREE_TARGET_STRING(p, gpr[4]);
- break;
- case UHI_close:
- if (gpr[4] < 3) {
- /* ignore closing stdin/stdout/stderr */
- gpr[2] = 0;
- goto uhi_done;
- }
- gpr[2] = close(gpr[4]);
- gpr[3] = errno_mips(errno);
- break;
- case UHI_read:
- gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], 0);
- gpr[3] = errno_mips(errno);
- break;
- case UHI_write:
- gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], 0);
- gpr[3] = errno_mips(errno);
- break;
- case UHI_lseek:
- gpr[2] = lseek(gpr[4], gpr[5], gpr[6]);
- gpr[3] = errno_mips(errno);
- break;
- case UHI_unlink:
- GET_TARGET_STRING(p, gpr[4]);
- gpr[2] = remove(p);
- gpr[3] = errno_mips(errno);
- FREE_TARGET_STRING(p, gpr[4]);
- break;
- case UHI_fstat:
- {
- struct stat sbuf;
- memset(&sbuf, 0, sizeof(sbuf));
- gpr[2] = fstat(gpr[4], &sbuf);
- gpr[3] = errno_mips(errno);
- if (gpr[2]) {
- goto uhi_done;
- }
- gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
- gpr[3] = errno_mips(errno);
- }
- break;
- case UHI_argc:
- gpr[2] = semihosting_get_argc();
- break;
- case UHI_argnlen:
- if (gpr[4] >= semihosting_get_argc()) {
- gpr[2] = -1;
- goto uhi_done;
- }
- gpr[2] = strlen(semihosting_get_arg(gpr[4]));
- break;
- case UHI_argn:
- if (gpr[4] >= semihosting_get_argc()) {
- gpr[2] = -1;
- goto uhi_done;
- }
- gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]);
- break;
- case UHI_plog:
- GET_TARGET_STRING(p, gpr[4]);
- p2 = strstr(p, "%d");
- if (p2) {
- int char_num = p2 - p;
- char *buf = g_malloc(char_num + 1);
- strncpy(buf, p, char_num);
- buf[char_num] = '\0';
- gpr[2] = printf("%s%d%s", buf, (int)gpr[5], p2 + 2);
- g_free(buf);
- } else {
- gpr[2] = printf("%s", p);
- }
- FREE_TARGET_STRING(p, gpr[4]);
- break;
- case UHI_assert:
- GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]);
- printf("assertion '");
- printf("\"%s\"", p);
- printf("': file \"%s\", line %d\n", p2, (int)gpr[6]);
- FREE_TARGET_STRING(p2, gpr[5]);
- FREE_TARGET_STRING(p, gpr[4]);
- abort();
- break;
- case UHI_pread:
- gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
- gpr[3] = errno_mips(errno);
- break;
- case UHI_pwrite:
- gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
- gpr[3] = errno_mips(errno);
- break;
-#ifndef _WIN32
- case UHI_link:
- GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]);
- gpr[2] = link(p, p2);
- gpr[3] = errno_mips(errno);
- FREE_TARGET_STRING(p2, gpr[5]);
- FREE_TARGET_STRING(p, gpr[4]);
- break;
-#endif
- default:
- fprintf(stderr, "Unknown UHI operation %d\n", op);
- abort();
- }
-uhi_done:
- return;
-}