DSTATUS disk_initialize(BYTE drv) { s32 retval = 0; #ifdef HW_RVL fstats *stats = (fstats*)memalign(32, sizeof(fstats)); #endif struct stat filestats; if((int)drv >= vff_totalmountedfs)return STA_NOINIT; #ifdef HW_RVL if(vff_types[(int)drv]==0)retval = ISFS_GetFileStats((s32)disk_vff_handles[(int)drv], stats); #endif if(vff_types[(int)drv]==1) { retval = fstat(fileno((FILE*)disk_vff_handles[(int)drv]), &filestats); } if(retval<0) { printf("getfilestats returned %d\n", retval); return STA_NOINIT; } #ifdef HW_RVL if(vff_types[(int)drv]==0)vff_filesizes[(int)drv] = stats->file_length; free(stats); #endif if(vff_types[(int)drv]==1)vff_filesizes[(int)drv] = filestats.st_size; //vff_filesizes[(int)drv] = (unsigned int)GetFileLength(disk_vff_handles[(int)drv]); vff_fatsizes[(int)drv] = VFF_GetFATSize(vff_filesizes[(int)drv]); vff_fat_types[(int)drv] = VFF_GetFATType(vff_filesizes[(int)drv]); printf("disk_init ok: filesize %x fatsize %x fat_type %d\n", vff_filesizes[(int)drv], vff_fatsizes[(int)drv], vff_fat_types[(int)drv]); return 0; }
int fileBrowser_WiiFS_readDir(fileBrowser_file* file, fileBrowser_file** dir){ static char dirents[32*(8+1+3+1)] __attribute__((aligned(32))); unsigned int numDirents = 32; // Call the corresponding ISFS function char* name = getAlignedName(&file->name); int ret = ISFS_ReadDir(name, dirents, &numDirents); // If it was not successful, just return the error if(ret < 0) return ret; // Convert the ISFS data to fileBrowser_files *dir = malloc( numDirents * sizeof(fileBrowser_file) ); int i; char* dirent = &dirents[0]; for(i=0; i<numDirents; ++i){ sprintf((*dir)[i].name, "%s/%s", name, dirent); // Collect info about this file int fd = ISFS_Open( getAlignedName((*dir)[i].name), 1 ); if(fd >= 0){ fstats* stats = memalign( 32, sizeof(fstats) ); ISFS_GetFileStats(fd, stats); (*dir)[i].attr = 0; (*dir)[i].size = stats->file_length; free(stats); ISFS_Close(fd); } else { (*dir)[i].attr = FILE_BROWSER_ATTR_DIR; (*dir)[i].size = 0; } (*dir)[i].offset = 0; while(*(dirent++)); // Advance to the next dirent } return numDirents; }
s32 read_file(char *filepath, u8 **buffer, u32 *filesize){ s32 Fd; int ret; if(buffer == NULL){ printf("NULL Pointer\n"); return -1; } Fd = ISFS_Open(filepath, ISFS_OPEN_READ); if (Fd < 0){ //printf("\n * ISFS_Open %s failed %d", filepath, Fd); //Pad_WaitButtons(); return Fd; } fstats *status; status = allocate_memory(sizeof(fstats)); if (status == NULL){ printf("Out of memory for status\n"); return -1; } ret = ISFS_GetFileStats(Fd, status); if (ret < 0){ printf("ISFS_GetFileStats failed %d\n", ret); ISFS_Close(Fd); free(status); return -1; } *buffer = allocate_memory(status->file_length); if (*buffer == NULL){ printf("Out of memory for buffer\n"); ISFS_Close(Fd); free(status); return -1; } ret = ISFS_Read(Fd, *buffer, status->file_length); if (ret < 0){ printf("ISFS_Read failed %d\n", ret); ISFS_Close(Fd); free(status); free(*buffer); return ret; } ISFS_Close(Fd); *filesize = status->file_length; free(status); return 0; }
int NandTitle::LoadFileFromNand(const char *filepath, u8 **outbuffer, u32 *outfilesize) { if(!filepath) return -1; fstats *stats = (fstats *) memalign(32, ALIGN32(sizeof(fstats))); if(!stats) return IPC_ENOMEM; int fd = ISFS_Open(filepath, ISFS_OPEN_READ); if(fd < 0) { free(stats); return fd; } int ret = ISFS_GetFileStats(fd, stats); if (ret < 0) { free(stats); ISFS_Close(fd); return ret; } u32 filesize = stats->file_length; free(stats); u8 *buffer = (u8 *) memalign(32, ALIGN32(filesize)); if(!buffer) { ISFS_Close(fd); return IPC_ENOMEM; } ret = ISFS_Read(fd, buffer, filesize); ISFS_Close(fd); if (ret < 0) { free(buffer); return ret; } *outbuffer = buffer; *outfilesize = filesize; return 0; }
u8 *ISFS_GetFile(u8 *path, u32 *size, s32 length) { *size = 0; s32 fd = ISFS_Open((const char *) path, ISFS_OPEN_READ); u8 *buf = NULL; static fstats stats ATTRIBUTE_ALIGN(32); if(fd >= 0) { if(ISFS_GetFileStats(fd, &stats) >= 0) { if(length <= 0) length = stats.file_length; if(length > 0) buf = (u8 *)MEM2_memalign(32, length); if(buf) { *size = stats.file_length; if(ISFS_Read(fd, (char*)buf, length) != length) { *size = 0; MEM2_free(buf); } } } ISFS_Close(fd); } if(*size > 0) { DCFlushRange(buf, *size); ICInvalidateRange(buf, *size); } return buf; }
bool U8NandArchive::SetFile( const char* nandPath ) { if(fst) free(fst); if(name_table) free(name_table); CloseFile(); // open file if( (fd = ISFS_Open( nandPath, ISFS_OPEN_READ ) ) < 0 ) { gprintf( "U8NandArchive: ISFS_Open( \"%s\" ) failed\n", nandPath ); return false; } // get file size fstats stats __attribute__(( aligned( 32 ) )); int ret = ISFS_GetFileStats( fd, &stats ); if( ret < 0 ) { CloseFile(); gprintf( "U8NandArchive: ISFS_GetFileStats( \"%s\" ) failed\n", nandPath ); return false; } // buffer for reading the header and stuff u8* buffer = (u8*)memalign( 32, 0x800 ); if( !buffer ) { CloseFile(); gprintf( "U8NandArchive: enomem\n" ); return false; } // read a chunk big enough that it should contain the U8 header if there is going to be one if( (ret = ISFS_Read( fd, buffer, 0x800 )) != 0x800 ) { free( buffer ); CloseFile(); gprintf( "U8NandArchive: ISFS_Read( 0x800 ) = %i\n", ret ); return false; } // find the start of the U8 data U8Header* tagStart = (U8Header*)FindU8Tag( buffer, ret ); if( !tagStart ) { free( buffer ); CloseFile(); gprintf( "U8NandArchive: didn't see a U8 tag\n" ); return false; } // remember where in the file the U8 starts dataOffset = ( (u8*)tagStart - buffer ); // allocate memory and read the fst if( !(fst = (FstEntry *)memalign( 32, RU( tagStart->dataOffset - dataOffset, 32 ) ) ) || ( ISFS_Seek( fd, dataOffset + tagStart->rootNodeOffset, SEEK_SET ) != (s32)( dataOffset + tagStart->rootNodeOffset ) ) || ( ISFS_Read( fd, fst, tagStart->dataOffset - dataOffset ) != (s32)( tagStart->dataOffset - dataOffset ) ) || ( fst->filelen * 0xC > tagStart->dataOffset ) ) { dataOffset = 0; free( buffer ); if( fst ) free( fst ); CloseFile(); gprintf( "U8NandArchive: error reading fst\n" ); } // set name table pointer u32 name_table_offset = fst->filelen * 0xC; name_table = ((char *)fst) + name_table_offset; free( buffer ); return true; }
void load() { u32 file_size; static fstats filestats_settings ATTRIBUTE_ALIGN(32); static fstats filestats_appios ATTRIBUTE_ALIGN(32); static u8 filearray_settings[1024] ATTRIBUTE_ALIGN(32); static u8 filearray_appios[1024] ATTRIBUTE_ALIGN(32); #if defined(STBOOT) || defined(STBOOTVWII) Settings.ios_dat = "/title/00010001/48424630/data/appios.dat"; Settings.dir_dat = "/title/00010001/48424630/data/list.dat"; Settings.settings_dat = "/title/00010001/48424630/data/settings.dat"; #else Settings.ios_dat = "/title/00010001/54484246/data/appios.dat"; Settings.dir_dat = "/title/00010001/54484246/data/list.dat"; Settings.settings_dat = "/title/00010001/54484246/data/settings.dat"; #endif AvailableCategoryLoad(Settings.dir_dat); // get settings s32 fd; fd = ISFS_Open(Settings.settings_dat.c_str(), ISFS_OPEN_READ); if (fd <= 0) ISFS_Close(fd); ISFS_GetFileStats(fd, &filestats_settings); file_size = ISFS_Read(fd, filearray_settings, filestats_settings.file_length); ISFS_Close(fd); if(file_size >= 0) { string source = (char*)filearray_settings; if(get_setting(source, "device_dat") != "") Settings.device_dat = get_setting(source, "device_dat"); if (get_setting(source, "theme") != "") { sprintf (Options.theme, get_setting(source, "theme").c_str()); theme(check_path(Settings.device_dat + ":/config/HBF/themes/") + Options.theme + "/"); } if(get_setting(source, "language") != "") { sprintf (Options.language, get_setting(source, "language").c_str()); ini_Open(check_path(Settings.device_dat + ":/config/HBF/languages/") + Options.language + ".lang"); AvailableCategory.categories[0] = tr(Settings.category_name_all); } if(get_setting(source, "font") != "") sprintf (Options.font, get_setting(source, "font").c_str()); if(get_setting(source, "slide_effect") != "") Options.slide_effect = atoi(get_setting(source, "slide_effect").c_str()); if(get_setting(source, "last_category_name") != "") { if(KategorieNr(get_setting(source, "last_category_name")) != -1) Settings.current_category = KategorieNr(get_setting(source, "last_category_name").c_str()); } if(get_setting(source, "last_category") != "") { Options.last_category = atoi(get_setting(source, "last_category").c_str()); if(Options.last_category == 1) Options.last_category = Settings.current_category +1; } if(get_setting(source, "last_app_name") != "") Settings.startingAppName = get_setting(source, "last_app_name"); if(get_setting(source, "apps_nr") != "") { Options.apps = atoi(get_setting(source, "apps_nr").c_str()); if(Options.apps > 5) Options.apps = 5; else if(Options.apps < 4) Options.apps = 4; } if(get_setting(source, "quick_start") != "") Options.quick_start = atoi(get_setting(source, "quick_start").c_str()); if(get_setting(source, "show_all") != "") Options.show_all = atoi(get_setting(source, "show_all").c_str()); if(get_setting(source, "navigation") != "") Options.navigation = atoi(get_setting(source, "navigation").c_str()); if(get_setting(source, "sdgecko") != "") Options.sdgecko = atoi(get_setting(source, "sdgecko").c_str()); #ifndef VWII if(get_setting(source, "bootmii_boot2") != "") Options.bootmii_boot2 = atoi(get_setting(source, "bootmii_boot2").c_str()); #endif if(get_setting(source, "network") != "") { Options.network = atoi(get_setting(source, "network").c_str()); Options.temp_network = Options.network; } if(get_setting(source, "wifigecko") != "") { Options.wifigecko = atoi(get_setting(source, "wifigecko").c_str()); Options.temp_wifigecko = Options.wifigecko; } if(get_setting(source, "newrevtext") != "") { Options.newrevtext = atoi(get_setting(source, "newrevtext").c_str()); Options.temp_newrevtext = Options.newrevtext; } if(get_setting(source, "code") != "") { sprintf (Settings.code, get_setting(source, "code").c_str()); strcpy (Options.temp_code, Settings.code); } if(get_setting(source, "grid") != "") Settings.grid = atoi(get_setting(source, "grid").c_str()); if(get_setting(source, "device") != "") Settings.device = get_setting(source, "device"); if(get_setting(source, "device_icon") != "") Options.device_icon = atoi(get_setting(source, "device_icon").c_str()); if(get_setting(source, "wiiload_ahb") != "") Options.wiiload_ahb = atoi(get_setting(source, "wiiload_ahb").c_str()); if(get_setting(source, "wiiload_ios") != "") Options.wiiload_ios = atoi(get_setting(source, "wiiload_ios").c_str()); if(get_setting(source, "system") != "") Settings.system = atoi(get_setting(source, "system").c_str()); if(get_setting(source, "top") != "") Settings.top = atoi(get_setting(source, "top").c_str()); if(get_setting(source, "bottom") != "") Settings.bottom = atoi(get_setting(source, "bottom").c_str()); if(get_setting(source, "left") != "") Settings.left = atoi(get_setting(source, "left").c_str()); if(get_setting(source, "right") != "") Settings.right = atoi(get_setting(source, "right").c_str()); } // get appios fd = ISFS_Open(Settings.ios_dat.c_str(), ISFS_OPEN_READ); if (fd <= 0) ISFS_Close(fd); ISFS_GetFileStats(fd, &filestats_appios); file_size = ISFS_Read(fd, filearray_appios, filestats_appios.file_length); ISFS_Close(fd); if(file_size >= 0) { string line; istringstream in((char*)filearray_appios); while(getline(in, line)) appios.push_back(app_ios(line.substr(0, line.find(" = ")), atoi(line.substr(line.find(" = ") +3).c_str()))); } }
static int _ISFS_open_r(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) { FILE_STRUCT *file = (FILE_STRUCT *)fileStruct; char *abspath = malloc(ISFS_MAXPATHLEN); if(!abspath) { r->_errno = ENOMEM; return -1; } char *ptr = strchr(path, ':'); if (ptr != NULL) snprintf(abspath, ISFS_MAXPATHLEN, "%s", ptr + 1); else snprintf(abspath, ISFS_MAXPATHLEN, "%s/%s", current->entry->abspath, path); RemoveDoubleSlash(abspath); if (!READ_ONLY && (flags & O_CREAT)) { int iOwnerPerm = 0; int iGroupPerm = 0; int iOtherPerm = 0; if (flags & S_IRUSR) iOwnerPerm |= ISFS_OPEN_READ; if (flags & S_IWUSR) iOwnerPerm |= ISFS_OPEN_WRITE; if (flags & S_IRGRP) iGroupPerm |= ISFS_OPEN_READ; if (flags & S_IWGRP) iGroupPerm |= ISFS_OPEN_WRITE; if (iGroupPerm & S_IROTH) iOtherPerm |= ISFS_OPEN_READ; if (flags & S_IWOTH) iOtherPerm |= ISFS_OPEN_WRITE; ISFS_CreateFile(abspath, 0, iOwnerPerm, iGroupPerm, iOtherPerm); } int iOpenMode = 0; if ((flags & 0x03) == O_RDONLY) iOpenMode |= ISFS_OPEN_READ; if (!READ_ONLY && ((flags & 0x03) == O_WRONLY)) iOpenMode |= ISFS_OPEN_WRITE; if ((flags & 0x03) == O_RDWR) iOpenMode |= READ_ONLY ? ISFS_OPEN_READ : ISFS_OPEN_RW; file->fd = ISFS_Open(abspath, iOpenMode); free(abspath); if (file->fd < 0) { if (file->fd == ISFS_EINVAL) r->_errno = EACCES; else r->_errno = -file->fd; return -1; } file->flags = flags; file->mode = mode; if (ISFS_GetFileStats(file->fd, &filest) == ISFS_OK) file->size = filest.file_length; if (!READ_ONLY && (flags & O_APPEND)) ISFS_Seek(file->fd, 0, SEEK_END); return (int)file; }
static bool read_directory(DIR_ENTRY *parent) { if(!parent || !parent->abspath) return false; u32 fileCount; if(parent->size != 0 && is_dir(parent)) { fileCount = parent->size; } else { s32 ret = ISFS_ReadDir(parent->abspath, NULL, &fileCount); if (ret != ISFS_OK) { return false; } } parent->flags = FLAG_DIR; parent->size = fileCount; parent->childCount = 0; if(strcmp(parent->abspath, "/") != 0) { DIR_ENTRY *child = add_child_entry(parent, "."); if (!child) return false; child->flags = FLAG_DIR; child->size = 0; child = add_child_entry(parent, ".."); if (!child) return false; child->flags = FLAG_DIR; child->size = 0; } if (fileCount > 0) { char *buffer = (char *) memalign(32, ISFS_MAXPATHLEN * fileCount); if(!buffer) return false; s32 ret = ISFS_ReadDir(parent->abspath, buffer, &fileCount); if (ret != ISFS_OK) { free(buffer); return false; } u32 fileNum; char *name = buffer; for (fileNum = 0; fileNum < fileCount; fileNum++) { DIR_ENTRY *child = add_child_entry(parent, name); if (!child) { free(buffer); return false; } name += strlen(name) + 1; u32 childFileCount; ret = ISFS_ReadDir(child->abspath, NULL, &childFileCount); if (ret == ISFS_OK) { child->flags = FLAG_DIR; child->size = childFileCount; } else { s32 fd = ISFS_Open(child->abspath, ISFS_OPEN_READ); if (fd >= 0) { if (ISFS_GetFileStats(fd, &filest) == ISFS_OK) child->size = filest.file_length; ISFS_Close(fd); } } } free(buffer); } return true; }
s8 PatchTMD( u8 delete_mode ) { Nand_Permissions Perm; memset(&Perm,0,sizeof(Nand_Permissions)); u8 SaveTmd = 0; SHA1 sha; // SHA-1 class sha.Reset(); u32 FileHash[5]; u8 *TMD_chk = NULL; s32 fd = 0; s32 r = 0; #ifdef _DEBUG gprintf("Path : %s\n",TMD_Path); #endif r = ISFS_GetAttr(TMD_Path, &Perm.owner, &Perm.group, &Perm.attributes, &Perm.ownerperm, &Perm.groupperm, &Perm.otherperm); if(r < 0 ) { //attribute getting failed. returning to default printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING : failed to get file's permissions. using defaults\n"); printf("\x1b[%u;%dm", 37, 1); gprintf("permission failure on desination! error %d\n",r); gprintf("writing with max permissions\n"); Perm.ownerperm = 3; Perm.groupperm = 3; Perm.otherperm = 0; } else { gprintf("r %d owner %d group %d attributes %X perm:%X-%X-%X\n", r, Perm.owner, Perm.group, Perm.attributes, Perm.ownerperm, Perm.groupperm, Perm.otherperm); } if(delete_mode == 0) { gprintf("patching TMD...\n"); printf("Patching TMD..."); } else { //return 1; gprintf("restoring TMD...\n"); printf("Restoring System Menu TMD...\n"); } fd = ISFS_Open(TMD_Path2,ISFS_OPEN_READ); if(fd < 0) { if(delete_mode) { printf("TMD backup not found. leaving TMD alone...\n"); return 1; } else { //got to make tmd copy :) gprintf("Making tmd backup...\n"); r = nand_copy(TMD_Path2,tmd_buf,tmd_size,Perm); if ( r < 0) { gprintf("Failure making TMD backup.error %d\n",r); printf("TMD backup/Patching Failure : error %d",r); goto _return; } } fd = 0; } ISFS_Close(fd); gprintf("TMD backup found\n"); //not so sure why we'd want to delete the tmd modification but ok... if(delete_mode) { if ( nand_copy(TMD_Path2,TMD_Path,Perm) < 0) { if(r == -80) { //checksum issues printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\nInstaller could not calculate the Checksum when restoring the TMD back!\n"); printf("the TMD however was copied...\n"); printf("Do you want to Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { nand_copy(TMD_Path,TMD_Path2,Perm); abort("TMD restoring failure."); } } else { printf("\x1b[%u;%dm", 33, 1); printf("UNABLE TO RESTORE THE SYSTEM MENU TMD!!!\n\nTHIS COULD BRICK THE WII SO PLEASE REINSTALL SYSTEM MENU\nWHEN RETURNING TO THE HOMEBREW CHANNEL!!!\n\n"); printf("\x1b[%u;%dm", 37, 1); printf("press A to return to the homebrew channel\n"); nand_copy(TMD_Path,TMD_Path2,Perm); UserYesNoStop(); exit(0); } } else ISFS_Delete(TMD_Path2); return 1; } else { //check if version is the same STACK_ALIGN(fstats,TMDb_status,sizeof(fstats),32); static u8 tmdb_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); static signed_blob *mbTMD; static tmd* pbTMD; fd = ISFS_Open(TMD_Path2,ISFS_OPEN_READ); if (fd < 0) { gprintf("TMD bCheck : failed to open source : %s\n",TMD_Path2); goto patch_tmd; } r = ISFS_GetFileStats(fd,TMDb_status); if (r < 0) { gprintf("TMD bCheck : Failed to get information about %s!\n",TMD_Path2); ISFS_Close(fd); goto patch_tmd; } memset(tmdb_buf,0,MAX_SIGNED_TMD_SIZE); r = ISFS_Read(fd,tmdb_buf,TMDb_status->file_length); if (r < 0) { gprintf("TMD bCheck : Failed to Read Data from %s!\n",TMD_Path2); ISFS_Close(fd); goto patch_tmd; } ISFS_Close(fd); mbTMD = (signed_blob *)tmdb_buf; pbTMD = (tmd*)SIGNATURE_PAYLOAD(mbTMD); if (pbTMD->title_version != rTMD->title_version) { gprintf("TMD bCheck : backup TMD version mismatch: %d & %d\n",rTMD->title_version,pbTMD->title_version); //got to make tmd copy :) r = nand_copy(TMD_Path2,tmd_buf,tmd_size,Perm); if ( r < 0) { gprintf("TMD bCheck : Failure making TMD backup.error %d\n",r); printf("TMD backup/Patching Failure : error %d",r); goto _return; } } else gprintf("TMD bCheck : backup TMD is correct\n"); r = 0; } patch_tmd: gprintf("detected access rights : 0x%08X\n",rTMD->access_rights); if(rTMD->access_rights == 0x03) { gprintf("no AHBPROT modification needed\n"); } else { rTMD->access_rights = 0x03; DCFlushRange(rTMD,sizeof(tmd)); if(rTMD->access_rights != 0x03) { gprintf("rights change failure.\n"); goto _return; } SaveTmd++; } gprintf("checking Boot app SHA1 hash...\n"); gprintf("bootapp ( %d ) SHA1 hash = %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",rTMD->boot_index ,rTMD->contents[rTMD->boot_index].hash[0],rTMD->contents[rTMD->boot_index].hash[1],rTMD->contents[rTMD->boot_index].hash[2],rTMD->contents[rTMD->boot_index].hash[3] ,rTMD->contents[rTMD->boot_index].hash[4],rTMD->contents[rTMD->boot_index].hash[5],rTMD->contents[rTMD->boot_index].hash[6],rTMD->contents[rTMD->boot_index].hash[7] ,rTMD->contents[rTMD->boot_index].hash[8],rTMD->contents[rTMD->boot_index].hash[9],rTMD->contents[rTMD->boot_index].hash[10],rTMD->contents[rTMD->boot_index].hash[11] ,rTMD->contents[rTMD->boot_index].hash[12],rTMD->contents[rTMD->boot_index].hash[13],rTMD->contents[rTMD->boot_index].hash[14],rTMD->contents[rTMD->boot_index].hash[15] ,rTMD->contents[rTMD->boot_index].hash[16],rTMD->contents[rTMD->boot_index].hash[17],rTMD->contents[rTMD->boot_index].hash[18],rTMD->contents[rTMD->boot_index].hash[19]); gprintf("generated priiloader SHA1 : "); sha.Reset(); sha.Input(priiloader_app,priiloader_app_size); if (!sha.Result(FileHash)) { gprintf("could not compute Hash of Priiloader!\n"); r = -1; goto _return; } if (!memcmp(rTMD->contents[rTMD->boot_index].hash, FileHash, sizeof(FileHash) ) ) { gprintf("no SHA hash change needed\n"); } else { memcpy(rTMD->contents[rTMD->boot_index].hash,FileHash,sizeof(FileHash)); gprintf("%08x %08x %08x %08x %08x\n",FileHash[0],FileHash[1],FileHash[2],FileHash[3],FileHash[4]); DCFlushRange(rTMD,sizeof(tmd)); SaveTmd++; } if(SaveTmd > 0) { gprintf("saving TMD\n"); r = nand_copy(TMD_Path,tmd_buf,tmd_size,Perm); if(r < 0 ) { gprintf("nand_copy failure. error %d\n",r); if(r == -80) goto _checkreturn; else goto _return; } } else { gprintf("no TMD mod's needed\n"); printf("no TMD modifications needed\n"); goto _return; } printf("Done\n"); _return: if (fd < r) { r = fd; } if(fd) { ISFS_Close(fd); } if (r < 0) { printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\nInstaller couldn't Patch the system menu TMD.\n"); printf("Priiloader could still end up being installed but could end up working differently\n"); printf("Do you want the Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { fd = ISFS_Open(TMD_Path2,ISFS_OPEN_RW); if(fd >= 0) { //the backup is there. as safety lets copy it back. ISFS_Close(fd); nand_copy(TMD_Path2,TMD_Path,Perm); } abort("TMD failure"); return -1; } else { nand_copy(TMD_Path2,TMD_Path,Perm); printf("\nDone!\n"); return 1; } return r; } else return 1; _checkreturn: if(fd) { ISFS_Close(fd); } if(TMD_chk) { free(TMD_chk); TMD_chk = NULL; } printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\n Installer could not calculate the Checksum for the TMD!"); printf("\nbut Patch write was successfull.\n"); printf("Do you want the Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { printf("reverting changes...\n"); nand_copy(TMD_Path2,TMD_Path,Perm); abort("TMD Patch failure\n"); } else { printf("\nDone!\n"); } return -80; }
s32 nand_copy(const char *source, const char *destination,Nand_Permissions src_perm) { //variables u8 *buffer = NULL; STACK_ALIGN(fstats,status,sizeof(fstats),32); s32 file_handler, ret; u32 FileHash_D1[5]; memset(FileHash_D1,0,5); u32 FileHash_D2[5]; memset(FileHash_D2,0xFF,5); //place different data in D2 so that if something goes wrong later on, the comparison will fail SHA1 sha; sha.Reset(); //variables - temp dir & SHA1 check char temp_dest[ISFS_MAXPATH]; memset(temp_dest,0,ISFS_MAXPATH); char *ptemp = NULL; u8 temp = 0; //get temp filename ptemp = strstr(destination,"/"); while(ptemp != NULL && strstr(ptemp+1,"/") != NULL) { ptemp = strstr(ptemp+1,"/"); } if(ptemp[0] == '/') { ptemp = ptemp+1; } memset(temp_dest,0,ISFS_MAXPATH); sprintf(temp_dest,"/tmp/%s",ptemp); //get data into pointer from original file file_handler = ISFS_Open(source,ISFS_OPEN_READ); if (file_handler < 0) { gprintf("failed to open source : %s\n",source); return file_handler; } ret = ISFS_GetFileStats(file_handler,status); if (ret < 0) { printf("\n\nFailed to get information about %s!\n",source); sleepx(2); ISFS_Close(file_handler); return ret; } buffer = (u8 *)memalign(32,ALIGN32(status->file_length)); if (buffer == NULL) { gprintf("buffer failed to align\n"); sleepx(2); ISFS_Close(file_handler); return 0; } memset(buffer,0,status->file_length); ret = ISFS_Read(file_handler,buffer,status->file_length); if (ret < 0) { printf("\n\nFailed to Read Data from %s!\n",source); sleepx(2); ISFS_Close(file_handler); free(buffer); buffer = NULL; return ret; } ISFS_Close(file_handler); //everything read into buffer. generate SHA1 hash of the buffer sha.Input(buffer,status->file_length); if (!sha.Result(FileHash_D1)) { gprintf("could not compute Hash of D1!\n"); free(buffer); buffer = NULL; return -80; } sha.Reset(); //done, lets create temp file and write :') ISFS_Delete(temp_dest); ISFS_CreateFile(temp_dest,src_perm.attributes,src_perm.ownerperm,src_perm.groupperm,src_perm.otherperm); //created. opening it... file_handler = ISFS_Open(temp_dest,ISFS_OPEN_RW); if (file_handler < 0) { gprintf("failed to open destination : %s\n",temp_dest); ISFS_Delete(temp_dest); free(buffer); buffer = NULL; return file_handler; } ret = ISFS_Write(file_handler,buffer,status->file_length); if (ret < 0) { gprintf("failed to write destination : %s\n",destination); ISFS_Close(file_handler); ISFS_Delete(temp_dest); free(buffer); buffer = NULL; return ret; } //write done. reopen file for reading and compare SHA1 hash ISFS_Close(file_handler); free(buffer); buffer = NULL; memset(status,0,sizeof(fstats)); file_handler = ISFS_Open(temp_dest,ISFS_OPEN_READ); if(!file_handler) { temp = -1; goto free_and_Return; } ret = ISFS_GetFileStats(file_handler,status); if (ret < 0) { ISFS_Close(file_handler); temp = -2; goto free_and_Return; } buffer = (u8 *)memalign(32,ALIGN32(status->file_length)); if (buffer == NULL) { gprintf("buffer failed to align\n"); ISFS_Close(file_handler); temp = -3; goto free_and_Return; } memset(buffer,0,status->file_length); if( ISFS_Read(file_handler,buffer,status->file_length) < 0 ) { temp = -4; goto free_and_Return; } ISFS_Close(file_handler); sha.Reset(); sha.Input(buffer,status->file_length); free(buffer); buffer = NULL; if (!sha.Result(FileHash_D2)) { gprintf("could not compute Hash of D2!\n"); return -80; } sha.Reset(); /*gprintf("sha1 original : %x %x %x %x %x\nsha1 written : %x %x %x %x %x\n", FileHash_D1[0],FileHash_D1[1],FileHash_D1[2],FileHash_D1[3],FileHash_D1[4], FileHash_D2[0],FileHash_D2[1],FileHash_D2[2],FileHash_D2[3],FileHash_D2[4]);*/ if (!memcmp(FileHash_D1,FileHash_D2,sizeof(FileHash_D1))) { gprintf("nand_copy : SHA1 hash success\n"); ISFS_Delete(destination); ret = ISFS_Rename(temp_dest,destination); gprintf("ISFS_Rename ret %d\n",ret); if ( ret < 0) temp = -5; goto free_and_Return; } else { temp = -6; goto free_and_Return; } free_and_Return: if(buffer) { free(buffer); buffer = NULL; } if (temp < 0) { gprintf("nand_copy temp %d fail o.o;\n",temp); ISFS_Delete(temp_dest); return -80; } return 1; }
s32 nand_copy(const char *destination,u8* Buf_To_Write_to_Copy, u32 buf_size,Nand_Permissions src_perm) { if( Buf_To_Write_to_Copy == NULL || buf_size < 1 ) { return -1; } s32 ret, dest_handler; gprintf("owner %d group %d attributes %X perm:%X-%X-%X\n", src_perm.owner, (u32)src_perm.group, (u32)src_perm.attributes, (u32)src_perm.ownerperm, (u32)src_perm.groupperm, (u32)src_perm.otherperm); //extract filename from destination char temp_dest[ISFS_MAXPATH]; memset(temp_dest,0,ISFS_MAXPATH); char *ptemp = NULL; ptemp = strstr(destination,"/"); while(ptemp != NULL && strstr(ptemp+1,"/") != NULL) { ptemp = strstr(ptemp+1,"/"); } if(ptemp[0] == '/') { ptemp = ptemp+1; } //create temp path memset(temp_dest,0,ISFS_MAXPATH); sprintf(temp_dest,"/tmp/%s",ptemp); ISFS_Delete(temp_dest); //and go for it ret = ISFS_CreateFile(temp_dest,src_perm.attributes,src_perm.ownerperm,src_perm.groupperm,src_perm.otherperm); if (ret != ISFS_OK) { printf("Failed to create file %s. ret = %d\n",temp_dest,ret); gprintf("Failed to create file %s. ret = %d\n",temp_dest,ret); return ret; } dest_handler = ISFS_Open(temp_dest,ISFS_OPEN_RW); if (dest_handler < 0) { gprintf("failed to open destination : %s\n",temp_dest); ISFS_Delete(temp_dest); return dest_handler; } ret = ISFS_Write(dest_handler,Buf_To_Write_to_Copy,buf_size); if (ret < 0) { gprintf("failed to write destination : %s\n",temp_dest); ISFS_Close(dest_handler); ISFS_Delete(temp_dest); return ret; } ISFS_Close(dest_handler); s32 temp = 0; u8 *Data2 = NULL; STACK_ALIGN(fstats,D2stat,sizeof(fstats),32); /*if (D2stat == NULL) { temp = -1; goto free_and_Return; }*/ dest_handler = ISFS_Open(temp_dest,ISFS_OPEN_RW); if(dest_handler < 0) { gprintf("temp_dest open error %d\n",dest_handler); temp = -2; goto free_and_Return; } temp = ISFS_GetFileStats(dest_handler,D2stat); if(temp < 0) { goto free_and_Return; } Data2 = (u8*)memalign(32,ALIGN32(D2stat->file_length)); if (Data2 == NULL) { temp = -3; goto free_and_Return; } if( ISFS_Read(dest_handler,Data2,D2stat->file_length) > 0 ) { if( !CompareSha1Hash(Buf_To_Write_to_Copy,buf_size,Data2,D2stat->file_length)) { temp = -4; goto free_and_Return; } } else { temp = -5; goto free_and_Return; } if(Data2) { free(Data2); Data2 = NULL; } ISFS_Close(dest_handler); //so it was written to /tmp correctly. lets call ISFS_Rename and compare AGAIN ISFS_Delete(destination); ret = ISFS_Rename(temp_dest,destination); if(ret < 0 ) { gprintf("nand_copy(buf) : rename returned %d\n",ret); temp = -6; goto free_and_Return; } free_and_Return: if(Data2 != NULL) { free(Data2); Data2 = NULL; } ISFS_Close(dest_handler); if (temp < 0) { gprintf("temp %d\n",temp); //ISFS_Delete(destination); return -80; } return 1; }
s8 WritePriiloader( bool priiloader_found ) { s32 ret = 0; s32 fd = 0; Nand_Permissions SysPerm; if(priiloader_found == false) { memset(&SysPerm,0,sizeof(Nand_Permissions)); SysPerm.otherperm = 3; SysPerm.groupperm = 3; SysPerm.ownerperm = 3; //system menu coping printf("Moving System Menu app..."); ret = nand_copy(original_app,copy_app,SysPerm); if (ret < 0) { if (ret == -80) { //checksum issues printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\n Installer could not calculate the Checksum for the System menu app"); printf("\nbut Copy was successfull.\n"); printf("Do you want the Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { printf("reverting changes...\n"); ISFS_Delete(copy_app); abort("System Menu Copying Failure"); } else printf("\nDone!\n"); } else abort("\nUnable to move the system menu. error %d",ret); } else { gprintf("Moving System Menu Done\n"); printf("Done!\n"); } } ret = 0; //sys_menu app moved. lets write priiloader STACK_ALIGN(fstats,status,sizeof(fstats),32); memset(&SysPerm,0,sizeof(Nand_Permissions)); SysPerm.otherperm = 3; SysPerm.groupperm = 3; SysPerm.ownerperm = 3; printf("Writing Priiloader app..."); gprintf("Writing Priiloader\n"); char temp_dest[ISFS_MAXPATH]; memset(temp_dest,0,ISFS_MAXPATH); char *ptemp = NULL; ptemp = strstr(original_app,"/"); while(ptemp != NULL && strstr(ptemp+1,"/") != NULL) { ptemp = strstr(ptemp+1,"/"); } if(ptemp[0] == '/') { ptemp = ptemp+1; } memset(temp_dest,0,ISFS_MAXPATH); sprintf(temp_dest,"/tmp/%s",ptemp); ISFS_Delete(temp_dest); ret = ISFS_CreateFile(temp_dest,SysPerm.attributes,SysPerm.ownerperm,SysPerm.groupperm,SysPerm.otherperm); fd = ISFS_Open(temp_dest,ISFS_OPEN_RW); if (fd < 0) { gprintf("error %d\n",fd); abort("\nFailed to open file for Priiloader writing"); } ret = ISFS_Write(fd,priiloader_app,priiloader_app_size); if (ret < 0 ) //check if the app was writen correctly { ISFS_Close(fd); ISFS_Delete(copy_app); ISFS_Delete(temp_dest); gprintf("Write failed. ret %d\n",ret); abort("\nWrite of Priiloader app failed"); } ISFS_Close(fd); //SHA1 check here fd = ISFS_Open(temp_dest,ISFS_OPEN_READ); if (fd < 0) { ISFS_Delete(copy_app); abort("\nFailed to open file for Priiloader checking"); } if (ISFS_GetFileStats(fd,status) < 0) { ISFS_Close(fd); ISFS_Delete(copy_app); abort("Failed to get stats of %s. System Menu Recovered",temp_dest); } else { if ( status->file_length != priiloader_app_size ) { ISFS_Close(fd); ISFS_Delete(copy_app); abort("Written Priiloader app isn't the correct size.System Menu Recovered"); } else { gprintf("Size Check Success\n"); printf("Size Check Success!\n"); } } u8 *AppData = (u8 *)memalign(32,ALIGN32(status->file_length)); if (AppData) ret = ISFS_Read(fd,AppData,status->file_length); else { ISFS_Close(fd); ISFS_Delete(copy_app); abort("Checksum comparison Failure! MemAlign Failure of AppData\n"); } ISFS_Close(fd); if (ret < 0) { if (AppData) { free(AppData); AppData = NULL; } ISFS_Delete(copy_app); abort("Checksum comparison Failure! read of priiloader app returned %u\n",ret); } if(CompareSha1Hash((u8*)priiloader_app,priiloader_app_size,AppData,status->file_length)) printf("Checksum comparison Success!\n"); else { if (AppData) { free(AppData); AppData = NULL; } ISFS_Delete(copy_app); abort("Checksum comparison Failure!\n"); } if (AppData) { free(AppData); AppData = NULL; } // rename and do a final SHA1 chezck ISFS_Delete(original_app); ret = ISFS_Rename(temp_dest,original_app); if(ret < 0 ) { gprintf("WritePriiloader : rename returned %d\n",ret); nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("\nFailed to Write Priiloader : error Ren %d",ret); } printf("Done!!\n"); gprintf("Wrote Priiloader App.Checking Installation\n"); printf("\nChecking Priiloader Installation...\n"); memset(status,0,sizeof(fstats)); fd = ISFS_Open(original_app,ISFS_OPEN_READ); if (fd < 0) { nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("\nFailed to open file for Priiloader checking"); } if (ISFS_GetFileStats(fd,status) < 0) { ISFS_Close(fd); nand_copy(copy_app,original_app,SysPerm); abort("Failed to get stats of %s. System Menu Recovered",original_app); } else { if ( status->file_length != priiloader_app_size ) { ISFS_Close(fd); nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Written Priiloader app isn't the correct size.System Menu Recovered"); } else { gprintf("Size Check Success\n"); printf("Size Check Success!\n"); } } AppData = (u8 *)memalign(32,ALIGN32(status->file_length)); if (AppData != NULL) ret = ISFS_Read(fd,AppData,status->file_length); else { ISFS_Close(fd); nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Checksum comparison Failure! MemAlign Failure of AppData\n"); } ISFS_Close(fd); if (ret < 0) { if (AppData) { free(AppData); AppData = NULL; } nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Checksum comparison Failure! read of priiloader app returned %u\n",ret); } if(CompareSha1Hash((u8*)priiloader_app,priiloader_app_size,AppData,status->file_length)) printf("Checksum comparison Success!\n"); else { if (AppData) { free(AppData); AppData = NULL; } nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Checksum comparison Failure!\n"); } if (AppData) { free(AppData); AppData = NULL; } gprintf("Priiloader Update Complete\n"); printf("Done!\n\n"); return 1; }
int NandTitle::ExtractFile(const char *nandPath, const char *filepath) { if(!nandPath || !filepath) return -1; char *strDup = strdup(filepath); if(!strDup) return -666; char *ptr = strrchr(strDup, '/'); if(!ptr) { free(strDup); return -333; } else { *ptr = 0; CreateSubfolder(strDup); free(strDup); } int done = 0; int fd = -1; int blocksize = 32*1024; u8 *buffer = (u8 *) memalign(32, ALIGN32(blocksize)); if(!buffer) return -666; fstats *stats = (fstats *) memalign(32, ALIGN32(sizeof(fstats))); if(!stats) { free(buffer); return -666; } do { fd = ISFS_Open(nandPath, ISFS_OPEN_READ); if(fd < 0) break; int ret = ISFS_GetFileStats(fd, stats); if (ret < 0) break; int filesize = stats->file_length; FILE *pFile = fopen(filepath, "wb"); if(!pFile) break; while(done < filesize) { if(filesize-done < blocksize) blocksize = filesize-done; ret = ISFS_Read(fd, buffer, blocksize); if(ret < 0) { done = ret; break; } fwrite(buffer, 1, ret, pFile); done += ret; } fclose(pFile); } while(0); free(buffer); free(stats); if(fd >= 0) ISFS_Close(fd); return done; }