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 |
//-------------------------------------------------------------- |