2010-04-24 21:37:39 +00:00
|
|
|
/*********************************************************************
|
|
|
|
* Copyright (C) 2003 Tord Lindstrom (pukko@home.se)
|
|
|
|
* Copyright (C) 2003,2004 adresd (adresd_ps2dev@yahoo.com)
|
|
|
|
* This file is subject to the terms and conditions of the PS2Link License.
|
|
|
|
* See the file LICENSE in the main directory of this distribution for more
|
|
|
|
* details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <tamtypes.h>
|
|
|
|
#include <kernel.h>
|
|
|
|
#include <sifrpc.h>
|
|
|
|
#include <iopheap.h>
|
|
|
|
#include <loadfile.h>
|
|
|
|
#include <iopcontrol.h>
|
|
|
|
#include <fileio.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "debug.h"
|
|
|
|
#include "hostlink.h"
|
|
|
|
#include "excepHandler.h"
|
|
|
|
#include "stdio.h"
|
|
|
|
|
|
|
|
#include <sbv_patches.h>
|
|
|
|
|
|
|
|
#define WELCOME_STRING "Welcome to pcsx2hostfs v1.52\n"
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define dbgprintf(args...) printf(args)
|
|
|
|
#define dbgscr_printf(args...) scr_printf(args)
|
|
|
|
#else
|
|
|
|
#define dbgprintf(args...) do { } while(0)
|
|
|
|
#define dbgscr_printf(args...) do { } while(0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//#define BGCOLOR ((volatile unsigned long*)0x120000e0)
|
|
|
|
//#define GS_SET_BGCOLOR(R,G,B) *BGCOLOR = ((u64)(R)<< 0) | ((u64)(G)<< 8) | ((u64)(B)<< 16)
|
|
|
|
|
|
|
|
#define IRX_BUFFER_BASE 0x1F80000
|
|
|
|
int irx_buffer_addr = 0;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Globals
|
|
|
|
extern int userThreadID;
|
|
|
|
|
|
|
|
// Argv name+path & just path
|
|
|
|
char elfName[256] __attribute__((aligned(16)));
|
|
|
|
char elfPath[256];
|
|
|
|
|
|
|
|
#ifndef BUILTIN_IRXS
|
|
|
|
char ioptrap_path[PKO_MAX_PATH];
|
|
|
|
char pcsx2hostfs_path[PKO_MAX_PATH];
|
|
|
|
|
|
|
|
void *ioptrap_mod = NULL, *pcsx2hostfs_mod = NULL;
|
|
|
|
int ioptrap_size = 0, pcsx2hostfs_size = 0;
|
|
|
|
#else
|
|
|
|
extern unsigned char _binary_ioptrap_irx_start[], _binary_pcsx2hostfs_irx_start[];
|
|
|
|
extern unsigned char _binary_ioptrap_irx_end[], _binary_pcsx2hostfs_irx_end[];
|
|
|
|
static unsigned int _binary_ioptrap_irx_size, _binary_pcsx2hostfs_irx_size;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
char *imgcmd = "rom0:UDNL rom0:EELOADCNF";
|
|
|
|
|
|
|
|
// Flags for which type of boot
|
|
|
|
#define B_CD 1
|
|
|
|
#define B_MC 2
|
|
|
|
#define B_HOST 3
|
|
|
|
#define B_CC 4
|
|
|
|
#define B_UNKN 5
|
|
|
|
int boot;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Prototypes
|
|
|
|
static void loadModules(void);
|
|
|
|
static void pkoLoadModule(char *path, int argc, char *argv);
|
|
|
|
static void getIpConfig(void);
|
|
|
|
|
|
|
|
extern int pkoExecEE(pko_pkt_execee_req *cmd);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define IPCONF_MAX_LEN 1024
|
|
|
|
|
|
|
|
char if_conf[IPCONF_MAX_LEN] = "";
|
|
|
|
char fExtraConfig[256];
|
|
|
|
int load_extra_conf = 0;
|
|
|
|
int if_conf_len = 0;
|
|
|
|
|
|
|
|
char ip[16] __attribute__((aligned(16))) = "192.168.0.10";
|
|
|
|
char netmask[16] __attribute__((aligned(16))) = "255.255.255.0";
|
|
|
|
char gw[16] __attribute__((aligned(16))) = "192.168.0.1";
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Parse network configuration from IPCONFIG.DAT
|
|
|
|
// Note: parsing really should be made more robust...
|
|
|
|
|
|
|
|
static int getBufferValue(char* result, char* buffer, u32 buffer_size, char* field)
|
|
|
|
{
|
|
|
|
u32 len = strlen(field);
|
|
|
|
u32 i = 0;
|
|
|
|
s32 j = 0;
|
|
|
|
char* start = 0;
|
|
|
|
char* end = 0;
|
|
|
|
|
|
|
|
while(strncmp(&buffer[i], field, len) != 0)
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if(i == buffer_size) return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for # comment
|
|
|
|
j = i;
|
|
|
|
|
|
|
|
while((j > 0) && (buffer[j] != '\n') && (buffer[j] !='\r'))
|
|
|
|
{
|
|
|
|
j--;
|
|
|
|
|
|
|
|
if(buffer[j] == '#')
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while(buffer[i] != '=')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if(i == buffer_size) return -3;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
|
|
|
|
while(buffer[i] == ' ')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if(i == buffer_size) return -4;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
|
|
|
|
if((buffer[i] != '\r') && (buffer[i] != '\n') && (buffer[i] != ';'))
|
|
|
|
{
|
|
|
|
start = &buffer[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -5;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(buffer[i] != ';')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if(i == buffer_size) return -5;
|
|
|
|
}
|
|
|
|
|
|
|
|
end = &buffer[i];
|
|
|
|
|
|
|
|
len = end - start;
|
|
|
|
|
|
|
|
if(len > 256) return -6;
|
|
|
|
|
|
|
|
strncpy(result, start, len);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
getIpConfig(void)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int i;
|
|
|
|
int t;
|
|
|
|
int len;
|
|
|
|
char c;
|
|
|
|
char buf[IPCONF_MAX_LEN+256];
|
|
|
|
static char path[256];
|
|
|
|
|
|
|
|
if (boot == B_CD) {
|
|
|
|
sprintf(path, "%s%s;1", elfPath, "IPCONFIG.DAT");
|
|
|
|
}
|
|
|
|
else if (boot == B_CC) {
|
|
|
|
strcpy(path, "mc0:/BOOT/IPCONFIG.DAT");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sprintf(path, "%s%s", elfPath, "IPCONFIG.DAT");
|
|
|
|
}
|
|
|
|
fd = fioOpen(path, O_RDONLY);
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
{
|
|
|
|
scr_printf("Could not find IPCONFIG.DAT, using defaults\n"
|
|
|
|
"Net config: %s %s %s\n", ip, netmask, gw);
|
|
|
|
// Set defaults
|
|
|
|
memset(if_conf, 0x00, IPCONF_MAX_LEN);
|
|
|
|
i = 0;
|
|
|
|
strncpy(&if_conf[i], ip, 15);
|
|
|
|
i += strlen(ip) + 1;
|
|
|
|
|
|
|
|
strncpy(&if_conf[i], netmask, 15);
|
|
|
|
i += strlen(netmask) + 1;
|
|
|
|
|
|
|
|
strncpy(&if_conf[i], gw, 15);
|
|
|
|
i += strlen(gw) + 1;
|
|
|
|
|
|
|
|
if_conf_len = i;
|
|
|
|
dbgscr_printf("conf len %d\n", if_conf_len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(if_conf, 0x00, IPCONF_MAX_LEN);
|
|
|
|
memset(buf, 0x00, IPCONF_MAX_LEN+256);
|
|
|
|
|
|
|
|
len = fioRead(fd, buf, IPCONF_MAX_LEN + 256 - 1); // Let the last byte be '\0'
|
|
|
|
fioClose(fd);
|
|
|
|
|
|
|
|
if (len < 0) {
|
|
|
|
dbgprintf("Error reading ipconfig.dat\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dbgscr_printf("ipconfig: Read %d bytes\n", len);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
// Clear out spaces (and potential ending CR/LF)
|
|
|
|
while ((c = buf[i]) != '\0') {
|
|
|
|
if ((c == ' ') || (c == '\r') || (c == '\n'))
|
|
|
|
buf[i] = '\0';
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
scr_printf("Net config: ");
|
|
|
|
for (t = 0, i = 0; t < 3; t++) {
|
|
|
|
strncpy(&if_conf[i], &buf[i], 15);
|
|
|
|
scr_printf("%s ", &if_conf[i]);
|
|
|
|
i += strlen(&if_conf[i]) + 1;
|
|
|
|
}
|
|
|
|
scr_printf("\n");
|
|
|
|
// get extra config filename
|
|
|
|
|
|
|
|
#ifndef USE_CACHED_CFG
|
|
|
|
if(getBufferValue(fExtraConfig, buf, len, "EXTRACNF") == 0)
|
|
|
|
{
|
|
|
|
scr_printf("extra conf: %s\n", fExtraConfig);
|
|
|
|
|
|
|
|
load_extra_conf = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
load_extra_conf = 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
load_extra_conf = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if_conf_len = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
getExtraConfig()
|
|
|
|
{
|
|
|
|
int fd, size, ret;
|
|
|
|
char *buf, *ptr, *ptr2;
|
|
|
|
fd = fioOpen(fExtraConfig, O_RDONLY);
|
|
|
|
|
|
|
|
if ( fd < 0 )
|
|
|
|
{
|
|
|
|
scr_printf("failed to open extra conf file\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = fioLseek(fd, 0, SEEK_END);
|
|
|
|
fioLseek(fd, 0, SEEK_SET);
|
|
|
|
buf = malloc(size + 1);
|
|
|
|
ret = fioRead(fd, buf, size);
|
|
|
|
buf[size] = 0;
|
|
|
|
fioClose(fd);
|
|
|
|
ptr = buf;
|
|
|
|
ptr2 = buf;
|
|
|
|
while(ptr < buf+size) {
|
|
|
|
ptr2 = strstr(ptr, ";");
|
|
|
|
if ( ptr2 == 0 ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ptr[ptr2-ptr] = 0;
|
|
|
|
scr_printf("loading %s\n", ptr);
|
|
|
|
pkoLoadModule(ptr, 0, NULL);
|
|
|
|
ptr = ptr2+1;
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Wrapper to load irx module from disc/rom
|
|
|
|
static void
|
|
|
|
pkoLoadModule(char *path, int argc, char *argv)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = SifLoadModule(path, argc, argv);
|
|
|
|
if (ret < 0) {
|
|
|
|
scr_printf("Could not load module %s: %d\n", path, ret);
|
|
|
|
SleepThread();
|
|
|
|
}
|
|
|
|
dbgscr_printf("[%d] returned\n", ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef BUILTIN_IRXS
|
|
|
|
/* Load a module into RAM. */
|
|
|
|
void * modbuf_load(const char *filename, int *filesize)
|
|
|
|
{
|
|
|
|
void *res = NULL;
|
|
|
|
int fd = -1, size;
|
|
|
|
|
|
|
|
if ((fd = fioOpen(filename, O_RDONLY)) < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if ((size = fioLseek(fd, 0, SEEK_END)) < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
fioLseek(fd, 0, SEEK_SET);
|
|
|
|
fioLseek(fd, 0, SEEK_SET);
|
|
|
|
|
|
|
|
res = (void *)irx_buffer_addr;
|
|
|
|
irx_buffer_addr += size + 32 - (size % 16);
|
|
|
|
dbgscr_printf(" modbuf_load : %s , %d (0x%X)\n",filename,size,(int)res);
|
|
|
|
|
|
|
|
if (fioRead(fd, res, size) != size)
|
|
|
|
res = NULL;
|
|
|
|
|
|
|
|
if (filesize)
|
|
|
|
*filesize = size;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (fd >= 0)
|
|
|
|
fioClose(fd);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int loadHostModBuffers()
|
|
|
|
{
|
|
|
|
if (irx_buffer_addr == 0)
|
|
|
|
{
|
|
|
|
irx_buffer_addr = IRX_BUFFER_BASE;
|
|
|
|
|
|
|
|
getIpConfig();
|
|
|
|
|
|
|
|
if (!(ioptrap_mod = modbuf_load(ioptrap_path, &ioptrap_size)))
|
|
|
|
{return -1;}
|
|
|
|
|
|
|
|
if (!(pcsx2hostfs_mod = modbuf_load(pcsx2hostfs_path, &pcsx2hostfs_size)))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dbgscr_printf("Using Cached Modules\n");
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Load all the irx modules we need, according to 'boot mode'
|
|
|
|
static void
|
|
|
|
loadModules(void)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
#ifdef USE_CACHED_CFG
|
|
|
|
int i,t;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dbgscr_printf("loadModules \n");
|
|
|
|
|
|
|
|
#ifdef USE_CACHED_CFG
|
|
|
|
if(if_conf_len==0)
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
if ((boot == B_MC) || (boot == B_CC))
|
|
|
|
{
|
|
|
|
pkoLoadModule("rom0:SIO2MAN", 0, NULL);
|
|
|
|
pkoLoadModule("rom0:MCMAN", 0, NULL);
|
|
|
|
pkoLoadModule("rom0:MCSERV", 0, NULL);
|
|
|
|
}
|
|
|
|
#ifdef USE_CACHED_CFG
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef BUILTIN_IRXS
|
|
|
|
_binary_ioptrap_irx_size = _binary_ioptrap_irx_end - _binary_ioptrap_irx_start;
|
|
|
|
_binary_pcsx2hostfs_irx_size = _binary_pcsx2hostfs_irx_end - _binary_pcsx2hostfs_irx_start;
|
|
|
|
|
|
|
|
#ifdef USE_CACHED_CFG
|
|
|
|
if(if_conf_len==0)
|
|
|
|
{
|
|
|
|
getIpConfig();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i=0;
|
|
|
|
scr_printf("Net config: ");
|
|
|
|
for (t = 0, i = 0; t < 3; t++) {
|
|
|
|
scr_printf("%s ", &if_conf[i]);
|
|
|
|
i += strlen(&if_conf[i]) + 1;
|
|
|
|
}
|
|
|
|
scr_printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
getIpConfig();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dbgscr_printf("Exec ioptrap module. (%x,%d) ", (unsigned int)_binary_ioptrap_irx_start, _binary_ioptrap_irx_size);
|
|
|
|
SifExecModuleBuffer(_binary_ioptrap_irx_start, _binary_ioptrap_irx_size, 0, NULL,&ret);
|
|
|
|
dbgscr_printf("[%d] returned\n", ret);
|
|
|
|
dbgscr_printf("Exec pcsx2hostfs module. (%x,%d) ", (unsigned int)_binary_pcsx2hostfs_irx_start, _binary_pcsx2hostfs_irx_size);
|
|
|
|
SifExecModuleBuffer(_binary_pcsx2hostfs_irx_start, _binary_pcsx2hostfs_irx_size, 0, NULL,&ret);
|
|
|
|
dbgscr_printf("[%d] returned\n", ret);
|
|
|
|
dbgscr_printf("All modules loaded on IOP.\n");
|
|
|
|
#else
|
|
|
|
if (boot == B_HOST) {
|
|
|
|
|
|
|
|
dbgscr_printf("Exec ioptrap module. (%x,%d) ", (u32)ioptrap_mod, ioptrap_size);
|
|
|
|
SifExecModuleBuffer(ioptrap_mod, ioptrap_size, 0, NULL,&ret);
|
|
|
|
dbgscr_printf("[%d] returned\n", ret);
|
|
|
|
dbgscr_printf("Exec pcsx2hostfs module. (%x,%d) ", (u32)pcsx2hostfs_mod, pcsx2hostfs_size);
|
|
|
|
SifExecModuleBuffer(pcsx2hostfs_mod, pcsx2hostfs_size, 0, NULL,&ret);
|
|
|
|
dbgscr_printf("[%d] returned\n", ret);
|
|
|
|
|
|
|
|
|
|
|
|
dbgscr_printf("All modules loaded on IOP.\n");
|
|
|
|
} else {
|
|
|
|
getIpConfig();
|
|
|
|
dbgscr_printf("Exec ioptrap module. ");
|
|
|
|
pkoLoadModule(ioptrap_path, 0, NULL);
|
|
|
|
dbgscr_printf("Exec pcsx2hostfs module. ");
|
|
|
|
pkoLoadModule(pcsx2hostfs_path, 0, NULL);
|
|
|
|
dbgscr_printf("All modules loaded on IOP. ");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// C standard strrchr func..
|
|
|
|
char *strrchr(const char *s, int i)
|
|
|
|
{
|
|
|
|
const char *last = NULL;
|
|
|
|
char c = i;
|
|
|
|
|
|
|
|
while (*s) {
|
|
|
|
if (*s == c) {
|
|
|
|
last = s;
|
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*s == c) {
|
|
|
|
last = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (char *) last;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Split path (argv[0]) at the last '/', '\' or ':' and initialise
|
|
|
|
// elfName (whole path & name to the elf, for example 'cdrom:\pukklink.elf')
|
|
|
|
// elfPath (path to where the elf was started, for example 'cdrom:\')
|
|
|
|
static void
|
|
|
|
setPathInfo(char *path)
|
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
strncpy(elfName, path, 255);
|
|
|
|
strncpy(elfPath, path, 255);
|
|
|
|
elfName[255] = '\0';
|
|
|
|
elfPath[255] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
ptr = strrchr(elfPath, '/');
|
|
|
|
if (ptr == NULL) {
|
|
|
|
ptr = strrchr(elfPath, '\\');
|
|
|
|
if (ptr == NULL) {
|
|
|
|
ptr = strrchr(elfPath, ':');
|
|
|
|
if (ptr == NULL) {
|
|
|
|
scr_printf("Did not find path (%s)!\n", path);
|
|
|
|
SleepThread();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr++;
|
|
|
|
*ptr = '\0';
|
|
|
|
|
|
|
|
#ifndef BUILTIN_IRXS
|
|
|
|
/* Paths to modules. */
|
|
|
|
|
|
|
|
sprintf(pcsx2hostfs_path, "%s%s", elfPath, "PS2LINK.IRX");
|
|
|
|
sprintf(ioptrap_path, "%s%s", elfPath, "IOPTRAP.IRX");
|
|
|
|
|
|
|
|
if (boot == B_CD) {
|
|
|
|
strcat(ioptrap_path, ";1");
|
|
|
|
strcat(pcsx2hostfs_path, ";1");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dbgscr_printf("path is %s\n", elfPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Clear user memory
|
|
|
|
void
|
|
|
|
wipeUserMem(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
// Whipe user mem
|
|
|
|
for (i = 0x100000; i < 0x2000000 ; i += 64) {
|
|
|
|
asm (
|
|
|
|
"\tsq $0, 0(%0) \n"
|
|
|
|
"\tsq $0, 16(%0) \n"
|
|
|
|
"\tsq $0, 32(%0) \n"
|
|
|
|
"\tsq $0, 48(%0) \n"
|
|
|
|
:: "r" (i) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Clear user memory - Load High and Host version
|
|
|
|
void
|
|
|
|
wipeUserMemLoadHigh(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
// Whipe user mem, apart from last bit
|
|
|
|
for (i = 0x100000; i < 0x1F00000 ; i += 64) {
|
|
|
|
asm (
|
|
|
|
"\tsq $0, 0(%0) \n"
|
|
|
|
"\tsq $0, 16(%0) \n"
|
|
|
|
"\tsq $0, 32(%0) \n"
|
|
|
|
"\tsq $0, 48(%0) \n"
|
|
|
|
:: "r" (i) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
restartIOP()
|
|
|
|
{
|
|
|
|
fioExit();
|
|
|
|
SifExitIopHeap();
|
|
|
|
SifLoadFileExit();
|
|
|
|
SifExitRpc();
|
|
|
|
|
|
|
|
dbgscr_printf("reset iop\n");
|
|
|
|
SifIopReset(imgcmd, 0);
|
|
|
|
while (SifIopSync()) ;
|
|
|
|
|
|
|
|
dbgscr_printf("rpc init\n");
|
|
|
|
SifInitRpc(0);
|
|
|
|
|
|
|
|
scr_printf("Initializing...\n");
|
|
|
|
sio_printf("Initializing...\n");
|
|
|
|
sbv_patch_enable_lmb();
|
|
|
|
sbv_patch_disable_prefix_check();
|
|
|
|
|
|
|
|
// SifLoadFileReset();
|
|
|
|
dbgscr_printf("loading modules\n");
|
|
|
|
loadModules();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if HOOK_THREADS
|
|
|
|
|
|
|
|
// we can spare 1k to allow a generous number of threads..
|
|
|
|
#define MAX_MONITORED_THREADS 256
|
|
|
|
|
|
|
|
int _first_load = 1;
|
|
|
|
|
|
|
|
int th_count;
|
|
|
|
int active_threads[MAX_MONITORED_THREADS];
|
|
|
|
|
|
|
|
void *addr_LoadExecPS2;
|
|
|
|
void *addr_CreateThread;
|
|
|
|
void *addr_DeleteThread;
|
|
|
|
|
|
|
|
void InstallKernelHooks(void)
|
|
|
|
{
|
|
|
|
// get the current address of each syscall we want to hook then replace the entry
|
|
|
|
// in the syscall table with that of our hook function.
|
|
|
|
|
|
|
|
addr_LoadExecPS2 = GetSyscall(6);
|
|
|
|
SetSyscall(6, &Hook_LoadExecPS2);
|
|
|
|
|
|
|
|
addr_CreateThread = GetSyscall(32);
|
|
|
|
SetSyscall(32, &Hook_CreateThread);
|
|
|
|
|
|
|
|
addr_DeleteThread = GetSyscall(33);
|
|
|
|
SetSyscall(33, &Hook_DeleteThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveKernelHooks(void)
|
|
|
|
{
|
|
|
|
SetSyscall(6, addr_LoadExecPS2);
|
|
|
|
SetSyscall(32, addr_CreateThread);
|
|
|
|
SetSyscall(33, addr_DeleteThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Hook_LoadExecPS2(char *fname, int argc, char *argv[])
|
|
|
|
{
|
|
|
|
// kill any active threads
|
|
|
|
KillActiveThreads();
|
|
|
|
|
|
|
|
// remove our kernel hooks
|
|
|
|
RemoveKernelHooks();
|
|
|
|
|
|
|
|
// call the real LoadExecPS2 handler, this will never return
|
|
|
|
return(((int (*)(char *, int, char **)) (addr_LoadExecPS2))(fname, argc, argv));
|
|
|
|
}
|
|
|
|
|
|
|
|
int Hook_CreateThread(ee_thread_t *thread_p)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < MAX_MONITORED_THREADS; i++)
|
|
|
|
{
|
|
|
|
if(active_threads[i] < 0) { break; }
|
|
|
|
}
|
|
|
|
|
|
|
|
if(i >= MAX_MONITORED_THREADS) { return(-1); }
|
|
|
|
|
|
|
|
// call the real CreateThread handler, saving the thread id in our list
|
|
|
|
return(active_threads[i] = ((int (*)(ee_thread_t *)) (addr_CreateThread))(thread_p));
|
|
|
|
}
|
|
|
|
|
|
|
|
int Hook_DeleteThread(int th_id)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i = 0; i < MAX_MONITORED_THREADS; i++)
|
|
|
|
{
|
|
|
|
if(active_threads[i] == th_id)
|
|
|
|
{
|
|
|
|
// remove the entry from the active thread list.
|
|
|
|
active_threads[i] = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// call the real DeleteThread handler
|
|
|
|
return(((int (*)(int)) (addr_DeleteThread))(th_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
// kill all threads created and not deleted since PS2LINK.ELF started except for the calling thread.
|
|
|
|
void KillActiveThreads(void)
|
|
|
|
{
|
|
|
|
int my_id = GetThreadId();
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i = 0; i < MAX_MONITORED_THREADS; i++)
|
|
|
|
{
|
|
|
|
if((active_threads[i] >= 0) && (active_threads[i] != my_id))
|
|
|
|
{
|
|
|
|
TerminateThread(active_threads[i]);
|
|
|
|
DeleteThread(active_threads[i]);
|
|
|
|
active_threads[i] = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ResetActiveThreads(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < MAX_MONITORED_THREADS; i++) { active_threads[i] = -1; }
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern void _start(void);
|
|
|
|
extern int _end;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
// int ret;
|
|
|
|
char *bootPath;
|
|
|
|
|
|
|
|
init_scr();
|
|
|
|
scr_printf(WELCOME_STRING);
|
|
|
|
#ifdef _LOADHIGHVER
|
|
|
|
scr_printf("Highload version\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef SCREENSHOTS
|
|
|
|
scr_printf("Screenshot capable\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
scr_printf("pcsx2hostfs loaded at 0x%08X-0x%08X\n", ((u32) _start) - 8, (u32) &_end);
|
|
|
|
|
|
|
|
installExceptionHandlers();
|
|
|
|
|
|
|
|
#if HOOK_THREADS
|
|
|
|
if(_first_load)
|
|
|
|
{
|
|
|
|
_first_load = 0;
|
|
|
|
InstallKernelHooks();
|
|
|
|
}
|
|
|
|
|
|
|
|
ResetActiveThreads();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// argc == 0 usually means naplink..
|
|
|
|
if (argc == 0) {
|
|
|
|
bootPath = "host:";
|
|
|
|
}
|
|
|
|
// reload1 usually gives an argc > 60000 (yea, this is kinda a hack..)
|
|
|
|
else if (argc != 1) {
|
|
|
|
bootPath = "mc0:/BWLINUX/";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bootPath = argv[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
SifInitRpc(0);
|
|
|
|
dbgscr_printf("Checking argv\n");
|
|
|
|
boot = 0;
|
|
|
|
|
|
|
|
setPathInfo(bootPath);
|
|
|
|
|
|
|
|
if(!strncmp(bootPath, "mc", strlen("mc"))) {
|
|
|
|
// Booting from my mc
|
|
|
|
scr_printf("Booting from mc dir (%s)\n", bootPath);
|
|
|
|
boot = B_MC;
|
|
|
|
}
|
|
|
|
else if(!strncmp(bootPath, "host", strlen("host"))) {
|
|
|
|
// Host
|
|
|
|
scr_printf("Booting from host (%s)\n", bootPath);
|
|
|
|
boot = B_HOST;
|
|
|
|
}
|
|
|
|
else if(!strncmp(bootPath, "rom0:OSDSYS", strlen("rom0:OSDSYS"))) {
|
|
|
|
// From CC's firmware
|
|
|
|
scr_printf("Booting as CC firmware\n");
|
|
|
|
boot = B_CC;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Unknown
|
|
|
|
scr_printf("Booting from unrecognized place %s\n", bootPath);
|
|
|
|
boot = B_UNKN;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_CACHED_CFG
|
|
|
|
if(if_conf_len==0)
|
|
|
|
{
|
|
|
|
scr_printf("Initial boot, will load config then reset\n");
|
|
|
|
if(boot == B_MC || boot == B_CC)
|
|
|
|
restartIOP();
|
|
|
|
|
|
|
|
getIpConfig();
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
scr_printf("Using cached config\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// System initalisation
|
|
|
|
#ifndef BUILTIN_IRXS
|
|
|
|
if (boot == B_HOST) {
|
|
|
|
if (loadHostModBuffers() < 0) {
|
|
|
|
dbgscr_printf("Unable to load modules from host:!\n");
|
|
|
|
SleepThread();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
restartIOP();
|
|
|
|
|
|
|
|
// CLEARSPU seems to cause exceptions in the Multi_Thread_Manager module.
|
|
|
|
// I suspect this is caused by the interrupt handlers or some such.
|
|
|
|
/*
|
|
|
|
dbgscr_printf("clearing spu\n");
|
|
|
|
if (SifLoadModule("rom0:CLEARSPU", 0, NULL)<0)
|
|
|
|
{
|
|
|
|
scr_printf("rom0:CLEARSPU failed\n");
|
|
|
|
sio_printf("rom0:CLEARSPU failed\n");
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
// get extra config
|
|
|
|
if(load_extra_conf)
|
|
|
|
{
|
|
|
|
dbgscr_printf("getting extra config\n");
|
|
|
|
getExtraConfig();
|
|
|
|
}
|
|
|
|
|
|
|
|
scr_printf("Ready\n");
|
|
|
|
sio_printf("Ready\n");
|
|
|
|
nprintf("Ready\n");
|
|
|
|
|
|
|
|
const char elfFile[PS2E_FIO_MAX_PATH];
|
|
|
|
|
|
|
|
if(argc<2 || strlen(argv[1]) == 0)
|
|
|
|
{
|
|
|
|
nprintf("No elf specified. Trying PS2E Hack.\n");
|
|
|
|
|
|
|
|
char* params_ptr = (char*)0x1FFFC00;
|
|
|
|
int* params_magic = params_ptr + 0;
|
|
|
|
int* params_argc = params_ptr + 4;
|
|
|
|
char* params_argv = params_ptr + 8;
|
|
|
|
|
|
|
|
nprintf("Magic = %c%c%c%c, argc=%d, argv[0]=%s\n", params_ptr[0], params_ptr[1], params_ptr[2], params_ptr[3], *params_argc, params_argv );
|
|
|
|
|
|
|
|
if(params_ptr[0] == 'E' && params_ptr[1] == '2' && params_ptr[2] == 'S' && params_ptr[3] == 'P')
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
argc = *params_argc;
|
|
|
|
for(i=0;i<=argc;i++)
|
|
|
|
{
|
|
|
|
argv[i] = params_argv;
|
|
|
|
params_argv += strlen(params_argv)+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nprintf("No elf to run. Looping infinitely.\n");
|
|
|
|
for(;;);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(elfFile,"host0:");
|
|
|
|
strcat(elfFile,argv[1]);
|
|
|
|
|
|
|
|
nprintf("Loading elf '%s'...", elfFile);
|
|
|
|
|
|
|
|
pko_pkt_execee_req cmd;
|
|
|
|
|
|
|
|
cmd.argc = 1;
|
|
|
|
strcpy(cmd.argv, elfFile);
|
|
|
|
cmd.argv[strlen(cmd.argv)+1] = 0; // second null char to end argv
|
|
|
|
|
|
|
|
pkoExecEE(&cmd);
|
|
|
|
|
|
|
|
// SleepThread();
|
|
|
|
ExitDeleteThread();
|
|
|
|
return 0;
|
|
|
|
}
|