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