source: ps2launchargs/source/uLaunchELF/loader/loader.c

Last change on this file was 1101, checked in by iritscen, 7 years ago

Added following to ps2launchargs:\n-Source code.\n-DLL needed to run ps2client.\n-Instructions for building uLaunchELF.

  • Property svn:executable set to *
File size: 11.2 KB
Line 
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//--------------------------------------------------------------
63typedef 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//--------------------------------------------------------------
81typedef 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//--------------------------------------------------------------
93t_ExecData elfdata;
94
95int 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;
96char HDDpath[256];
97char partition[128];
98
99static int pkoLoadElf(char *path);
100
101int userThreadID = 0;
102////static char userThreadStack[16*1024] __attribute__((aligned(16)));
103
104#define MAX_ARGS 16
105#define MAX_ARGLEN 256
106
107struct 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//--------------------------------------------------------------
122static 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;
179error:
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//--------------------------------------------------------------
191static 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//--------------------------------------------------------------
240void 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//--------------------------------------------------------------
260char *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//--------------------------------------------------------------
286int 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//--------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.