| 1 |
//-------------------------------------------------------------- |
| 2 |
//File name: elf.c |
| 3 |
//-------------------------------------------------------------- |
| 4 |
#include "launchelf.h" |
| 5 |
|
| 6 |
unsigned char *elfLoaderLoadFile(char *path); // Iritscen: Modeled this on config.c's loadConfig() |
| 7 |
|
| 8 |
#define MAX_PATH 1025 |
| 9 |
|
| 10 |
extern u8 *loader_elf; |
| 11 |
extern int size_loader_elf; |
| 12 |
extern u8 *fakehost_irx; |
| 13 |
extern int size_fakehost_irx; |
| 14 |
extern char LaunchElfDir[MAX_PATH]; // Iritscen: "extern"ed from main.c |
| 15 |
|
| 16 |
// ELF-loading stuff |
| 17 |
#define ELF_MAGIC 0x464c457f |
| 18 |
#define ELF_PT_LOAD 1 |
| 19 |
|
| 20 |
//------------------------------ |
| 21 |
typedef struct |
| 22 |
{ |
| 23 |
u8 ident[16]; // struct definition for ELF object header |
| 24 |
u16 type; |
| 25 |
u16 machine; |
| 26 |
u32 version; |
| 27 |
u32 entry; |
| 28 |
u32 phoff; |
| 29 |
u32 shoff; |
| 30 |
u32 flags; |
| 31 |
u16 ehsize; |
| 32 |
u16 phentsize; |
| 33 |
u16 phnum; |
| 34 |
u16 shentsize; |
| 35 |
u16 shnum; |
| 36 |
u16 shstrndx; |
| 37 |
} elf_header_t; |
| 38 |
//------------------------------ |
| 39 |
typedef struct |
| 40 |
{ |
| 41 |
u32 type; // struct definition for ELF program section header |
| 42 |
u32 offset; |
| 43 |
void *vaddr; |
| 44 |
u32 paddr; |
| 45 |
u32 filesz; |
| 46 |
u32 memsz; |
| 47 |
u32 flags; |
| 48 |
u32 align; |
| 49 |
} elf_pheader_t; |
| 50 |
//-------------------------------------------------------------- |
| 51 |
//End of data declarations |
| 52 |
//-------------------------------------------------------------- |
| 53 |
//Start of function code |
| 54 |
//-------------------------------------------------------------- |
| 55 |
// checkELFheader Tests for valid ELF file |
| 56 |
// Modified version of loader from Independence |
| 57 |
// (C) 2003 Marcus R. Brown <mrbrown@0xd6.org> |
| 58 |
//-------------------------------------------------------------- |
| 59 |
int checkELFheader(char *path) |
| 60 |
{ |
| 61 |
elf_header_t elf_head; |
| 62 |
u8 *boot_elf = (u8 *) &elf_head; |
| 63 |
elf_header_t *eh = (elf_header_t *) boot_elf; |
| 64 |
int fd, size=0, ret; |
| 65 |
char fullpath[MAX_PATH], tmp[MAX_PATH], *p; |
| 66 |
|
| 67 |
strcpy(fullpath,path); |
| 68 |
if( !strncmp(fullpath, "mc", 2) |
| 69 |
||!strncmp(fullpath, "vmc", 3) |
| 70 |
||!strncmp(fullpath, "rom", 3) |
| 71 |
||!strncmp(fullpath, "cdrom", 5) |
| 72 |
||!strncmp(fullpath, "cdfs", 4) |
| 73 |
){; //fullpath is already correct |
| 74 |
}else if(!strncmp(fullpath, "hdd0:", 5)) { |
| 75 |
p = &path[5]; |
| 76 |
if(*p == '/') |
| 77 |
p++; |
| 78 |
sprintf(tmp, "hdd0:%s", p); |
| 79 |
p = strchr(tmp, '/'); |
| 80 |
sprintf(fullpath, "pfs0:%s", p); |
| 81 |
*p = 0; |
| 82 |
if( (ret = mountParty(tmp)) < 0) |
| 83 |
goto error; |
| 84 |
fullpath[3] += ret; |
| 85 |
}else if(!strncmp(fullpath, "mass", 4)){ |
| 86 |
char *pathSep; |
| 87 |
|
| 88 |
pathSep = strchr(path, '/'); |
| 89 |
if(pathSep && (pathSep-path<7) && pathSep[-1]==':') |
| 90 |
strcpy(fullpath+(pathSep-path), pathSep+1); |
| 91 |
}else if(!strncmp(fullpath, "host:", 5)){ |
| 92 |
if(path[5] == '/') |
| 93 |
strcpy(fullpath+5, path+6); |
| 94 |
} else { |
| 95 |
return 0; //return 0 for unrecognized device |
| 96 |
} |
| 97 |
if ((fd = genOpen(fullpath, O_RDONLY)) < 0) |
| 98 |
goto error; |
| 99 |
size = genLseek(fd, 0, SEEK_END); |
| 100 |
if (!size){ |
| 101 |
genClose(fd); |
| 102 |
goto error; |
| 103 |
} |
| 104 |
genLseek(fd, 0, SEEK_SET); |
| 105 |
genRead(fd, boot_elf, sizeof(elf_header_t)); |
| 106 |
genClose(fd); |
| 107 |
|
| 108 |
if ((_lw((u32)&eh->ident) != ELF_MAGIC) || eh->type != 2) |
| 109 |
goto error; |
| 110 |
|
| 111 |
return 1; //return 1 for successful check |
| 112 |
error: |
| 113 |
return -1; //return -1 for failed check |
| 114 |
} |
| 115 |
//------------------------------ |
| 116 |
//End of func: int checkELFheader(const char *path) |
| 117 |
//-------------------------------------------------------------- |
| 118 |
// RunLoaderElf loads LOADER.ELF from program memory and passes |
| 119 |
// args of selected ELF and partition to it |
| 120 |
// Modified version of loader from Independence |
| 121 |
// (C) 2003 Marcus R. Brown <mrbrown@0xd6.org> |
| 122 |
//------------------------------ |
| 123 |
void RunLoaderElf(char *filename, char *party) |
| 124 |
{ |
| 125 |
u8 *boot_elf; |
| 126 |
elf_header_t *eh; |
| 127 |
elf_pheader_t *eph; |
| 128 |
void *pdata; |
| 129 |
int ret, i; |
| 130 |
int argc; // Iritscen: Added to allow add'l args |
| 131 |
char *argv[16/*MAX_ARGS*/]; // Iritscen: Changed from "2" to allow add'l args |
| 132 |
|
| 133 |
if((!strncmp(party, "hdd0:", 5)) && (!strncmp(filename, "pfs0:", 5))){ |
| 134 |
char fakepath[128], *p; |
| 135 |
if(0 > fileXioMount("pfs0:", party, FIO_MT_RDONLY)){ |
| 136 |
//Some error occurred, it could be due to something else having used pfs0 |
| 137 |
unmountParty(0); //So we try unmounting pfs0, to try again |
| 138 |
if(0 > fileXioMount("pfs0:", party, FIO_MT_RDONLY)) |
| 139 |
return; //If it still fails, we have to give up... |
| 140 |
} |
| 141 |
strcpy(fakepath,filename); |
| 142 |
p=strrchr(fakepath,'/'); |
| 143 |
if(p==NULL) strcpy(fakepath,"pfs0:"); |
| 144 |
else |
| 145 |
{ |
| 146 |
p++; |
| 147 |
*p='\0'; |
| 148 |
} |
| 149 |
//printf("Loading fakehost.irx %i bytes\n", size_fakehost_irx); |
| 150 |
//printf("Faking for path \"%s\" on partition \"%s\"\n", fakepath, party); |
| 151 |
SifExecModuleBuffer(&fakehost_irx, size_fakehost_irx, strlen(fakepath), fakepath, &ret); |
| 152 |
|
| 153 |
} |
| 154 |
|
| 155 |
/* NB: LOADER.ELF is embedded */ |
| 156 |
boot_elf = (u8 *)&loader_elf; |
| 157 |
eh = (elf_header_t *)boot_elf; |
| 158 |
if (_lw((u32)&eh->ident) != ELF_MAGIC) |
| 159 |
while (1); |
| 160 |
|
| 161 |
eph = (elf_pheader_t *)(boot_elf + eh->phoff); |
| 162 |
|
| 163 |
/* Scan through the ELF's program headers and copy them into RAM, then |
| 164 |
zero out any non-loaded regions. */ |
| 165 |
for (i = 0; i < eh->phnum; i++) |
| 166 |
{ |
| 167 |
if (eph[i].type != ELF_PT_LOAD) |
| 168 |
continue; |
| 169 |
|
| 170 |
pdata = (void *)(boot_elf + eph[i].offset); |
| 171 |
memcpy(eph[i].vaddr, pdata, eph[i].filesz); |
| 172 |
|
| 173 |
if (eph[i].memsz > eph[i].filesz) |
| 174 |
memset(eph[i].vaddr + eph[i].filesz, 0, |
| 175 |
eph[i].memsz - eph[i].filesz); |
| 176 |
} |
| 177 |
|
| 178 |
/* Let's go. */ |
| 179 |
fioExit(); |
| 180 |
SifInitRpc(0); |
| 181 |
SifExitRpc(); |
| 182 |
FlushCache(0); |
| 183 |
FlushCache(2); |
| 184 |
|
| 185 |
argv[0] = filename; |
| 186 |
argv[1] = party; |
| 187 |
argc = 2; |
| 188 |
|
| 189 |
// Iritscen: Load launch args from file |
| 190 |
char txtPath[MAX_PATH]; |
| 191 |
strcpy(txtPath, LaunchElfDir); // a path like "host:C:/Users/Home/pcsx2/uLaunchELF/" |
| 192 |
strcat(txtPath, "LaunchArgs.txt"); |
| 193 |
printf("uLaunchELF: Attempting to open %s...\n", txtPath); |
| 194 |
unsigned char *argsTxt = elfLoaderLoadFile(txtPath); |
| 195 |
if (argsTxt != NULL) |
| 196 |
{ |
| 197 |
int argsRead = 0; |
| 198 |
unsigned char *lineStart = argsTxt, *scanner = lineStart; |
| 199 |
while (*lineStart != '\0' && argsRead < 16 /*MAX_ARGS*/) |
| 200 |
{ |
| 201 |
// Find end of line and copy line to an argv[] element |
| 202 |
while (*scanner != '\r' && *scanner != '\n' && *scanner != '\0') |
| 203 |
scanner++; |
| 204 |
int length = scanner - lineStart; |
| 205 |
argv[argsRead + 2] = malloc(length + 1); |
| 206 |
strncpy(argv[argsRead + 2], lineStart, length); |
| 207 |
argv[argsRead + 2][length] = '\0'; |
| 208 |
printf("Got argument %s.\n", argv[argsRead + 2]); |
| 209 |
|
| 210 |
// Advance to next line |
| 211 |
while (*scanner == '\r' || *scanner == '\n') |
| 212 |
scanner++; |
| 213 |
lineStart = scanner; |
| 214 |
argsRead++; |
| 215 |
} |
| 216 |
|
| 217 |
argc += argsRead; |
| 218 |
printf("uLaunchELF: Passing %d argument(s) to the loader for the game:\n", argsRead); |
| 219 |
int a; |
| 220 |
for (a = 0; a < argsRead; a++) |
| 221 |
printf(" arg %d: %s\n", a + 1, argv[a + 2]); |
| 222 |
} |
| 223 |
else |
| 224 |
printf("uLaunchELF: Could not load LaunchArgs.txt from disk!\n"); |
| 225 |
|
| 226 |
ExecPS2((void *)eh->entry, 0, argc, argv); |
| 227 |
} |
| 228 |
//------------------------------ |
| 229 |
//End of func: void RunLoaderElf(char *filename, char *party) |
| 230 |
//-------------------------------------------------------------- |
| 231 |
// Iritscen: Modeled this on config.c's loadConfig() |
| 232 |
unsigned char *elfLoaderLoadFile(char *path) |
| 233 |
{ |
| 234 |
int fd = -1, tst; |
| 235 |
size_t fileSize; |
| 236 |
char filePath[MAX_PATH]; |
| 237 |
unsigned char *RAM_p; |
| 238 |
|
| 239 |
if ((tst = genFixPath(path, filePath)) >= 0) |
| 240 |
fd = genOpen(filePath, O_RDONLY); |
| 241 |
|
| 242 |
if (fd < 0) |
| 243 |
{ |
| 244 |
failed_load: |
| 245 |
return NULL; |
| 246 |
} |
| 247 |
fileSize = genLseek(fd, 0, SEEK_END); |
| 248 |
printf("fileSize=%d\n", fileSize); |
| 249 |
genLseek(fd, 0, SEEK_SET); |
| 250 |
RAM_p = (char*)malloc(fileSize); |
| 251 |
if (RAM_p == NULL) |
| 252 |
{ |
| 253 |
genClose(fd); |
| 254 |
goto failed_load; |
| 255 |
} |
| 256 |
|
| 257 |
genRead(fd, RAM_p, fileSize); // read file as one long string |
| 258 |
genClose(fd); |
| 259 |
RAM_p[fileSize] = '\0'; // terminate the file contents string |
| 260 |
return RAM_p; |
| 261 |
} |
| 262 |
//-------------------------------------------------------------- |
| 263 |
//End of file: elf.c |
| 264 |
//-------------------------------------------------------------- |