diff --git a/source/fileops.c b/source/fileops.c index 785fff3..acca2cb 100644 --- a/source/fileops.c +++ b/source/fileops.c @@ -1,9 +1,8 @@ #include -#include #include #include "fileops.h" - +#include "malloc.h" bool FSOPFileExists(const char* file) { @@ -85,7 +84,7 @@ s32 FSOPReadOpenFile(FILE* fp, void* buffer, u32 offset, u32 length) s32 FSOPReadOpenFileA(FILE* fp, void** buffer, u32 offset, u32 length) { - *buffer = memalign(32, length); + *buffer = memalign32(length); if (!*buffer) return -1; diff --git a/source/malloc.h b/source/malloc.h new file mode 100644 index 0000000..8a12a83 --- /dev/null +++ b/source/malloc.h @@ -0,0 +1,11 @@ +#include + +static inline void *memalign32(size_t size) +{ + return aligned_alloc(0x20, (size + 0x1F) & ~0x1F); +} + +static inline void *memalign64(size_t size) +{ + return aligned_alloc(0x40, (size + 0x3F) & ~0x3F); +} \ No newline at end of file diff --git a/source/nand.c b/source/nand.c index 57e4aa2..bba65ea 100644 --- a/source/nand.c +++ b/source/nand.c @@ -1,10 +1,10 @@ #include #include #include -#include #include #include "nand.h" +#include "malloc.h" #include "fileops.h" /* Buffer */ @@ -118,7 +118,7 @@ u8* NANDReadFromFile(const char* path, u32 offset, u32 length, u32* size) if (!length) length = IOS_Seek(fd, 0, SEEK_END); - u8* data = (u8*)memalign(0x40, length); + u8* data = memalign64(length); if (!data) { *size = 0; @@ -155,9 +155,10 @@ u8* NANDLoadFile(const char* path, u32* size) s32 NANDWriteFileSafe(const char* path, u8* data, u32 size) { + char tmpPath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(64); + NANDInitialize(); - - char* tmpPath = (char*)memalign(0x40, ISFS_MAXPATH); + u32 i; for (i = strlen(path); i > 0; --i) @@ -175,43 +176,29 @@ s32 NANDWriteFileSafe(const char* path, u8* data, u32 size) ret = ISFS_CreateFile(tmpPath, 0, 3, 3, 3); if (ret < 0) - { - free(tmpPath); return ret; - } } - else + else if (ret < 0) { - if (ret < 0) - { - free(tmpPath); - return ret; - } + return ret; } s32 fd = IOS_Open(tmpPath, 2); if (fd < 0) - { - free(tmpPath); return fd; - } ret = IOS_Write(fd, data, size); IOS_Close(fd); if (ret != size) - { - free(tmpPath); return ret - 3; - } if (strcmp(tmpPath, path)) ret = ISFS_Rename(tmpPath, path); else ret = 0; - - free(tmpPath); + return ret; } diff --git a/source/sys.c b/source/sys.c index 8c8b530..27977f1 100644 --- a/source/sys.c +++ b/source/sys.c @@ -1,14 +1,14 @@ #include #include -#include #include #include "sys.h" +#include "malloc.h" #include "mload.h" #include "ehcmodule_elf.h" /* Constants */ -#define CERTS_LEN 0x280 +#define CERTS_LEN 0x280 /* Variables */ static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys"; @@ -29,75 +29,77 @@ void __Sys_PowerCallback(void) Sys_Shutdown(); } -bool isIOSstub(u8 ios_number) -{ - u32 tmd_size; - tmd_view *ios_tmd; - - - if((boot2version >= 5) && ( ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224)) return true; - - ES_GetTMDViewSize(0x0000000100000000ULL | ios_number, &tmd_size); - if (!tmd_size) - { - //getting size failed. invalid or fake tmd for sure! - //gprintf("failed to get tmd for ios %d\n",ios_number); - return true; - } - ios_tmd = (tmd_view *)memalign( 32, (tmd_size+31)&(~31) ); - if(!ios_tmd) - { - //gprintf("failed to mem align the TMD struct!\n"); - return true; - } - memset(ios_tmd , 0, tmd_size); - ES_GetTMDView(0x0000000100000000ULL | ios_number, (u8*)ios_tmd , tmd_size); - //gprintf("IOS %d is rev %d(0x%x) with tmd size of %u and %u contents\n",ios_number,ios_tmd->title_version,ios_tmd->title_version,tmd_size,ios_tmd->num_contents); - /*Stubs have a few things in common: - - title version : it is mostly 65280 , or even better : in hex the last 2 digits are 0. - example : IOS 60 rev 6400 = 0x1900 = 00 = stub - - exception for IOS21 which is active, the tmd size is 592 bytes (or 140 with the views) - - the stub ios' have 1 app of their own (type 0x1) and 2 shared apps (type 0x8001). - eventho the 00 check seems to work fine , we'll only use other knowledge as well cause some - people/applications install an ios with a stub rev >_> ...*/ - u8 Version = ios_tmd->title_version; - - if((boot2version >= 5) && (ios_number == 249 || ios_number == 250) && (Version < 18)) return true; - if(( ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224) && (Version < 4)) return true; - //version now contains the last 2 bytes. as said above, if this is 00, its a stub - if ( Version == 0 ) - { - if ( ( ios_tmd->num_contents == 3) && (ios_tmd->contents[0].type == 1 && ios_tmd->contents[1].type == 0x8001 && ios_tmd->contents[2].type == 0x8001) ) - { - //gprintf("IOS %d is a stub\n",ios_number); - free(ios_tmd); - return true; - } - else - { - //gprintf("IOS %d is active\n",ios_number); - free(ios_tmd); - return false; - } - } - //gprintf("IOS %d is active\n",ios_number); - free(ios_tmd); - return false; -} - +bool isIOSstub(u8 ios_number) +{ + u32 tmd_size = 0; + tmd_view *ios_tmd; + + if ((boot2version >= 5) && (ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224)) + return true; + + ES_GetTMDViewSize(0x0000000100000000ULL | ios_number, &tmd_size); + if (!tmd_size) + { + // getting size failed. invalid or fake tmd for sure! + // gprintf("failed to get tmd for ios %d\n",ios_number); + return true; + } + ios_tmd = memalign32(tmd_size); + if (!ios_tmd) + { + // gprintf("failed to mem align the TMD struct!\n"); + return true; + } + memset(ios_tmd, 0, tmd_size); + ES_GetTMDView(0x0000000100000000ULL | ios_number, (u8 *)ios_tmd, tmd_size); + // gprintf("IOS %d is rev %d(0x%x) with tmd size of %u and %u contents\n",ios_number,ios_tmd->title_version,ios_tmd->title_version,tmd_size,ios_tmd->num_contents); + /*Stubs have a few things in common: + - title version : it is mostly 65280 , or even better : in hex the last 2 digits are 0. + example : IOS 60 rev 6400 = 0x1900 = 00 = stub + - exception for IOS21 which is active, the tmd size is 592 bytes (or 140 with the views) + - the stub ios' have 1 app of their own (type 0x1) and 2 shared apps (type 0x8001). + eventho the 00 check seems to work fine , we'll only use other knowledge as well cause some + people/applications install an ios with a stub rev >_> ...*/ + u8 Version = ios_tmd->title_version; + + if ((boot2version >= 5) && (ios_number == 249 || ios_number == 250) && (Version < 18)) + return true; + if ((ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224) && (Version < 4)) + return true; + // version now contains the last 2 bytes. as said above, if this is 00, its a stub + if (Version == 0) + { + if ((ios_tmd->num_contents == 3) && (ios_tmd->contents[0].type == 1 && ios_tmd->contents[1].type == 0x8001 && ios_tmd->contents[2].type == 0x8001)) + { + // gprintf("IOS %d is a stub\n",ios_number); + free(ios_tmd); + return true; + } + else + { + // gprintf("IOS %d is active\n",ios_number); + free(ios_tmd); + return false; + } + } + // gprintf("IOS %d is active\n",ios_number); + free(ios_tmd); + return false; +} bool loadIOS(int ios) { - if(isIOSstub(ios)) return false; + if (isIOSstub(ios)) + return false; mload_close(); - if(IOS_ReloadIOS(ios)>=0) + if (IOS_ReloadIOS(ios) >= 0) { if (IOS_GetVersion() != 249 && IOS_GetVersion() != 250) { if (mload_init() >= 0) { data_elf my_data_elf; - mload_elf((void *) ehcmodule_elf, &my_data_elf); + mload_elf((void *)ehcmodule_elf, &my_data_elf); mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, 0x47); } } @@ -125,17 +127,20 @@ void Sys_Reboot(void) void Sys_Shutdown(void) { /* Poweroff console */ - if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) { + if (CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) + { s32 ret; /* Set LED mode */ ret = CONF_GetIdleLedMode(); - if(ret >= 0 && ret <= 2) + if (ret >= 0 && ret <= 2) STM_SetLedMode(ret); /* Shutdown to idle */ STM_ShutdownToIdle(); - } else { + } + else + { /* Shutdown to standby */ STM_ShutdownToStandby(); } @@ -144,21 +149,22 @@ void Sys_Shutdown(void) void Sys_LoadMenu(void) { int HBC = 0; - char * sig = (char *)0x80001804; - if( sig[0] == 'S' && - sig[1] == 'T' && - sig[2] == 'U' && - sig[3] == 'B' && - sig[4] == 'H' && - sig[5] == 'A' && - sig[6] == 'X' && - sig[7] == 'X') + char *sig = (char *)0x80001804; + if (sig[0] == 'S' && + sig[1] == 'T' && + sig[2] == 'U' && + sig[3] == 'B' && + sig[4] == 'H' && + sig[5] == 'A' && + sig[6] == 'X' && + sig[7] == 'X') { - HBC=1; // Exit to HBC + HBC = 1; // Exit to HBC } /* Homebrew Channel stub */ - if (HBC == 1) { + if (HBC == 1) + { exit(0); } /* Return to the Wii system menu */ @@ -183,9 +189,10 @@ s32 Sys_GetCerts(signed_blob **certs, u32 *len) IOS_Close(fd); /* Set values */ - if (ret > 0) { + if (ret > 0) + { *certs = certificates; - *len = sizeof(certificates); + *len = sizeof(certificates); } return ret; diff --git a/source/title.c b/source/title.c index 9567411..19abbc3 100644 --- a/source/title.c +++ b/source/title.c @@ -2,12 +2,11 @@ #include #include #include -#include #include #include "sha1.h" #include "utils.h" - +#include "malloc.h" s32 Title_ZeroSignature(signed_blob *p_sig) { @@ -79,7 +78,7 @@ s32 Title_GetList(u64 **outbuf, u32 *outlen) { u64 *titles = NULL; - u32 len, nb_titles; + u32 nb_titles; s32 ret; /* Get number of titles */ @@ -87,11 +86,9 @@ s32 Title_GetList(u64 **outbuf, u32 *outlen) if (ret < 0) return ret; - /* Calculate buffer lenght */ - len = round_up(sizeof(u64) * nb_titles, 32); /* Allocate memory */ - titles = memalign(32, len); + titles = memalign32(nb_titles * sizeof(u64)); if (!titles) return -1; @@ -126,7 +123,7 @@ s32 Title_GetTicketViews(u64 tid, tikview **outbuf, u32 *outlen) return ret; /* Allocate memory */ - views = (tikview *)memalign(32, sizeof(tikview) * nb_views); + views = memalign32(sizeof(tikview) * nb_views); if (!views) return -1; @@ -161,7 +158,7 @@ s32 Title_GetTMD(u64 tid, signed_blob **outbuf, u32 *outlen) return ret; /* Allocate memory */ - p_tmd = memalign(32, round_up(len, 32)); + p_tmd = memalign32(len); if (!p_tmd) return -1; @@ -290,7 +287,7 @@ s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen) } /* Allocate memory */ - buffer = (u8 *)memalign(32, cnt); + buffer = memalign32(cnt); if (!buffer) { ret = -1; goto out; diff --git a/source/wad.c b/source/wad.c index 4287d04..83a2f4c 100644 --- a/source/wad.c +++ b/source/wad.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -16,6 +15,7 @@ #include "sha1.h" #include "menu.h" #include "iospatch.h" +#include "malloc.h" // Turn upper and lower into a full title ID #define TITLE_ID(x,y) (((u64)(x) << 32) | (y)) @@ -97,7 +97,7 @@ u64 get_title_ios(u64 title) { // Check to see if title exists if (ES_GetDataDir(title, filepath) >= 0 ) { - u32 tmd_size; + u32 tmd_size = 0; static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); ret = ES_GetStoredTMDSize(title, &tmd_size); @@ -265,62 +265,86 @@ const char* GetSysMenuVersionString(u16 version) return VersionLookupTable[version % 32][version / 32]; }; -static char* GetTitleExec(u64 tId, bool tweaked) +static u32 GetSysMenuBootContent(void) { - u32 size; - const u8 buffer[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); + s32 ret; + u32 cid = 0; + u32 size = 0; + signed_blob *s_tmd = NULL; - s32 ret = ES_GetStoredTMDSize(0x100000002LL, &size); - signed_blob* tmdRaw = (signed_blob*)buffer; - - ret = ES_GetStoredTMD(0x100000002LL, tmdRaw, size); - if (ret < 0) + ret = ES_GetStoredTMDSize(0x100000002LL, &size); + if (!size) { - printf("Error! ES_GetStoredTMDSize: Failed! (Error: %d)\n", ret); - return NULL; + printf("Error! ES_GetStoredTMDSize failed (ret=%i)\n", ret); + return 0; } - tmd* smTMD = SIGNATURE_PAYLOAD(tmdRaw); + s_tmd = memalign32(size); + if (!s_tmd) + { + printf("Error! Memory allocation failed!\n"); + return 0; + } - char* path = (char*)memalign(0x40, ISFS_MAXPATH); - if (!path) - return NULL; + ret = ES_GetStoredTMD(0x100000002LL, (u8*)s_tmd, size); + if (ret < 0) + { + printf("Error! ES_GetStoredTMD failed (ret=%i)\n", ret); + free(s_tmd); + return 0; + } - if(tweaked) - sprintf(path, "/title/%08x/%08x/content/1%.7x.app", TITLE_UPPER(tId), TITLE_LOWER(tId), smTMD->contents[smTMD->boot_index].cid); - else - sprintf(path, "/title/%08x/%08x/content/%.8x.app", TITLE_UPPER(tId), TITLE_LOWER(tId), smTMD->contents[smTMD->boot_index].cid); + tmd *p_tmd = SIGNATURE_PAYLOAD(s_tmd); - return path; + for (int i = 0; i < p_tmd->num_contents; i++) + { + tmd_content* content = &p_tmd->contents[i]; + if (content->index == p_tmd->boot_index) + { + cid = content->cid; + break; + } + } + + free(s_tmd); + if (!cid) printf("Error! Cannot find system menu boot content!\n"); + + return cid; +} + +bool GetSysMenuExecPath(char path[ISFS_MAXPATH], bool mainDOL) +{ + u32 cid = GetSysMenuBootContent(); + if (!cid) return false; + + if (mainDOL) cid |= 0x10000000; + sprintf(path, "/title/00000001/00000002/content/%08x.app", cid); + + return true; } bool IsPriiloaderInstalled() { - char* path = GetTitleExec(0x100000002LL, true); - if (!path) + char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20); + + if (!GetSysMenuExecPath(path, true)) return false; - - + u32 size = 0; NANDGetFileSize(path, &size); - free(path); - if (size > 0) - return true; - else - return false; + return (size > 0); } static bool BackUpPriiloader() { - char* path = GetTitleExec(0x100000002LL, false); - if (!path) + char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20); + + if (!GetSysMenuExecPath(path, false)) return false; u32 size = 0; s32 ret = NANDBackUpFile(path, "/tmp/priiload.app", &size); - free(path); - if (ret < 0) { printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); @@ -334,23 +358,19 @@ static bool BackUpPriiloader() static bool MoveMenu(bool restore) { - char* srcPath = GetTitleExec(0x100000002LL, restore); - if (!srcPath) + ATTRIBUTE_ALIGN(0x20) + char srcPath[ISFS_MAXPATH], dstPath[ISFS_MAXPATH]; + + if (!GetSysMenuBootContent()) return false; - char* dstPath = GetTitleExec(0x100000002LL, !restore); - if (!dstPath) - { - free(srcPath); - return false; - } + GetSysMenuExecPath(srcPath, restore); + GetSysMenuExecPath(dstPath, !restore); u32 size = 0; s32 ret = NANDBackUpFile(srcPath, dstPath, &size); if (ret < 0) { - free(srcPath); - free(dstPath); printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); return false; } @@ -358,23 +378,19 @@ static bool MoveMenu(bool restore) u32 checkSize = 0; ret = NANDGetFileSize(dstPath, &checkSize); - free(srcPath); - free(dstPath); - return (checkSize == size); } static bool RestorePriiloader() { - char* dstPath = GetTitleExec(0x100000002LL, false); - if (!dstPath) - return false; + char dstPath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20); + + if (!GetSysMenuExecPath(dstPath, false)); u32 size = 0; s32 ret = NANDBackUpFile("/tmp/priiload.app", dstPath, &size); if (ret < 0) { - free(dstPath); printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); return false; } @@ -382,8 +398,6 @@ static bool RestorePriiloader() u32 checkSize = 0; ret = NANDGetFileSize(dstPath, &checkSize); - free(dstPath); - return (checkSize == size && checkSize == gPriiloaderSize); } @@ -453,56 +467,30 @@ static void CleanupPriiloaderLeftOvers(bool retain) static bool CompareHashes(bool priiloader) { - char* dstPath = NULL; - char* srcPath = GetTitleExec(0x100000002LL, false); + ATTRIBUTE_ALIGN(0x20) + char srcPath[ISFS_MAXPATH], dstPath[ISFS_MAXPATH] = "/tmp/priiload.app"; - if (!srcPath) + if (!GetSysMenuExecPath(srcPath, false)) return false; - - if (priiloader) - { - dstPath = (char*)memalign(0x40, ISFS_MAXPATH); - if (!dstPath) - { - free(srcPath); - return false; - } - - strcpy(dstPath, "/tmp/priiload.app"); - } - else - { - dstPath = GetTitleExec(0x100000002LL, true); - if (!dstPath) - { - free(srcPath); - return false; - } - } + + if (!priiloader) + GetSysMenuExecPath(dstPath, true); u32 sizeA = 0; u32 sizeB = 0; u8* dataA = NANDLoadFile(srcPath, &sizeA); if (!dataA) - { - free(srcPath); - free(dstPath); return false; - } u8* dataB = NANDLoadFile(dstPath, &sizeB); - if (!dataA) + if (!dataB) { - free(srcPath); - free(dstPath); free(dataA); return false; } - bool ret = !CompareHash(dataA, sizeA, dataB, sizeB); + bool ret = (sizeA == sizeB) && !CompareHash(dataA, sizeA, dataB, sizeB); - free(srcPath); - free(dstPath); free(dataA); free(dataB); @@ -971,9 +959,9 @@ skipChecks: { if (restored) { - char* path = GetTitleExec(0x100000002LL, true); + char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20); + GetSysMenuExecPath(path, true); NANDDeleteFile(path); - free(path); } } }