Search
lxdream.org :: lxdream/src/dcload.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/dcload.c
changeset 422:61a0598e07ff
prev209:ff67a7b9aa17
next502:c4ecae2b1b5e
author nkeynes
date Wed Nov 07 11:45:53 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Add crash handler to get a backtrace via gdb
file annotate diff log raw
nkeynes@102
     1
/**
nkeynes@422
     2
 * $Id: dcload.c,v 1.7 2007-10-06 08:59:42 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@422
    20
#include <unistd.h>
nkeynes@422
    21
#include <fcntl.h>
nkeynes@422
    22
nkeynes@102
    23
#include "dream.h"
nkeynes@422
    24
#include "mem.h"
nkeynes@182
    25
#include "dreamcast.h"
nkeynes@102
    26
#include "syscall.h"
nkeynes@102
    27
#include "sh4/sh4core.h"
nkeynes@102
    28
nkeynes@102
    29
#define SYS_READ 0
nkeynes@102
    30
#define SYS_WRITE 1
nkeynes@102
    31
#define SYS_OPEN 2
nkeynes@102
    32
#define SYS_CLOSE 3
nkeynes@102
    33
#define SYS_CREAT 4
nkeynes@102
    34
#define SYS_LINK 5
nkeynes@102
    35
#define SYS_UNLINK 6
nkeynes@102
    36
#define SYS_CHDIR 7
nkeynes@102
    37
#define SYS_CHMOD 8
nkeynes@102
    38
#define SYS_LSEEK 9
nkeynes@102
    39
#define SYS_FSTAT 10
nkeynes@102
    40
#define SYS_TIME 11
nkeynes@102
    41
#define SYS_STAT 12
nkeynes@102
    42
#define SYS_UTIME 13
nkeynes@102
    43
#define SYS_ASSIGNWRKMEM 14
nkeynes@102
    44
#define SYS_EXIT 15
nkeynes@102
    45
#define SYS_OPENDIR 16
nkeynes@102
    46
#define SYS_CLOSEDIR 17
nkeynes@102
    47
#define SYS_READDIR 18
nkeynes@102
    48
#define SYS_GETHOSTINFO 19
nkeynes@102
    49
nkeynes@102
    50
#define SYS_MAGIC 0xDEADBEEF
nkeynes@102
    51
#define SYS_MAGIC_ADDR 0x8c004004
nkeynes@102
    52
#define SYSCALL_ADDR 0x8c004008
nkeynes@102
    53
nkeynes@209
    54
static gboolean dcload_allow_unsafe = FALSE;
nkeynes@182
    55
nkeynes@209
    56
void dcload_set_allow_unsafe( gboolean allow )
nkeynes@182
    57
{
nkeynes@209
    58
    dcload_allow_unsafe = allow;
nkeynes@209
    59
}
nkeynes@209
    60
nkeynes@209
    61
#define MAX_OPEN_FDS 16
nkeynes@209
    62
/**
nkeynes@209
    63
 * Mapping from emulator fd to real fd (so we can limit read/write
nkeynes@209
    64
 * to only fds we've explicitly granted access to).
nkeynes@209
    65
 */
nkeynes@209
    66
int open_fds[MAX_OPEN_FDS];
nkeynes@209
    67
nkeynes@209
    68
int dcload_alloc_fd() 
nkeynes@209
    69
{
nkeynes@209
    70
    int i;
nkeynes@209
    71
    for( i=0; i<MAX_OPEN_FDS; i++ ) {
nkeynes@209
    72
	if( open_fds[i] == -1 ) {
nkeynes@209
    73
	    return i;
nkeynes@209
    74
	}
nkeynes@209
    75
    }
nkeynes@209
    76
    return -1;
nkeynes@182
    77
}
nkeynes@182
    78
nkeynes@102
    79
void dcload_syscall( uint32_t syscall_id ) 
nkeynes@102
    80
{
nkeynes@422
    81
    // uint32_t syscall = sh4r.r[4];
nkeynes@209
    82
    int fd;
nkeynes@102
    83
    switch( sh4r.r[4] ) {
nkeynes@102
    84
    case SYS_READ:
nkeynes@209
    85
	fd = sh4r.r[5];
nkeynes@209
    86
	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
nkeynes@209
    87
	    sh4r.r[0] = -1;
nkeynes@209
    88
	} else {
nkeynes@102
    89
	    char *buf = mem_get_region( sh4r.r[6] );
nkeynes@102
    90
	    int length = sh4r.r[7];
nkeynes@209
    91
	    sh4r.r[0] = read( open_fds[fd], buf, length );
nkeynes@209
    92
	}
nkeynes@209
    93
	break;
nkeynes@209
    94
    case SYS_WRITE:
nkeynes@209
    95
	fd = sh4r.r[5];
nkeynes@209
    96
	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
nkeynes@209
    97
	    sh4r.r[0] = -1;
nkeynes@102
    98
	} else {
nkeynes@209
    99
	    char *buf = mem_get_region( sh4r.r[6] );
nkeynes@209
   100
	    int length = sh4r.r[7];
nkeynes@209
   101
	    sh4r.r[0] = write( open_fds[fd], buf, length );
nkeynes@209
   102
	}
nkeynes@209
   103
	break;
nkeynes@209
   104
    case SYS_LSEEK:
nkeynes@209
   105
	fd = sh4r.r[5];
nkeynes@209
   106
	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
nkeynes@209
   107
	    sh4r.r[0] = -1;
nkeynes@209
   108
	} else {
nkeynes@209
   109
	    sh4r.r[0] = lseek( open_fds[fd], sh4r.r[6], sh4r.r[7] );
nkeynes@209
   110
	}
nkeynes@209
   111
	break;
nkeynes@209
   112
nkeynes@209
   113
/* Secure access only */
nkeynes@209
   114
    case SYS_OPEN:
nkeynes@209
   115
	if( dcload_allow_unsafe ) {
nkeynes@209
   116
	    fd = dcload_alloc_fd();
nkeynes@209
   117
	    if( fd == -1 ) {
nkeynes@209
   118
		sh4r.r[0] = -1;
nkeynes@209
   119
	    } else {
nkeynes@209
   120
		char *filename = mem_get_region( sh4r.r[5] );
nkeynes@209
   121
		int realfd = open( filename, sh4r.r[6] );
nkeynes@209
   122
		open_fds[fd] = realfd;
nkeynes@209
   123
		sh4r.r[0] = realfd;
nkeynes@209
   124
	    }
nkeynes@209
   125
	} else {
nkeynes@209
   126
	    ERROR( "Denying access to local filesystem" );
nkeynes@102
   127
	    sh4r.r[0] = -1;
nkeynes@102
   128
	}
nkeynes@102
   129
	break;
nkeynes@209
   130
    case SYS_CLOSE:
nkeynes@209
   131
	if( dcload_allow_unsafe ) {
nkeynes@209
   132
	    fd = sh4r.r[5];
nkeynes@209
   133
	    if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
nkeynes@209
   134
		sh4r.r[0] = -1;
nkeynes@209
   135
	    } else {
nkeynes@209
   136
		if( open_fds[fd] > 2 ) {
nkeynes@209
   137
		    sh4r.r[0] = close( open_fds[fd] );
nkeynes@209
   138
		} else {
nkeynes@209
   139
		    /* Don't actually close real fds 0-2 */
nkeynes@209
   140
		    sh4r.r[0] = 0;
nkeynes@209
   141
		}
nkeynes@209
   142
		open_fds[fd] = -1;
nkeynes@209
   143
	    }
nkeynes@102
   144
	}
nkeynes@102
   145
	break;
nkeynes@102
   146
    case SYS_EXIT:
nkeynes@209
   147
	if( dcload_allow_unsafe ) {
nkeynes@183
   148
	    exit( sh4r.r[5] );
nkeynes@209
   149
	} else {
nkeynes@182
   150
	    dreamcast_stop();
nkeynes@209
   151
	}
nkeynes@102
   152
    default:
nkeynes@102
   153
	sh4r.r[0] = -1;
nkeynes@102
   154
    }
nkeynes@102
   155
nkeynes@102
   156
}
nkeynes@102
   157
nkeynes@102
   158
void dcload_install() 
nkeynes@102
   159
{
nkeynes@209
   160
    memset( &open_fds, -1, sizeof(open_fds) );
nkeynes@209
   161
    open_fds[0] = 0;
nkeynes@209
   162
    open_fds[1] = 1;
nkeynes@209
   163
    open_fds[2] = 2;
nkeynes@102
   164
    syscall_add_hook_vector( 0xF0, SYSCALL_ADDR, dcload_syscall );
nkeynes@102
   165
    sh4_write_long( SYS_MAGIC_ADDR, SYS_MAGIC );
nkeynes@102
   166
}
.