Search
lxdream.org :: lxdream/src/dcload.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/dcload.c
changeset 209:ff67a7b9aa17
prev183:5938ecc01dc8
next422:61a0598e07ff
author nkeynes
date Sun Sep 16 07:03:23 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Implement MAC.W, MAC.L and DIV1
Correct SHAD/SHLD
Fix privilege and slot illegal checks on LDC/STC opcodes
Fix various other small bugs
view annotate diff log raw
     1 /**
     2  * $Id: dcload.c,v 1.6 2006-08-07 13:18:16 nkeynes Exp $
     3  * 
     4  * DC-load syscall implementation.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <stdio.h>
    20 #include "dream.h"
    21 #include "dreamcast.h"
    22 #include "mem.h"
    23 #include "syscall.h"
    24 #include "sh4/sh4core.h"
    26 #define SYS_READ 0
    27 #define SYS_WRITE 1
    28 #define SYS_OPEN 2
    29 #define SYS_CLOSE 3
    30 #define SYS_CREAT 4
    31 #define SYS_LINK 5
    32 #define SYS_UNLINK 6
    33 #define SYS_CHDIR 7
    34 #define SYS_CHMOD 8
    35 #define SYS_LSEEK 9
    36 #define SYS_FSTAT 10
    37 #define SYS_TIME 11
    38 #define SYS_STAT 12
    39 #define SYS_UTIME 13
    40 #define SYS_ASSIGNWRKMEM 14
    41 #define SYS_EXIT 15
    42 #define SYS_OPENDIR 16
    43 #define SYS_CLOSEDIR 17
    44 #define SYS_READDIR 18
    45 #define SYS_GETHOSTINFO 19
    47 #define SYS_MAGIC 0xDEADBEEF
    48 #define SYS_MAGIC_ADDR 0x8c004004
    49 #define SYSCALL_ADDR 0x8c004008
    51 static gboolean dcload_allow_unsafe = FALSE;
    53 void dcload_set_allow_unsafe( gboolean allow )
    54 {
    55     dcload_allow_unsafe = allow;
    56 }
    58 #define MAX_OPEN_FDS 16
    59 /**
    60  * Mapping from emulator fd to real fd (so we can limit read/write
    61  * to only fds we've explicitly granted access to).
    62  */
    63 int open_fds[MAX_OPEN_FDS];
    65 int dcload_alloc_fd() 
    66 {
    67     int i;
    68     for( i=0; i<MAX_OPEN_FDS; i++ ) {
    69 	if( open_fds[i] == -1 ) {
    70 	    return i;
    71 	}
    72     }
    73     return -1;
    74 }
    76 void dcload_syscall( uint32_t syscall_id ) 
    77 {
    78     uint32_t syscall = sh4r.r[4];
    79     int fd;
    80     switch( sh4r.r[4] ) {
    81     case SYS_READ:
    82 	fd = sh4r.r[5];
    83 	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
    84 	    sh4r.r[0] = -1;
    85 	} else {
    86 	    char *buf = mem_get_region( sh4r.r[6] );
    87 	    int length = sh4r.r[7];
    88 	    sh4r.r[0] = read( open_fds[fd], buf, length );
    89 	}
    90 	break;
    91     case SYS_WRITE:
    92 	fd = sh4r.r[5];
    93 	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
    94 	    sh4r.r[0] = -1;
    95 	} else {
    96 	    char *buf = mem_get_region( sh4r.r[6] );
    97 	    int length = sh4r.r[7];
    98 	    sh4r.r[0] = write( open_fds[fd], buf, length );
    99 	}
   100 	break;
   101     case SYS_LSEEK:
   102 	fd = sh4r.r[5];
   103 	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
   104 	    sh4r.r[0] = -1;
   105 	} else {
   106 	    sh4r.r[0] = lseek( open_fds[fd], sh4r.r[6], sh4r.r[7] );
   107 	}
   108 	break;
   110 /* Secure access only */
   111     case SYS_OPEN:
   112 	if( dcload_allow_unsafe ) {
   113 	    fd = dcload_alloc_fd();
   114 	    if( fd == -1 ) {
   115 		sh4r.r[0] = -1;
   116 	    } else {
   117 		char *filename = mem_get_region( sh4r.r[5] );
   118 		int realfd = open( filename, sh4r.r[6] );
   119 		open_fds[fd] = realfd;
   120 		sh4r.r[0] = realfd;
   121 	    }
   122 	} else {
   123 	    ERROR( "Denying access to local filesystem" );
   124 	    sh4r.r[0] = -1;
   125 	}
   126 	break;
   127     case SYS_CLOSE:
   128 	if( dcload_allow_unsafe ) {
   129 	    fd = sh4r.r[5];
   130 	    if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
   131 		sh4r.r[0] = -1;
   132 	    } else {
   133 		if( open_fds[fd] > 2 ) {
   134 		    sh4r.r[0] = close( open_fds[fd] );
   135 		} else {
   136 		    /* Don't actually close real fds 0-2 */
   137 		    sh4r.r[0] = 0;
   138 		}
   139 		open_fds[fd] = -1;
   140 	    }
   141 	}
   142 	break;
   143     case SYS_EXIT:
   144 	if( dcload_allow_unsafe ) {
   145 	    exit( sh4r.r[5] );
   146 	} else {
   147 	    dreamcast_stop();
   148 	}
   149     default:
   150 	sh4r.r[0] = -1;
   151     }
   153 }
   155 void dcload_install() 
   156 {
   157     memset( &open_fds, -1, sizeof(open_fds) );
   158     open_fds[0] = 0;
   159     open_fds[1] = 1;
   160     open_fds[2] = 2;
   161     syscall_add_hook_vector( 0xF0, SYSCALL_ADDR, dcload_syscall );
   162     sh4_write_long( SYS_MAGIC_ADDR, SYS_MAGIC );
   163 }
.