1 | //--------------------------------------------------------------
|
---|
2 | //File name: loader.c
|
---|
3 | //--------------------------------------------------------------
|
---|
4 | //dlanor: This subprogram has been modified to minimize the code
|
---|
5 | //dlanor: size of the resident loader portion. Some of the parts
|
---|
6 | //dlanor: that were moved into the main program include loading
|
---|
7 | //dlanor: of all IRXs and mounting pfs0: for ELFs on hdd.
|
---|
8 | //dlanor: Another change was to skip threading in favor of ExecPS2
|
---|
9 | /*==================================================================
|
---|
10 | == ==
|
---|
11 | == Copyright(c)2004 Adam Metcalf(gamblore_@hotmail.com) ==
|
---|
12 | == Copyright(c)2004 Thomas Hawcroft(t0mb0la@yahoo.com) ==
|
---|
13 | == This file is subject to terms and conditions shown in the ==
|
---|
14 | == file LICENSE which should be kept in the top folder of ==
|
---|
15 | == this distribution. ==
|
---|
16 | == ==
|
---|
17 | == Portions of this code taken from PS2Link: ==
|
---|
18 | == pkoLoadElf ==
|
---|
19 | == wipeUserMemory ==
|
---|
20 | == (C) 2003 Tord Lindstrom (pukko@home.se) ==
|
---|
21 | == (C) 2003 adresd (adresd_ps2dev@yahoo.com) ==
|
---|
22 | == Portions of this code taken from Independence MC exploit ==
|
---|
23 | == tLoadElf ==
|
---|
24 | == LoadAndRunHDDElf ==
|
---|
25 | == (C) 2003 Marcus Brown <mrbrown@0xd6.org> ==
|
---|
26 | == ==
|
---|
27 | ==================================================================*/
|
---|
28 | #include "tamtypes.h"
|
---|
29 | #include "debug.h"
|
---|
30 | #include "kernel.h"
|
---|
31 | #include "sifrpc.h"
|
---|
32 | #include "loadfile.h"
|
---|
33 | #include "fileio.h"
|
---|
34 | #include "iopcontrol.h"
|
---|
35 | #include "stdarg.h"
|
---|
36 | #include "stdio.h" // Iritscen: added this for printf()
|
---|
37 | #include "string.h"
|
---|
38 | #include "malloc.h"
|
---|
39 | #include "libmc.h"
|
---|
40 | #include "iopheap.h"
|
---|
41 | #include "sys/fcntl.h"
|
---|
42 | #include "sys/stat.h"
|
---|
43 | #include "sys/ioctl.h"
|
---|
44 | #include "fileXio_rpc.h"
|
---|
45 | #include "errno.h"
|
---|
46 | #include "libhdd.h"
|
---|
47 | #include "sbv_patches.h"
|
---|
48 | //--------------------------------------------------------------
|
---|
49 | //#define DEBUG
|
---|
50 | #ifdef DEBUG
|
---|
51 | #define dbgprintf(args...) scr_printf(args)
|
---|
52 | #define dbginit_scr() init_scr()
|
---|
53 | #else
|
---|
54 | #define dbgprintf(args...) do { } while(0)
|
---|
55 | #define dbginit_scr() do { } while(0)
|
---|
56 | #endif
|
---|
57 |
|
---|
58 | // ELF-header structures and identifiers
|
---|
59 | #define ELF_MAGIC 0x464c457f
|
---|
60 | #define ELF_PT_LOAD 1
|
---|
61 |
|
---|
62 | //--------------------------------------------------------------
|
---|
63 | typedef struct
|
---|
64 | {
|
---|
65 | u8 ident[16];
|
---|
66 | u16 type;
|
---|
67 | u16 machine;
|
---|
68 | u32 version;
|
---|
69 | u32 entry;
|
---|
70 | u32 phoff;
|
---|
71 | u32 shoff;
|
---|
72 | u32 flags;
|
---|
73 | u16 ehsize;
|
---|
74 | u16 phentsize;
|
---|
75 | u16 phnum;
|
---|
76 | u16 shentsize;
|
---|
77 | u16 shnum;
|
---|
78 | u16 shstrndx;
|
---|
79 | } elf_header_t;
|
---|
80 | //--------------------------------------------------------------
|
---|
81 | typedef struct
|
---|
82 | {
|
---|
83 | u32 type;
|
---|
84 | u32 offset;
|
---|
85 | void *vaddr;
|
---|
86 | u32 paddr;
|
---|
87 | u32 filesz;
|
---|
88 | u32 memsz;
|
---|
89 | u32 flags;
|
---|
90 | u32 align;
|
---|
91 | } elf_pheader_t;
|
---|
92 | //--------------------------------------------------------------
|
---|
93 | t_ExecData elfdata;
|
---|
94 |
|
---|
95 | int fileMode = FIO_S_IRUSR | FIO_S_IWUSR | FIO_S_IXUSR | FIO_S_IRGRP | FIO_S_IWGRP | FIO_S_IXGRP | FIO_S_IROTH | FIO_S_IWOTH | FIO_S_IXOTH;
|
---|
96 | char HDDpath[256];
|
---|
97 | char partition[128];
|
---|
98 |
|
---|
99 | static int pkoLoadElf(char *path);
|
---|
100 |
|
---|
101 | int userThreadID = 0;
|
---|
102 | ////static char userThreadStack[16*1024] __attribute__((aligned(16)));
|
---|
103 |
|
---|
104 | #define MAX_ARGS 16
|
---|
105 | #define MAX_ARGLEN 256
|
---|
106 |
|
---|
107 | struct argData
|
---|
108 | {
|
---|
109 | int flag; // Contains thread id atm
|
---|
110 | int argc;
|
---|
111 | char *argv[MAX_ARGS];
|
---|
112 | } __attribute__((packed)) userArgs;
|
---|
113 | //--------------------------------------------------------------
|
---|
114 | //End of data declarations
|
---|
115 | //--------------------------------------------------------------
|
---|
116 | //Start of function code:
|
---|
117 | //--------------------------------------------------------------
|
---|
118 | // Read ELF from hard drive to required location(s) in memory.
|
---|
119 | // Modified version of loader from Independence
|
---|
120 | // (C) 2003 Marcus R. Brown <mrbrown@0xd6.org>
|
---|
121 | //--------------------------------------------------------------
|
---|
122 | static int tLoadElf(char *filename)
|
---|
123 | {
|
---|
124 | u8 *boot_elf = (u8 *)0x1800000;
|
---|
125 | elf_header_t *eh = (elf_header_t *)boot_elf;
|
---|
126 | elf_pheader_t *eph;
|
---|
127 |
|
---|
128 | int fd, size, i;
|
---|
129 |
|
---|
130 | //NB: Coming here means pfs0: was mounted correctly earlier
|
---|
131 | if ((fd = fileXioOpen(filename, O_RDONLY, fileMode)) < 0)
|
---|
132 | {
|
---|
133 | dbgprintf("Failed in fileXioOpen %s\n",filename);
|
---|
134 | goto error;
|
---|
135 | }
|
---|
136 | dbgprintf("Opened file %s\n",filename);
|
---|
137 | size = fileXioLseek(fd, 0, SEEK_END);
|
---|
138 | dbgprintf("File size = %i\n",size);
|
---|
139 | if (!size)
|
---|
140 | {
|
---|
141 | dbgprintf("Failed in fileXioLseek\n");
|
---|
142 | fileXioClose(fd);
|
---|
143 | goto error;
|
---|
144 | }
|
---|
145 | fileXioLseek(fd, 0, SEEK_SET);
|
---|
146 | fileXioRead(fd, boot_elf, sizeof(elf_header_t));
|
---|
147 | dbgprintf("Read elf header from file\n");
|
---|
148 | fileXioLseek(fd, eh->phoff, SEEK_SET);
|
---|
149 | eph = (elf_pheader_t *)(boot_elf + eh->phoff);
|
---|
150 | size=eh->phnum*eh->phentsize;
|
---|
151 | size=fileXioRead(fd, (void *)eph, size);
|
---|
152 | dbgprintf("Read %i bytes of program header(s) from file\n",size);
|
---|
153 | for (i = 0; i < eh->phnum; i++)
|
---|
154 | {
|
---|
155 | if (eph[i].type != ELF_PT_LOAD)
|
---|
156 | continue;
|
---|
157 |
|
---|
158 | fileXioLseek(fd, eph[i].offset, SEEK_SET);
|
---|
159 | size=eph[i].filesz;
|
---|
160 | size=fileXioRead(fd, eph[i].vaddr, size);
|
---|
161 | dbgprintf("Read %i bytes to %x\n", size, eph[i].vaddr);
|
---|
162 | if (eph[i].memsz > eph[i].filesz)
|
---|
163 | memset(eph[i].vaddr + eph[i].filesz, 0,
|
---|
164 | eph[i].memsz - eph[i].filesz);
|
---|
165 | }
|
---|
166 |
|
---|
167 | fileXioClose(fd);
|
---|
168 | // fileXioUmount("pfs0:"); We leave the filesystem mounted now for fakehost
|
---|
169 |
|
---|
170 | if (_lw((u32)&eh->ident) != ELF_MAGIC) // this should have already been
|
---|
171 | { // done by menu, but a double-check
|
---|
172 | dbgprintf("Not a recognised ELF.\n"); // doesn't do any harm
|
---|
173 | goto error;
|
---|
174 | }
|
---|
175 |
|
---|
176 | dbgprintf("entry=%x\n",eh->entry);
|
---|
177 | elfdata.epc=eh->entry;
|
---|
178 | return 0;
|
---|
179 | error:
|
---|
180 | elfdata.epc=0;
|
---|
181 | return -1;
|
---|
182 | }
|
---|
183 | //--------------------------------------------------------------
|
---|
184 | //End of func: int tLoadElf(char *filename)
|
---|
185 | //--------------------------------------------------------------
|
---|
186 | // Load the actual elf, and create a thread for it
|
---|
187 | // Return the thread id
|
---|
188 | // PS2Link (C) 2003 Tord Lindstrom (pukko@home.se)
|
---|
189 | // (C) 2003 adresd (adresd_ps2dev@yahoo.com)
|
---|
190 | //--------------------------------------------------------------
|
---|
191 | static int pkoLoadElf(char *path)
|
---|
192 | {
|
---|
193 | ee_thread_t th_attr;
|
---|
194 | int ret=0;
|
---|
195 | int pid;
|
---|
196 |
|
---|
197 | if(!strncmp(path, "host", 4)) ret = SifLoadElf(path, &elfdata);
|
---|
198 | else if(!strncmp(path, "mc", 2)) ret = SifLoadElf(path, &elfdata);
|
---|
199 | else if(!strncmp(path, "cdrom", 5)) ret = SifLoadElf(path, &elfdata);
|
---|
200 | else if(!strncmp(path, "cdfs", 4)) ret = SifLoadElf(path, &elfdata);
|
---|
201 | else if(!strncmp(path, "pfs0", 4)) ret = tLoadElf(path);
|
---|
202 | else if(!strncmp(path, "vmc", 3)) ret = tLoadElf(path);
|
---|
203 | else ret = SifLoadElf(path, &elfdata);
|
---|
204 |
|
---|
205 | FlushCache(0);
|
---|
206 | FlushCache(2);
|
---|
207 |
|
---|
208 | dbgprintf("EE: LoadElf returned %d\n", ret);
|
---|
209 |
|
---|
210 | dbgprintf("EE: Creating user thread (ent: %x, gp: %x, st: %x)\n",
|
---|
211 | elfdata.epc, elfdata.gp, elfdata.sp);
|
---|
212 |
|
---|
213 | if (elfdata.epc == 0) {
|
---|
214 | dbgprintf("EE: Could not load file\n");
|
---|
215 | return -1;
|
---|
216 | }
|
---|
217 |
|
---|
218 | th_attr.func = (void *)elfdata.epc;
|
---|
219 | //// th_attr.stack = userThreadStack;
|
---|
220 | //// th_attr.stack_size = sizeof(userThreadStack);
|
---|
221 | th_attr.gp_reg = (void *)elfdata.gp;
|
---|
222 | th_attr.initial_priority = 64;
|
---|
223 |
|
---|
224 | pid = 1; ////CreateThread(&th_attr);
|
---|
225 | if (pid < 0) {
|
---|
226 | dbgprintf("EE: Create user thread failed %d\n", pid);
|
---|
227 | return -1;
|
---|
228 | }
|
---|
229 | dbgprintf("EE: Created user thread: %d\n", pid);
|
---|
230 |
|
---|
231 | return pid;
|
---|
232 | }
|
---|
233 | //--------------------------------------------------------------
|
---|
234 | //End of func: static int pkoLoadElf(char *path)
|
---|
235 | //--------------------------------------------------------------
|
---|
236 | // Clear user memory
|
---|
237 | // PS2Link (C) 2003 Tord Lindstrom (pukko@home.se)
|
---|
238 | // (C) 2003 adresd (adresd_ps2dev@yahoo.com)
|
---|
239 | //--------------------------------------------------------------
|
---|
240 | void wipeUserMem(void)
|
---|
241 | {
|
---|
242 | int i;
|
---|
243 | for (i = 0x100000; i < 0x2000000 ; i += 64) {
|
---|
244 | asm (
|
---|
245 | "\tsq $0, 0(%0) \n"
|
---|
246 | "\tsq $0, 16(%0) \n"
|
---|
247 | "\tsq $0, 32(%0) \n"
|
---|
248 | "\tsq $0, 48(%0) \n"
|
---|
249 | :: "r" (i) );
|
---|
250 | }
|
---|
251 | }
|
---|
252 | //--------------------------------------------------------------
|
---|
253 | //End of func: void wipeUserMem(void)
|
---|
254 | //--------------------------------------------------------------
|
---|
255 | // C standard strrchr func.. returns pointer to the last occurance of a
|
---|
256 | // character in a string, or NULL if not found
|
---|
257 | // PS2Link (C) 2003 Tord Lindstrom (pukko@home.se)
|
---|
258 | // (C) 2003 adresd (adresd_ps2dev@yahoo.com)
|
---|
259 | //--------------------------------------------------------------
|
---|
260 | char *strrchr(const char *sp, int i)
|
---|
261 | {
|
---|
262 | const char *last = NULL;
|
---|
263 | char c = i;
|
---|
264 |
|
---|
265 | while (*sp)
|
---|
266 | {
|
---|
267 | if (*sp == c)
|
---|
268 | {
|
---|
269 | last = sp;
|
---|
270 | }
|
---|
271 | sp++;
|
---|
272 | }
|
---|
273 |
|
---|
274 | if (*sp == c)
|
---|
275 | {
|
---|
276 | last = sp;
|
---|
277 | }
|
---|
278 |
|
---|
279 | return (char *) last;
|
---|
280 | }
|
---|
281 | //--------------------------------------------------------------
|
---|
282 | //End of func: char *strrchr(const char *sp, int i)
|
---|
283 | //--------------------------------------------------------------
|
---|
284 | // *** MAIN ***
|
---|
285 | //--------------------------------------------------------------
|
---|
286 | int main(int argc, char *argv[])
|
---|
287 | {
|
---|
288 | char s[256],fakepart[128], *ptr;
|
---|
289 | int pid=-1;
|
---|
290 |
|
---|
291 | // Initialize
|
---|
292 | SifInitRpc(0);
|
---|
293 | dbginit_scr();
|
---|
294 | wipeUserMem();
|
---|
295 | dbgprintf("Welcome to Loader of LaunchELF v3.50\nPlease wait...loading.\n");
|
---|
296 |
|
---|
297 | strcpy(s,argv[0]);
|
---|
298 | dbgprintf("argv[0] = %s\n",s);
|
---|
299 | /*if (argc==1) // Iritscen: Commented this out and changed "(argc==2)" to "(argc>=2)" below in order to allow add'l args
|
---|
300 | { // should be two params passed by menu
|
---|
301 | while(1); // leave this here for adding mc0, host or other
|
---|
302 | // to be added in future
|
---|
303 | }*/
|
---|
304 | if (argc>=2) // if call came from hddmenu.elf
|
---|
305 | { // arg1=path to ELF, arg2=partition to mount
|
---|
306 | strcpy(partition,argv[1]);
|
---|
307 | dbgprintf("argv[1] = %s\n", partition);
|
---|
308 | strcpy(HDDpath,s);
|
---|
309 | }
|
---|
310 | dbgprintf("Loading %s\n",HDDpath);
|
---|
311 | pid = pkoLoadElf(HDDpath);
|
---|
312 | dbgprintf("pkoLoadElf returned %i\n",pid);
|
---|
313 | //// if (pid < 0)
|
---|
314 | //// {
|
---|
315 | //// dbgprintf("failed\n");
|
---|
316 | //// dbgprintf("Could not execute file %s\n", HDDpath);
|
---|
317 | //// return -1;
|
---|
318 | //// }
|
---|
319 | if(!strncmp(HDDpath, "pfs0", 4))
|
---|
320 | {
|
---|
321 | strcpy(fakepart,HDDpath);
|
---|
322 | ptr=strrchr(fakepart,'/');
|
---|
323 | if(ptr==NULL) strcpy(fakepart,"pfs0:");
|
---|
324 | else
|
---|
325 | {
|
---|
326 | ptr++;
|
---|
327 | *ptr='\0';
|
---|
328 | }
|
---|
329 | ptr=strrchr(s,'/');
|
---|
330 | if(ptr==NULL) ptr=strrchr(s,':');
|
---|
331 | if(ptr!=NULL)
|
---|
332 | {
|
---|
333 | ptr++;
|
---|
334 | strcpy(HDDpath,"host:");
|
---|
335 | strcat(HDDpath,ptr);
|
---|
336 | }
|
---|
337 | }
|
---|
338 |
|
---|
339 | //// FlushCache(0);
|
---|
340 | //// FlushCache(2);
|
---|
341 |
|
---|
342 | userThreadID = pid;
|
---|
343 |
|
---|
344 | // Iritscen: Copy extra arguments in argv[] to userArgs
|
---|
345 | if (argc > 2)
|
---|
346 | {
|
---|
347 | printf("uLaunchELF loader: Received %d launch argument(s) for the game:\n", argc - 2);
|
---|
348 | userArgs.argc = argc - 1;
|
---|
349 | userArgs.argv[0] = HDDpath;
|
---|
350 | int a;
|
---|
351 | for (a = 0; a < argc - 2; a++)
|
---|
352 | {
|
---|
353 | userArgs.argv[a + 1] = argv[a + 2];
|
---|
354 | printf(" %s\n", argv[a + 2]);
|
---|
355 | }
|
---|
356 | }
|
---|
357 | userArgs.flag = (int)&userThreadID;
|
---|
358 |
|
---|
359 | //// ret = StartThread(userThreadID, &userArgs);
|
---|
360 | //// if (ret < 0)
|
---|
361 | //// {
|
---|
362 | //// dbgprintf("failed\n");
|
---|
363 | //// dbgprintf("EE: Start user thread failed %d\n", ret);
|
---|
364 | //// DeleteThread(userThreadID);
|
---|
365 | //// return -1;
|
---|
366 | //// }
|
---|
367 | //// SleepThread();
|
---|
368 |
|
---|
369 | __asm__ __volatile__(
|
---|
370 | ".set noreorder\n\t"
|
---|
371 | "jal FlushCache\n\t"
|
---|
372 | "li $a0, 0\n\t"
|
---|
373 | "jal FlushCache\n\t"
|
---|
374 | "li $a0, 2\n\t"
|
---|
375 | "lui $sp, 0x000a\n\t"
|
---|
376 | "nop\n\t"
|
---|
377 | "addiu $sp, $sp, 0x8000\n\t"
|
---|
378 | "nop\n\t"
|
---|
379 | ".set reorder\n\t"
|
---|
380 | );
|
---|
381 | ExecPS2((void *)elfdata.epc, (void *)elfdata.gp, userArgs.argc, userArgs.argv);
|
---|
382 | return 0;
|
---|
383 | }
|
---|
384 | //--------------------------------------------------------------
|
---|
385 | //End of func: int main(int argc, char *argv[])
|
---|
386 | //--------------------------------------------------------------
|
---|
387 | //End of file: loader.c
|
---|
388 | //--------------------------------------------------------------
|
---|