s32 Title_GetTMD(u64 tid, signed_blob **outbuf, u32 *outlen) { void *p_tmd = NULL; u32 len; s32 ret; /* Get TMD size */ ret = ES_GetStoredTMDSize(tid, &len); if (ret < 0) return ret; /* Allocate memory */ p_tmd = memalign(32, round_up(len, 32)); if (!p_tmd) return -1; /* Read TMD */ ret = ES_GetStoredTMD(tid, p_tmd, len); if (ret < 0) goto err; /* Set values */ *outbuf = p_tmd; *outlen = len; return 0; err: /* Free memory */ if (p_tmd) free(p_tmd); return ret; }
s32 GetTMD(u64 TicketID, signed_blob **Output, u32 *Length) { signed_blob* TMD = NULL; u32 TMD_Length; s32 ret; /* Retrieve TMD length */ ret = ES_GetStoredTMDSize(TicketID, &TMD_Length); if (ret < 0) return ret; /* Allocate memory */ TMD = (signed_blob*)MEM2_memalign(32, (TMD_Length+31)&(~31)); if (!TMD) return IPC_ENOMEM; /* Retrieve TMD */ ret = ES_GetStoredTMD(TicketID, TMD, TMD_Length); if (ret < 0) { free(TMD); return ret; } /* Set values */ *Output = TMD; *Length = TMD_Length; return 0; }
signed_blob *GetTMD(u8 ios, u32 *TMD_Length) { if(ES_GetStoredTMDSize(TITLE_ID(1, ios), TMD_Length) < 0) return NULL; signed_blob *TMD = (signed_blob*)MEM2_alloc(*TMD_Length); if(TMD == NULL) return NULL; if(ES_GetStoredTMD(TITLE_ID(1, ios), TMD, *TMD_Length) < 0) { MEM2_free(TMD); return NULL; } return TMD; }
bool isIOSstub(u8 ios_number) { static signed_blob ios_tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); u32 tmd_size; tmd *ios_tmd; if (ios_number == 249) { ES_GetStoredTMDSize(0x0000000100000000ULL | ios_number, &tmd_size); ES_GetStoredTMD(0x0000000100000000ULL | ios_number, ios_tmd_buf, tmd_size); ios_tmd = SIGNATURE_PAYLOAD(ios_tmd_buf); if (ios_tmd->title_version >= 65280) return TRUE; } return FALSE; }
tmd* NandTitle::GetTMD(u64 tid) { signed_blob *s_tmd = (signed_blob *) tmd_buf; u32 tmd_size; if (ES_GetStoredTMDSize(tid, &tmd_size) < 0) { return NULL; } s32 ret = ES_GetStoredTMD(tid, s_tmd, tmd_size); if (ret < 0) { return NULL; } tmd *t = (tmd*) SIGNATURE_PAYLOAD(s_tmd); return t; }
s32 WII_OpenURL(const char *url) { u32 tmdsize; u64 tid = 0; u64 *list; u32 titlecount; s32 ret; int i; if(!__initialized) return WII_ENOTINIT; ret = ES_GetNumTitles(&titlecount); if(ret < 0) return WII_EINTERNAL; list = memalign(32, titlecount * sizeof(u64) + 32); ret = ES_GetTitles(list, titlecount); if(ret < 0) { free(list); return WII_EINTERNAL; } for(i=0; i<titlecount; i++) { if((list[i] & ~0xFF) == 0x1000148414400LL) { tid = list[i]; break; } } free(list); if(!tid) return WII_EINSTALL; if(ES_GetStoredTMDSize(tid, &tmdsize) < 0) return WII_EINSTALL; return WII_LaunchTitleWithArgs(tid, 0, url, NULL); }
//boot HBC in either HAXX or JODI locations //this function expects WII_Initialize() be called before it is called s32 WII_BootHBC() { u32 tmdsize; u64 tid = 0; u64 *list; u32 titlecount; s32 ret; u32 i; ret = ES_GetNumTitles(&titlecount); if(ret < 0) return WII_EINTERNAL; list = CFMemAlign(32, titlecount * sizeof(u64) + 32); ret = ES_GetTitles(list, titlecount); if(ret < 0) { CFFree(list); return WII_EINTERNAL; } for(i=0; i<titlecount; i++) { if (list[i]==TITLE_ID(0x00010001,0x4A4F4449) || list[i]==TITLE_ID(0x00010001,0x48415858) || list[i]==TITLE_ID(0x00010001,0xaf1bf516)) { tid = list[i]; break; } } CFFree(list); if(!tid) return WII_EINSTALL; if(ES_GetStoredTMDSize(tid, &tmdsize) < 0) return WII_EINSTALL; return WII_LaunchTitle(tid); }
s32 LoadKernel() { u32 TMDSize; u32 i,u; s32 r = ES_GetStoredTMDSize( 0x000000010000003aLL, &TMDSize ); if( r < 0 ) { gprintf("ES_GetStoredTMDSize():%d\r\n", r ); return r; } gprintf("TMDSize:%u\r\n", TMDSize ); TitleMetaData *TMD = (TitleMetaData*)memalign( 32, TMDSize ); if( TMD == (TitleMetaData*)NULL ) { gprintf("Failed to alloc:%u\r\n", TMDSize ); return r; //todo errors are < 0 r still has >= 0 from previous call } r = ES_GetStoredTMD( 0x000000010000003aLL, (signed_blob *)TMD, TMDSize ); if( r < 0 ) { gprintf("ES_GetStoredTMD():%d\r\n", r ); free(TMD); return r; } //Look for boot index for( i=0; i < TMD->ContentCount; ++i ) { if( TMD->BootIndex == TMD->Contents[i].Index ) break; } gprintf("BootIndex:%u\r\n", i ); s32 cfd = IOS_Open( "/shared1/content.map", 1 ); if( cfd < 0 ) { gprintf("IOS_Open():%d\r\n", cfd ); free(TMD); return cfd; } for( u=0;; u+=0x1C ) { if( IOS_Read( cfd, Entry, 0x1C ) != 0x1C ) { gprintf("Hash not found in content.map\r\n"); free(TMD); return -2; } if( memcmp( (char*)(Entry+8), TMD->Contents[i].SHA1, 0x14 ) == 0 ) break; } FoundVersion = ((TMD->TitleID & 0xFFFF) << 16) | (TMD->TitleVersion); free(TMD); IOS_Close( cfd ); u32 *IOSVersion = (u32*)0x93003000; DCInvalidateRange(IOSVersion, 0x20); *IOSVersion = FoundVersion; gprintf("IOS Version: 0x%08X\n", FoundVersion); DCFlushRange(IOSVersion, 0x20); //char Path[32]; char *Path = (char*)0x93003020; DCInvalidateRange(Path, 1024); memset(Path, 0, 1024); sprintf( Path, "/shared1/%.8s.app", Entry ); gprintf("Kernel:\"%s\"\r\n", Path ); DCFlushRange(Path, 1024); s32 kfd = IOS_Open( Path, 1 ); if( kfd < 0 ) { gprintf("IOS_Open():%d\r\n", kfd ); return kfd; } KernelSize = IOS_Seek( kfd, 0, SEEK_END ); IOS_Seek( kfd, 0, 0); gprintf("KernelSize:%u\r\n", KernelSize ); if( IOS_Read( kfd, Kernel, KernelSize ) != KernelSize ) { gprintf("IOS_Read() failed\r\n"); IOS_Close(kfd); return -1; } IOS_Close(kfd); return 0; }
s32 *get_ioslist(u32 *cnt) { u64 *buf = 0; s32 res; u32 i, k = 0, tcnt = 0, icnt = 0; s32 *ioses = NULL; bool skip_title; /* Get stored IOS versions */ res = ES_GetNumTitles(&tcnt); if (res < 0) { printf("\t- ES_GetNumTitles: Error! (result = %ld).\n", res); return 0; } buf = memalign(32, sizeof(u64) * tcnt); if (!buf) { printf("\t- Error allocating titlelist memory buffer!\n"); return 0; } res = ES_GetTitles(buf, tcnt); if (res < 0) { printf("\t- ES_GetTitles: Error! (result = %ld).\n", res); free(buf); return 0; } for (i = 0; i < tcnt; i++) { /* Skip BC, MIOS, System Menu, BootMii IOS, BC-NAND, BC-WFS and stub IOSses */ if ((TITLE_UPPER(buf[i - k]) == 1) && (TITLE_LOWER(buf[i - k]) > 2) && (TITLE_LOWER(buf[i - k]) < 0xFE)) { u32 tmdSize = 0; tmd *iosTMD = NULL; signed_blob *iosTMDBuffer = NULL; /* Get stored TMD size */ res = ES_GetStoredTMDSize(buf[i - k], &tmdSize); if (res < 0) { printf("\t- ES_GetStoredTMDSize: Error! (result = %ld / IOS%lu).\n", res, ((u32)buf[i - k])); break; } iosTMDBuffer = (signed_blob*)memalign(32, (tmdSize+31)&(~31)); if (!iosTMDBuffer) { res = -1; printf("\t- Error allocating IOS%lu TMD buffer (size = %lu bytes).\n", ((u32)buf[i - k]), tmdSize); break; } memset(iosTMDBuffer, 0, tmdSize); /* Get stored TMD */ res = ES_GetStoredTMD(buf[i - k], iosTMDBuffer, tmdSize); if (res < 0) { printf("\t- ES_GetStoredTMD: Error! (result = %ld / IOS%lu).\n", res, ((u32)buf[i - k])); free(iosTMDBuffer); break; } iosTMD = (tmd*)SIGNATURE_PAYLOAD(iosTMDBuffer); /* Calculate title size */ u16 j; u32 titleSize = 0; for (j = 0; j < iosTMD->num_contents; j++) { tmd_content *content = &iosTMD->contents[j]; /* Add content size */ titleSize += content->size; } /* Check if this IOS is a stub */ skip_title = (titleSize < 0x100000); free(iosTMDBuffer); } else { skip_title = true; } if (!skip_title) { icnt++; } else { /* Move around memory blocks */ if ((tcnt - 1) > i) { memmove(&(buf[i - k]), &(buf[i - k + 1]), (sizeof(u64) * (tcnt - i - 1))); k++; } } } if (res < 0) { free(buf); return 0; } if (realloc(buf, sizeof(u64) * icnt) == NULL) { printf("\t- Error reallocating titlelist memory block!\n"); free(buf); return 0; } ioses = (s32 *)malloc(sizeof(s32) * icnt); if (!ioses) { printf("\t- Error allocating IOS memory buffer!\n"); free(buf); return 0; } for (i = 0; i < icnt; i++) ioses[i] = (s32)buf[i]; free(buf); qsort(ioses, icnt, sizeof(s32), __s32Cmp); *cnt = icnt; return ioses; }
s32 extractChannelContents(u64 titleID, char* location) { u32 TitleIDH=TITLE_UPPER(titleID); u32 TitleIDL=TITLE_LOWER(titleID); if(ES_SetUID(titleID)<0) return ERR_UID; u32 tmd_size ATTRIBUTE_ALIGN(32); if(ES_GetStoredTMDSize(titleID, &tmd_size)<0) return ERR_TMDSIZE; signed_blob *TMD = (signed_blob *)memalign( 32, tmd_size ); memset(TMD, 0, tmd_size); if(ES_GetStoredTMD(titleID, TMD, tmd_size)<0) { free(TMD); return ERR_TMD; } u32 cnt ATTRIBUTE_ALIGN(32); if(ES_GetNumTicketViews(titleID, &cnt)<0) { free(TMD); return ERR_TIKCOUNT; } if( cnt <= 0 ) { free(TMD); return ERR_TIKCOUNT; } tikview *views = (tikview *)memalign( 32, sizeof(tikview)*cnt ); if(ES_GetTicketViews(titleID, views, cnt)<0) { free(views); free(TMD); return ERR_TIK; } printf("Allocated and filled views.\n"); sleep(3); Identify_SU(); int z; tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD)))); // OH GOD CREDIAR, WTF WAS THAT MESS! // List format is "XXXXXXXX = YYYYYYYY" where X is index, and Y is cid. char *lookup_list=calloc(21,((tmd*)(SIGNATURE_PAYLOAD(TMD)))->num_contents); ClearScreen(); printf("\nNumber of contents: %d\n",((tmd*)(SIGNATURE_PAYLOAD(TMD)))->num_contents); sleep(1); for(z=0; z < ((tmd*)(SIGNATURE_PAYLOAD(TMD)))->num_contents; z++) { /* Get Content */ char nameDirectory[80]; sprintf(nameDirectory,"/title/%08x/%08x/content/%08x.app",TitleIDH,TitleIDL,TMDc[z].cid); s32 contentFd=ISFS_Open(nameDirectory,ISFS_OPEN_READ); u8 *data=calloc(TMDc[z].size,1); if(contentFd<0) { switch(contentFd) { case ISFS_EINVAL: printf("FAILED! (Invalid Argument %s)\n\tQuitting...\n",nameDirectory); sleep(5); Finish(1); break; case ISFS_ENOMEM: printf("FAILED! (Out of memory %s)\n\tQuitting...\n",nameDirectory); sleep(5); Finish(1); break; default: goto skip; // Finish(1); break; } } int isUnaligned = ((int)data)%32 | TMDc[z].size%32; int alignedLen = (TMDc[z].size+31)&0xffffffe0; unsigned char* alignedBuf; if(isUnaligned) alignedBuf = memalign(32, alignedLen); else alignedBuf = data; ISFS_Seek(contentFd,0,0); ISFS_Read(contentFd, alignedBuf, alignedLen); // If it was unaligned, you have to copy it and clean up if(isUnaligned){ memcpy(data, alignedBuf, TMDc[z].size); free(alignedBuf); } ISFS_Close(contentFd); // Do copying here. // data is the actual content data (use fwrite with it :P). // Copy the file with it's index as it's filename char* destination=calloc(sizeof(location)+14, 1); char lookup_entry[21]; sprintf(destination, "%s/%08x.app",location,TMDc[z].index); sprintf(lookup_entry, "%08x = %08x\n",TMDc[z].index,TMDc[z].cid); strcat(lookup_list, lookup_entry); printf("Got destination as: %s\n", destination); sleep(3); FILE *dfd=fopen(destination,"wb+"); printf("Opened %s\n", destination); sleep(3); // free(destination); fwrite(data, TMDc[z].size, 1, dfd); printf("Wrote data to %s\n", destination); sleep(3); fclose(dfd); printf("Closed %s\n", destination); sleep(2); skip: _nop(); } // Make a file containing the lookups called files.txt char* lookup_file=calloc(sizeof(location)+14, 1); sprintf(lookup_file, "%s/files.txt",location); printf("Got destination as: %s\n", lookup_file); sleep(3); FILE* lfd=fopen(lookup_file,"wb+"); printf("Opened %s\n", lookup_file); sleep(3); // free(lookup_file); fwrite(lookup_list, 21, ((tmd*)SIGNATURE_PAYLOAD(TMD))->num_contents, lfd); printf("Wrote lookups to %s\n", lookup_file); sleep(3); fclose(lfd); printf("Closed %s\n", lookup_file); sleep(2); printf("Freed TMD and views"); sleep(1);
return ERR_NONE; } void changeChannelName(u64 titleID) { printf("Identifying as 00000001-00000000 (SU)!... "); CheckESRetval(ES_Identify(SU_IDENTIFY)); // if(ES_SetUID(titleID)<0) // return; u32 tmd_size ATTRIBUTE_ALIGN(32); if(CheckESRetval(ES_GetStoredTMDSize(titleID, &tmd_size))!=0) return; signed_blob *TMD = (signed_blob *)memalign( 32, tmd_size ); memset(TMD, 0, tmd_size); if(CheckESRetval(ES_GetStoredTMD(titleID, TMD, tmd_size))!=0) { free(TMD); return; } u32 cnt ATTRIBUTE_ALIGN(32); if(CheckESRetval(ES_GetNumTicketViews(titleID, &cnt))!=0) { free(TMD); return; } if( cnt <= 0 ) { free(TMD); return; } tikview *views = (tikview *)memalign( 32, sizeof(tikview)*cnt ); if(CheckESRetval(ES_GetTicketViews(titleID, views, cnt))!=0) { free(views); free(TMD); return; } char *name=calloc((0x54/2),1); int z; for(z=0; z < 1; ++z) { tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD)))); // OH GOD CREDIAR, WTF WAS THAT MESS!!! //printf("%d,",TMDc->index); s32 cfd = ES_OpenTitleContent( titleID, TMDc->index); free(views); if(CheckESRetval(cfd)!=0) { ; //printf("ES_OpenContent(%d) failed\n", cfd); //sleep(10); //exit(0); } else { u64 sz ATTRIBUTE_ALIGN(32) = 0x140; u8 *data = (u8*)memalign(32, sz); if( TMDc->size < sz ) sz = TMDc->size; if( data != NULL ) { if(ES_ReadContent(cfd, data, sz)<0) { free(data); return; } int y; int chan_name_offset=(language_setting*0x54); // Set to WiiMU's language for(y=0;y<(0x54/2);y++) name[y]=data[(0x9C+chan_name_offset)+(y*2)+1]; } if(CheckESRetval(ES_CloseContent(cfd))!=0) { ; //printf("ES_CloseContent failed\n"); //sleep(10); //exit(0); } free(data); } } int wiistring_size; reenter: wiistring_size=type_string_wiimote(name, 0x54/2); if(wiistring_size<=0) { printf("\n\nPlease enter a name!\n"); sleep(3); goto reenter; } name[wiistring_size+1]=0; /* Get Content */ char nameDirectory[80]; tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD)))); sprintf(nameDirectory,"/title/%08x/%08x/content/%08x.app",TITLE_UPPER(titleID),TITLE_LOWER(titleID),TMDc->cid); s32 contentFd=ISFS_Open(nameDirectory,ISFS_OPEN_RW); CheckISFSRetval(contentFd); ClearScreen(); printf("\n\nOpened content!\n"); u8 *data=calloc(TMDc->size,1); int isUnaligned = ((int)data)%32 | TMDc->size%32; int alignedLen = (TMDc->size+31)&0xffffffe0; u8* alignedBuf; if(isUnaligned) alignedBuf = memalign(32, alignedLen); else alignedBuf = data; CheckISFSRetval(ISFS_Seek(contentFd,0,0)); CheckISFSRetval(ISFS_Read(contentFd, alignedBuf, alignedLen)); printf("Read content!\n"); int y; int chan_name_offset=(SYSCONF_GetArea()*0x54); // Edits the one for the Wii's system Menu char* nameOut=calloc(96,1); for(y=0;y<(0x54/2);y++) nameOut[(y*2)+1]=name[y]; printf("Wrote new name! %s\n", name); CheckISFSRetval(ISFS_Seek(contentFd,(0x9C+chan_name_offset),0)); printf("Seeked to location!\n"); if(nameOut==NULL) { printf("FAILED! (Name Out is NULL!)\n"); sleep(5); Finish(1); } if(((u32)nameOut%32)!=0) { isUnaligned = ((int)nameOut)%32 | 0x54%32; alignedLen = (0x54+31)&0xffffffe0; if(isUnaligned){ alignedBuf = memalign(32, alignedLen); memcpy(alignedBuf, nameOut, 0x54); } else alignedBuf = (u8*)nameOut; } CheckISFSRetval(ISFS_Write(contentFd, alignedBuf, 0x54)); printf("Wrote content name!\nReading new Header Chunk!\n"); CheckISFSRetval(ISFS_Seek(contentFd,0,0)); CheckISFSRetval(ISFS_Read(contentFd, alignedBuf, alignedLen)); printf("Read content!\n"); u8* header_chunk=calloc(0x640, 1); int i; for(i=0;i<0x630;i++) header_chunk[i]=alignedBuf[i]; for(i=0x630;i<0x640;i++) header_chunk[i]=0; u8* hash=calloc(0x10,1); md5(header_chunk, 0x640, hash); CheckISFSRetval(ISFS_Seek(contentFd,0x630,0)); printf("Seeked to location!\n"); if(hash==NULL) { printf("FAILED! (Hash is NULL!)\n"); sleep(5); Finish(1); } if(((u32)hash%32)!=0) { isUnaligned = ((int)hash)%32 | 0x10%32; alignedLen = (0x10+31)&0xffffffe0; if(isUnaligned){ alignedBuf = memalign(32, alignedLen); memcpy(alignedBuf, hash, 0x10); } else alignedBuf = hash;
s32 IOS_GetPreferredVersion() { int ver = IOS_EBADVERSION; s32 res; u32 count; u64 *titles; u32 tmd_size; u32 i; u32 a,b; res = __IOS_InitHeap(); if(res<0) return res; res = ES_GetNumTitles(&count); if(res < 0) { #ifdef DEBUG_IOS printf(" GetNumTitles failed: %d\n",res); #endif return res; } #ifdef DEBUG_IOS printf(" %d titles on card:\n",count); #endif titles = iosAlloc(__ios_hid, sizeof(u64)*count); if(!titles) { printf(" iosAlloc titles failed\n"); return -1; } res = ES_GetTitles(titles, count); if(res < 0) { #ifdef DEBUG_IOS printf(" GetTitles failed: %d\n",res); #endif iosFree(__ios_hid, titles); return res; } u32 *tmdbuffer = memalign(32, MAX_SIGNED_TMD_SIZE); if(!tmdbuffer) { iosFree(__ios_hid, titles); return -1; } for(i=0; i<count; i++) { a = titles[i]>>32; b = titles[i]&0xFFFFFFFF; if(a != 1) continue; if(b < IOS_MIN_VERSION) continue; if(b > IOS_MAX_VERSION) continue; if (ES_GetStoredTMDSize(titles[i], &tmd_size) < 0) continue; if (tmd_size < 0 || tmd_size > 4096) continue; if(ES_GetStoredTMD(titles[i], (signed_blob *)tmdbuffer, tmd_size) < 0) continue; if (!tmdbuffer[1] && !tmdbuffer[2]) continue; if((((s32)b) > ((s32)ver) && ver != 58) || b == 58) ver = b; } #ifdef DEBUG_IOS printf(" Preferred verson: %d\n",ver); #endif iosFree(__ios_hid, titles); free(tmdbuffer); return ver; }