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