[1101] | 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 | //--------------------------------------------------------------
|
---|