int main(int argc, char **argv) { // Exit after 10 seconds if there is an error __exception_setreload(10); CheckForGecko(); DCInvalidateRange(loader_stub, 0x1800); memcpy(loader_stub, (void*)0x80001800, 0x1800); DCFlushRange(loader_stub, 0x1800); if( !IsWiiU() ) { gprintf("Nintendont Loader\r\n"); gprintf("Built : %s %s\r\n", __DATE__, __TIME__ ); gprintf("Version : %d.%d\r\n", NIN_VERSION>>16, NIN_VERSION&0xFFFF ); }
int gprintf( const char *str, ... ) { if( IsWiiU() ) { if(wiiu_done == true) return 0; // We're running on a vWii, log the results to a file // Open the file if it hasn't been already if (nl_log == NULL) { char LogPath[20]; sprintf(LogPath, "%s:/nloader.log", GetRootDevice()); nl_log = fopen(LogPath, "w"); } if (nl_log != NULL) { va_list ap; va_start(ap,str); vfprintf(nl_log, str, ap); // No need for a buffer, goes straight to the file // Flushes the stream so we don't have to wait for the file to close or it to fill fflush(nl_log); va_end(ap); } else { return -1; // Couldn't open the file } } else { // We're running on a real Wii, send the results to a USB Gecko if(!GeckoFound) return 0; // No USB Gecko found char astr[4096] = {0}; va_list ap; va_start(ap,str); vsnprintf(astr, sizeof(astr), str, ap); va_end(ap); int i = 0; while( astr[i] != '\0' ) { EXISendByte( astr[i] ); ++i; } } return 1; // Everything went okay }
void ConfigInit( void ) { FIL cfg; u32 read; dbgprintf("CFGInit()\r\n"); ConfigSyncBeforeRead(); if (ncfg->Magicbytes != 0x01070CF6) { dbgprintf("Cfg not in memory, trying file\r\n"); if (f_open_char(&cfg, "/nincfg.bin", FA_OPEN_EXISTING | FA_READ) != FR_OK) { dbgprintf("CFG:Failed to open config\r\n"); Shutdown(); } f_read( &cfg, ncfg, sizeof(NIN_CFG), &read ); sync_after_write(ncfg, sizeof(NIN_CFG)); f_close( &cfg ); if( read != sizeof(NIN_CFG) ) { dbgprintf("CFG:Failed to read config\r\n"); Shutdown(); } ConfigSyncBeforeRead(); } if( IsWiiU() ) { //ncfg->Config |= NIN_CFG_HID; ncfg->MaxPads = 0; // Disable debugging and the drive access LED. ncfg->Config &= ~(NIN_CFG_DEBUGGER | NIN_CFG_DEBUGWAIT | NIN_CFG_LED); } //if( (read32(0) >> 8) == 0x47504F ) // PSO 1&2 disable cheats/debugging //{ // ncfg->Config &= ~(NIN_CFG_CHEATS|NIN_CFG_DEBUGGER|NIN_CFG_DEBUGWAIT); //} }
void InsertModule( char *Module, u32 ModuleSize ) { u32 loadersize = *(vu32*)(Kernel) + *(vu32*)(Kernel+4); u32 PatchCount = 0; int i = 0, j = 0; #ifdef DEBUG_MODULE_PATCH gprintf("LoaderSize:%08X\r\n", loadersize ); #endif if( loadersize == 0 ) return; if( loadersize > 0x1000 ) return; Elf32_Ehdr *inhdr = (Elf32_Ehdr*)(Kernel+loadersize); unsigned int size = KernelSize; char *buf = Kernel; Elf32_Ehdr *outhdr = (Elf32_Ehdr *)(buf+loadersize); // set new ES thread entry point *(volatile unsigned int*)(buf+loadersize+0x254) = 0x20F00000; // Update ES stack address *(volatile unsigned int*)(buf+loadersize+0x264) = 0x2000; //size *(volatile unsigned int*)(buf+loadersize+0x26C) = 0x2010F000; #ifdef DEBUG_MODULE_PATCH gprintf("PHeaders:%d\r\n", inhdr->e_phnum ); gprintf("PHOffset:%d\r\n", inhdr->e_phoff ); #endif if( inhdr->e_phnum == 0 ) { #ifdef DEBUG_MODULE_PATCH gprintf("Error program header entries are zero!\r\n"); #endif } else { for( i=0; i < inhdr->e_phnum; ++i ) { Elf32_Phdr *phdr = (Elf32_Phdr*)( Module + inhdr->e_phoff + sizeof( Elf32_Phdr ) * i ); if( (phdr->p_vaddr & 0xF0000000) == 0x20000000 ) { #ifdef DEBUG_MODULE_PATCH gprintf("Type:%X Offset:%08X VAdr:%08X PAdr:%08X FSz:%08X MSz:%08X\r\n", (phdr->p_type), (phdr->p_offset), (phdr->p_vaddr), (phdr->p_paddr), (phdr->p_filesz), (phdr->p_memsz) ); #endif if( (phdr->p_filesz) > 100*1024*1024 ) continue; //Look for entry for(j=0; j < (outhdr->e_phnum); ++j ) { Elf32_Phdr *ophdr = (Elf32_Phdr *)( buf + loadersize + j*sizeof(Elf32_Phdr) + (outhdr->e_phoff) ); if( (ophdr->p_vaddr) == 0x20100000 && (phdr->p_vaddr) == 0x20F00000 ) { #ifdef DEBUG_MODULE_PATCH gprintf(" O:Type:%X Offset:%08X VAdr:%08X PAdr:%08X FSz:%08X MSz:%08X\r\n", (ophdr->p_type), (ophdr->p_offset), (ophdr->p_vaddr), (ophdr->p_paddr), (ophdr->p_filesz), (ophdr->p_memsz) ); #endif ophdr->p_vaddr = phdr->p_vaddr; ophdr->p_paddr = phdr->p_paddr; ophdr->p_filesz = phdr->p_filesz; ophdr->p_memsz = phdr->p_filesz; ophdr->p_offset = ( size - loadersize ); size += (phdr->p_filesz); *(unsigned int*)(buf+8) = ( (*(unsigned int*)(buf+8)) + (phdr->p_filesz) ); memcpy( buf+loadersize+(ophdr->p_offset), (char*)(Module+phdr->p_offset), phdr->p_filesz ); #ifdef DEBUG_MODULE_PATCH gprintf(" N:Type:%X Offset:%08X VAdr:%08X PAdr:%08X FSz:%08X MSz:%08X\r\n", (ophdr->p_type), (ophdr->p_offset), (ophdr->p_vaddr), (ophdr->p_paddr), (ophdr->p_filesz), (ophdr->p_memsz) ); #endif break; } else if( (ophdr->p_vaddr) == 0x2010D000 && (phdr->p_vaddr) == 0x20F28000 ) { #ifdef DEBUG_MODULE_PATCH gprintf(" O:Type:%X Offset:%08X VAdr:%08X PAdr:%08X FSz:%08X MSz:%08X\r\n", (ophdr->p_type), (ophdr->p_offset), (ophdr->p_vaddr), (ophdr->p_paddr), (ophdr->p_filesz), (ophdr->p_memsz) ); #endif ophdr->p_vaddr = phdr->p_vaddr; ophdr->p_paddr = phdr->p_paddr; // is not set correctly because of BSS, meaning the VMA isnt set up to the actually used point ophdr->p_filesz = 0x58000; ophdr->p_memsz = 0x58000; ophdr->p_offset = ( size - loadersize ); size += (phdr->p_filesz); *(unsigned int*)(buf+8) = ( (*(unsigned int*)(buf+8)) + (phdr->p_filesz) ); memcpy( buf+loadersize+(ophdr->p_offset), (char*)(Module+phdr->p_offset), phdr->p_filesz ); #ifdef DEBUG_MODULE_PATCH gprintf(" N:Type:%X Offset:%08X VAdr:%08X PAdr:%08X FSz:%08X MSz:%08X\r\n", (ophdr->p_type), (ophdr->p_offset), (ophdr->p_vaddr), (ophdr->p_paddr), (ophdr->p_filesz), (ophdr->p_memsz) ); #endif break; } else if( (ophdr->p_vaddr) == 0x2010E000 && (phdr->p_vaddr) == 0x20106000 ) { #ifdef DEBUG_MODULE_PATCH gprintf(" O:Type:%X Offset:%08X VAdr:%08X PAdr:%08X FSz:%08X MSz:%08X\r\n", (ophdr->p_type), (ophdr->p_offset), (ophdr->p_vaddr), (ophdr->p_paddr), (ophdr->p_filesz), (ophdr->p_memsz) ); #endif ophdr->p_vaddr = phdr->p_vaddr; ophdr->p_paddr = phdr->p_paddr; ophdr->p_memsz = 0x9000; memcpy( buf+loadersize+(ophdr->p_offset), (char*)(Module+phdr->p_offset), phdr->p_filesz ); #ifdef DEBUG_MODULE_PATCH gprintf(" N:Type:%X Offset:%08X VAdr:%08X PAdr:%08X FSz:%08X MSz:%08X\r\n", (ophdr->p_type), (ophdr->p_offset), (ophdr->p_vaddr), (ophdr->p_paddr), (ophdr->p_filesz), (ophdr->p_memsz) ); #endif goto done; } } } } } done: for( i=0; i < size; i+=4 ) { if( !IsWiiU() ) { if( memcmp( buf+i, UnusedSWI, sizeof(UnusedSWI) ) == 0 ) { #ifdef DEBUG_MODULE_PATCH gprintf("Found Unused SWI at %08X\r\n", i ); #endif memcpy( buf+i, EXISendBuffer, sizeof( EXISendBuffer ) ); PatchCount |= 1; } if( memcmp( buf+i, swi_v80, sizeof(swi_v80) ) == 0 ) { #ifdef DEBUG_MODULE_PATCH gprintf("Found SWI at %08X\r\n", i ); #endif memcpy( buf+i, swipatch_v80, sizeof( swipatch_v80 ) ); PatchCount |= 2; } } if( memcmp( buf+i, HWAccess_ES, sizeof(HWAccess_ES) ) == 0 ) { #ifdef DEBUG_MODULE_PATCH gprintf("Found HWAccess_ES at %08X\r\n", i ); #endif memcpy( buf+i, HWAccess_ESPatch, sizeof( HWAccess_ESPatch ) ); PatchCount |= 4; } if( IsWiiU() ) { if( PatchCount == 4 ) break; } else { if( PatchCount == 7 ) break; } } DCFlushRange(Kernel, KernelSize); }
void CheckForGecko( void ) { if( !IsWiiU() ) GeckoFound = usb_isgeckoalive( 1 ); }