//-------------------------------------------------------------- //File name: elf.c //-------------------------------------------------------------- #include "launchelf.h" unsigned char *elfLoaderLoadFile(char *path); // Iritscen: Modeled this on config.c's loadConfig() #define MAX_PATH 1025 extern u8 *loader_elf; extern int size_loader_elf; extern u8 *fakehost_irx; extern int size_fakehost_irx; extern char LaunchElfDir[MAX_PATH]; // Iritscen: "extern"ed from main.c // ELF-loading stuff #define ELF_MAGIC 0x464c457f #define ELF_PT_LOAD 1 //------------------------------ typedef struct { u8 ident[16]; // struct definition for ELF object header u16 type; u16 machine; u32 version; u32 entry; u32 phoff; u32 shoff; u32 flags; u16 ehsize; u16 phentsize; u16 phnum; u16 shentsize; u16 shnum; u16 shstrndx; } elf_header_t; //------------------------------ typedef struct { u32 type; // struct definition for ELF program section header u32 offset; void *vaddr; u32 paddr; u32 filesz; u32 memsz; u32 flags; u32 align; } elf_pheader_t; //-------------------------------------------------------------- //End of data declarations //-------------------------------------------------------------- //Start of function code //-------------------------------------------------------------- // checkELFheader Tests for valid ELF file // Modified version of loader from Independence // (C) 2003 Marcus R. Brown //-------------------------------------------------------------- int checkELFheader(char *path) { elf_header_t elf_head; u8 *boot_elf = (u8 *) &elf_head; elf_header_t *eh = (elf_header_t *) boot_elf; int fd, size=0, ret; char fullpath[MAX_PATH], tmp[MAX_PATH], *p; strcpy(fullpath,path); if( !strncmp(fullpath, "mc", 2) ||!strncmp(fullpath, "vmc", 3) ||!strncmp(fullpath, "rom", 3) ||!strncmp(fullpath, "cdrom", 5) ||!strncmp(fullpath, "cdfs", 4) ){; //fullpath is already correct }else if(!strncmp(fullpath, "hdd0:", 5)) { p = &path[5]; if(*p == '/') p++; sprintf(tmp, "hdd0:%s", p); p = strchr(tmp, '/'); sprintf(fullpath, "pfs0:%s", p); *p = 0; if( (ret = mountParty(tmp)) < 0) goto error; fullpath[3] += ret; }else if(!strncmp(fullpath, "mass", 4)){ char *pathSep; pathSep = strchr(path, '/'); if(pathSep && (pathSep-path<7) && pathSep[-1]==':') strcpy(fullpath+(pathSep-path), pathSep+1); }else if(!strncmp(fullpath, "host:", 5)){ if(path[5] == '/') strcpy(fullpath+5, path+6); } else { return 0; //return 0 for unrecognized device } if ((fd = genOpen(fullpath, O_RDONLY)) < 0) goto error; size = genLseek(fd, 0, SEEK_END); if (!size){ genClose(fd); goto error; } genLseek(fd, 0, SEEK_SET); genRead(fd, boot_elf, sizeof(elf_header_t)); genClose(fd); if ((_lw((u32)&eh->ident) != ELF_MAGIC) || eh->type != 2) goto error; return 1; //return 1 for successful check error: return -1; //return -1 for failed check } //------------------------------ //End of func: int checkELFheader(const char *path) //-------------------------------------------------------------- // RunLoaderElf loads LOADER.ELF from program memory and passes // args of selected ELF and partition to it // Modified version of loader from Independence // (C) 2003 Marcus R. Brown //------------------------------ void RunLoaderElf(char *filename, char *party) { u8 *boot_elf; elf_header_t *eh; elf_pheader_t *eph; void *pdata; int ret, i; int argc; // Iritscen: Added to allow add'l args char *argv[16/*MAX_ARGS*/]; // Iritscen: Changed from "2" to allow add'l args if((!strncmp(party, "hdd0:", 5)) && (!strncmp(filename, "pfs0:", 5))){ char fakepath[128], *p; if(0 > fileXioMount("pfs0:", party, FIO_MT_RDONLY)){ //Some error occurred, it could be due to something else having used pfs0 unmountParty(0); //So we try unmounting pfs0, to try again if(0 > fileXioMount("pfs0:", party, FIO_MT_RDONLY)) return; //If it still fails, we have to give up... } strcpy(fakepath,filename); p=strrchr(fakepath,'/'); if(p==NULL) strcpy(fakepath,"pfs0:"); else { p++; *p='\0'; } //printf("Loading fakehost.irx %i bytes\n", size_fakehost_irx); //printf("Faking for path \"%s\" on partition \"%s\"\n", fakepath, party); SifExecModuleBuffer(&fakehost_irx, size_fakehost_irx, strlen(fakepath), fakepath, &ret); } /* NB: LOADER.ELF is embedded */ boot_elf = (u8 *)&loader_elf; eh = (elf_header_t *)boot_elf; if (_lw((u32)&eh->ident) != ELF_MAGIC) while (1); eph = (elf_pheader_t *)(boot_elf + eh->phoff); /* Scan through the ELF's program headers and copy them into RAM, then zero out any non-loaded regions. */ for (i = 0; i < eh->phnum; i++) { if (eph[i].type != ELF_PT_LOAD) continue; pdata = (void *)(boot_elf + eph[i].offset); memcpy(eph[i].vaddr, pdata, eph[i].filesz); if (eph[i].memsz > eph[i].filesz) memset(eph[i].vaddr + eph[i].filesz, 0, eph[i].memsz - eph[i].filesz); } /* Let's go. */ fioExit(); SifInitRpc(0); SifExitRpc(); FlushCache(0); FlushCache(2); argv[0] = filename; argv[1] = party; argc = 2; // Iritscen: Load launch args from file char txtPath[MAX_PATH]; strcpy(txtPath, LaunchElfDir); // a path like "host:C:/Users/Home/pcsx2/uLaunchELF/" strcat(txtPath, "LaunchArgs.txt"); printf("uLaunchELF: Attempting to open %s...\n", txtPath); unsigned char *argsTxt = elfLoaderLoadFile(txtPath); if (argsTxt != NULL) { int argsRead = 0; unsigned char *lineStart = argsTxt, *scanner = lineStart; while (*lineStart != '\0' && argsRead < 16 /*MAX_ARGS*/) { // Find end of line and copy line to an argv[] element while (*scanner != '\r' && *scanner != '\n' && *scanner != '\0') scanner++; int length = scanner - lineStart; argv[argsRead + 2] = malloc(length + 1); strncpy(argv[argsRead + 2], lineStart, length); argv[argsRead + 2][length] = '\0'; printf("Got argument %s.\n", argv[argsRead + 2]); // Advance to next line while (*scanner == '\r' || *scanner == '\n') scanner++; lineStart = scanner; argsRead++; } argc += argsRead; printf("uLaunchELF: Passing %d argument(s) to the loader for the game:\n", argsRead); int a; for (a = 0; a < argsRead; a++) printf(" arg %d: %s\n", a + 1, argv[a + 2]); } else printf("uLaunchELF: Could not load LaunchArgs.txt from disk!\n"); ExecPS2((void *)eh->entry, 0, argc, argv); } //------------------------------ //End of func: void RunLoaderElf(char *filename, char *party) //-------------------------------------------------------------- // Iritscen: Modeled this on config.c's loadConfig() unsigned char *elfLoaderLoadFile(char *path) { int fd = -1, tst; size_t fileSize; char filePath[MAX_PATH]; unsigned char *RAM_p; if ((tst = genFixPath(path, filePath)) >= 0) fd = genOpen(filePath, O_RDONLY); if (fd < 0) { failed_load: return NULL; } fileSize = genLseek(fd, 0, SEEK_END); printf("fileSize=%d\n", fileSize); genLseek(fd, 0, SEEK_SET); RAM_p = (char*)malloc(fileSize); if (RAM_p == NULL) { genClose(fd); goto failed_load; } genRead(fd, RAM_p, fileSize); // read file as one long string genClose(fd); RAM_p[fileSize] = '\0'; // terminate the file contents string return RAM_p; } //-------------------------------------------------------------- //End of file: elf.c //--------------------------------------------------------------