Esempio n. 1
0
void RestoreSneekFolder (void)
{
    s32 fd;
    int ret;

    char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
    char pathBak[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);

    Debug ("RestoreSneekFolder [begin]");

    ISFS_Initialize ();

    sprintf (path, "/sneek/nandpath.bin");
    ret = ISFS_Delete (path);
    Debug ("RestoreSneekFolder: delete '%s' = %d", path, ret);

    sprintf (path, "/sneek/nandcfg.pl");
    ret = ISFS_Delete (path);
    Debug ("RestoreSneekFolder: delete '%s' = %d", path, ret);

    ret = sprintf (path, "/sneek/nandcfg.ch");
    ISFS_Delete (path);
    Debug ("RestoreSneekFolder: delete '%s' = %d", path, ret);

    sprintf (path, "/title/00000001/00000002/data/loader.ini");
    sprintf (pathBak, "/title/00000001/00000002/data/loader.bak");

    fd = ISFS_Open(pathBak, ISFS_OPEN_READ);
    if (fd > 0)
    {
        ISFS_Close(fd);

        ret = ISFS_Delete (path);
        Debug ("RestoreSneekFolder: delete '%s' = %d", path, ret);
        ret = ISFS_Rename (pathBak, path);
        Debug ("RestoreSneekFolder: rename '%s'->'%s' = %d", pathBak, path, ret);
    }

    sprintf (path, "/sneek/nandcfg.bin");
    sprintf (pathBak, "/sneek/nandcfg.bak");

    fd = ISFS_Open(pathBak, ISFS_OPEN_READ);
    if (fd > 0)
    {
        ISFS_Close(fd);

        ret = ISFS_Delete (path);
        Debug ("RestoreSneekFolder: delete '%s' = %d", path, ret);
        ret = ISFS_Rename (pathBak, path);
        Debug ("RestoreSneekFolder: rename '%s'->'%s' = %d", pathBak, path, ret);
    }

    ISFS_Deinitialize ();

    Debug ("RestoreSneekFolder [end]");
}
Esempio n. 2
0
void RestorePriiloader (int nidx)
{
    char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
    char pathBack[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);

    ISFS_Initialize();

    sprintf (path, "%s/title/00000001/00000002/data/main.bin", nandConfig->NandInfo[nidx]);
    sprintf (pathBack, "%s/title/00000001/00000002/data/main.bak", nandConfig->NandInfo[nidx]);

    ISFS_Delete (path);
    ISFS_Rename (pathBack, path);

    sprintf (path, "%s/title/00000001/00000002/data/loader.ini", nandConfig->NandInfo[nidx]);
    sprintf (pathBack, "%s/title/00000001/00000002/data/loader.bak", nandConfig->NandInfo[nidx]);

    ISFS_Delete (path);
    ISFS_Rename (pathBack, path);

    ISFS_Deinitialize ();
}
void NandSave::WriteFile(const char *file_name, u8 *content, u32 size)
{
	memset(&ISFS_Path, 0, ISFS_MAXPATH);
	if(file_name == NULL || content == NULL || size == 0)
		return;
	strcpy(ISFS_Path, file_name);
	ISFS_CreateFile(ISFS_Path, 0, 3, 3, 3);
	fd = ISFS_Open(ISFS_Path, ISFS_OPEN_WRITE);
	if(fd < 0)
		return;
	ret = ISFS_Write(fd, content, size);
	ISFS_Close(fd);
	if(ret < 0)
		ISFS_Delete(ISFS_Path);
}
Esempio n. 4
0
static s32 __Config_Delete(const char *filename)
{
	s32 ret;

	/* Open ISFS */
	ret = ISFS_Open();
	if (ret < 0)
		return ret;

	/* Delete file */
	ret = ISFS_Delete(filename);

	/* Close ISFS */
	ISFS_Close();

	return ret;
}
Esempio n. 5
0
void removeswitchmii(void)
{
  s32 ret;
  char filepath[256];

  if(switchmii == true)
  {
	sprintf(filepath, "/bootmii/switchtomii");
	
	ret = ISFS_Delete(filepath);
	
	if (ret < 0)
		printf("\nError! ISFS_Delete(%s) returned %d)\n", filepath, ret);

    switchmii = false;
  }
}
Esempio n. 6
0
s8 RemovePriiloader ( void )
{
    s32 fd = 0;
    Nand_Permissions SysPerm;
    memset(&SysPerm,0,sizeof(Nand_Permissions));
    SysPerm.otherperm = 3;
    SysPerm.groupperm = 3;
    SysPerm.ownerperm = 3;
    printf("Restoring System menu app...");
    s32 ret = nand_copy(copy_app,original_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 when coping the System menu app\n");
            printf("back! the app 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())
            {
                printf("reverting changes...\n");
                ISFS_Close(fd);
                ISFS_CreateFile(original_app,0,3,3,3);
                fd = ISFS_Open(original_app,ISFS_OPEN_RW);
                ISFS_Write(fd,priiloader_app,priiloader_app_size);
                ISFS_Close(fd);
                abort("System Menu Copying Failure");
            }
        }
        else
        {
            ISFS_CreateFile(original_app,0,3,3,3);
            fd = ISFS_Open(original_app,ISFS_OPEN_RW);
            ISFS_Write(fd,priiloader_app,priiloader_app_size);
            ISFS_Close(fd);
            abort("\nUnable to restore the system menu! (ret = %d)",ret);
        }
    }
    ret = ISFS_Delete(copy_app);
    printf("Done!\n");
    return 1;
}
Esempio n. 7
0
s32 Uninstall_DeleteTitle(u32 title_u, u32 title_l)
{
	s32 ret;
	char filepath[256];
	sprintf(filepath, "/title/%08x/%08x",  title_u, title_l);
	
	/* Remove title */
	//printf("\t\t- Deleting title file %s...", filepath);
	fflush(stdout);

	ret = ISFS_Delete(filepath);
	//if (ret < 0)
		//printf("\n\tError! ISFS_Delete(ret = %d)\n", ret);
	//else
		//printf(" OK!\n");

	return ret;
}
Esempio n. 8
0
s32 Uninstall_DeleteTicket(u32 title_u, u32 title_l)
{
	s32 ret;

	char filepath[256];
	sprintf(filepath, "/ticket/%08x/%08x.tik", title_u, title_l);
	
	/* Delete ticket */
	//printf("\t\t- Deleting ticket file %s...", filepath);
	fflush(stdout);

	ret = ISFS_Delete(filepath);
	//if (ret < 0)
		//printf("\n\tTicket delete failed (No ticket?) %d\n", ret);
	//else
		//printf(" OK!\n");
	return ret;
}
Esempio n. 9
0
void RestoreSM (int nidx)
{
    bool find = FALSE;
    char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
    char pathBack[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
    char *sm[] = {"00000088","00000085","0000008b","0000008e","00000098","00000095","0000009b","0000009e"};
    s32 smsize;
    bool issm = FALSE;

    ISFS_Initialize();

    int i;
    s32 fd;
    for (i = 0; i < sizeof(sm) / sizeof(char*); i++)
    {
        sprintf (path, "%s/title/00000001/00000002/content/%s.app", nandConfig->NandInfo[nidx], sm[i]);
        sprintf (pathBack, "%s/title/00000001/00000002/content/%s.bak", nandConfig->NandInfo[nidx], sm[i]);

        fd = ISFS_Open (path, ISFS_OPEN_READ);
        Debug ("ReplaceNandSystemMenu: checking %s (%d)", sm[i], fd);

        if (fd < 0) continue;
        smsize = ISFS_Seek(fd, 0, 2);

        Debug ("ReplaceNandSystemMenu: sm size %d", smsize);

        if (smsize > 1000000) // E' piu' grande di 1MB... e' il sistem menu
            issm = TRUE;

        ISFS_Close (fd);
        find = TRUE;
        break;
    }

    if (find && !issm)
    {
        // Restore filesistem
        ISFS_Delete (path);
        ISFS_Rename (pathBack, path);
    }

    ISFS_Deinitialize ();
}
Esempio n. 10
0
void renamefilesback(void)
{
  s32 ret;
  char filepath[256];
  char filepathold[256];
  
  if( armbootmii == true && armbootsneek == true )
  { 
    sprintf(filepath, "/bootmii/armbootsneek.bin");
    ret = ISFS_Delete(filepath);
	if (ret < 0)
		printf("\nError! ISFS_Delete(%s) returned %d)\n", filepath, ret);
	
	sprintf(filepathold, "/bootmii/armboot.bin");
	ret = ISFS_Rename(filepathold, filepath);
	if (ret < 0)
		printf("\nError! ISFS_Rename(%s, %s) returned %d)\n", filepathold, 
			filepath, ret);
	
	sprintf(filepathold, "/bootmii/armbootmii.bin");
	sprintf(filepath, "/bootmii/armboot.bin");
	ret = ISFS_Rename(filepathold, filepath);
	if (ret < 0)
		printf("\nError! ISFS_Rename(%s, %s) returned %d)\n", filepathold, 
			filepath, ret);	
  }
  if( armbootmii == true && armbootsneek == false ) 
  { 
    sprintf(filepath, "/bootmii/armbootsneek.bin");
	sprintf(filepathold, "/bootmii/armboot.bin");
	ret = ISFS_Rename(filepathold, filepath);
	if (ret < 0)
		printf("\nError! ISFS_Rename(%s, %s) returned %d)\n", filepathold, 
			filepath, ret);
	
	sprintf(filepathold, "/bootmii/armbootmii.bin");
	sprintf(filepath, "/bootmii/armboot.bin");
	ret = ISFS_Rename(filepathold, filepath);
	if (ret < 0)
		printf("\nError! ISFS_Rename(%s, %s) returned %d)\n", filepathold, 
			filepath, ret);				
  }
}
Esempio n. 11
0
s32 Downgrade_TMD_Revision(void *ptmd, u32 tmd_size, void *certs, u32 certs_size) 
{
	// The revison of the tmd used as paramter here has to be >= the revision of the installed tmd
	s32 ret;

	printf("Setting the revision to 0...\n");

	ret = ES_AddTitleStart(ptmd, tmd_size, certs, certs_size, NULL, 0);
	if (ret < 0) 
	{
		if (ret == -1035)
		{
			printf("Error: ES_AddTitleStart returned %d, maybe you need an updated Downgrader\n", ret);
		} else
		{
			printf("Error: ES_AddTitleStart returned %d\n", ret);
		}
		ES_AddTitleCancel();
		return ret;
	}

	s32 file;
	char *tmd_path = "/tmp/title.tmd";
	
	ret = ISFS_Delete(tmd_path);	
	if (ret < 0) 
	{
		printf("Error: ISFS_Delete returned %d\n", ret);
		ES_AddTitleCancel();
		ISFS_Deinitialize();
		return ret;
	}
	ret = ISFS_CreateFile(tmd_path, 0, 3, 3, 3);
	if (ret < 0) 
	{
		printf("Error: ISFS_CreateFile returned %d\n", ret);
		ES_AddTitleCancel();
		ISFS_Deinitialize();
		return ret;
	}

	file = ISFS_Open(tmd_path, ISFS_OPEN_RW);
	if (file < 0)
	{
		printf("Error: ISFS_Open returned %d\n", file);
		ES_AddTitleCancel();
		ISFS_Deinitialize();
		return file;
	}
	
	u8 *tmd = (u8 *)ptmd;
	tmd[0x1dc] = 0;
	tmd[0x1dd] = 0;
	
	ret = ISFS_Write(file, (u8 *)ptmd, tmd_size);
	if (ret < 0) 
	{
		printf("Error: ISFS_Write returned %d\n", ret);
		ISFS_Close(file);
		ES_AddTitleCancel();
		ISFS_Deinitialize();
		return ret;
	}

	ISFS_Close(file);
	ISFS_Deinitialize();

	ret = ES_AddTitleFinish();
	if (ret < 0) 
	{
		printf("Error: ES_AddTitleFinish returned %d\n", ret);
		return ret;
	}
	
	return 1;
}
bool NandSave::CheckSave()
{
	/* 10 million variables */
	u32 u8_bin_size = 0;
	u8 *u8_bin = NULL;
	u32 certSize = 0;
	signed_blob *certBuffer = NULL;
	u32 tmd_bin_size = 0;
	const signed_blob *tmd_bin = NULL;
	u32 tik_bin_size = 0;
	const signed_blob *tik_bin = NULL;
	u32 banner_bin_size = 0;
	const u8 *banner_bin = NULL;
	u32 entries = 0;
	/* May our banner already exist */
	memset(&ISFS_Path, 0, ISFS_MAXPATH);
	strcpy(ISFS_Path, BANNER_PATH);
	fd = ISFS_Open(ISFS_Path, ISFS_OPEN_READ);
	if(fd >= 0)
	{
		ISFS_Close(fd);
		gprintf("Found WiiFlow Save\n");
		goto done;
	}
	/* extract our archive */
	u8_bin = DecompressCopy(save_bin, save_bin_size, &u8_bin_size);
	if(u8_bin == NULL || u8_bin_size == 0)
		goto error;
	/* grab cert.sys */
	memset(&ISFS_Path, 0, ISFS_MAXPATH);
	strcpy(ISFS_Path, "/sys/cert.sys");
	certBuffer = (signed_blob*)ISFS_GetFile(ISFS_Path, &certSize, -1);
	if(certBuffer == NULL || certSize == 0)
		goto error;
	/* Install tik and tmd */
	tik_bin = (const signed_blob*)u8_get_file(u8_bin, "tik.bin", &tik_bin_size);
	if(tik_bin == NULL || tik_bin_size == 0)
		goto error;
	ret = ES_AddTicket(tik_bin, tik_bin_size, certBuffer, certSize, NULL, 0);
	if(ret < 0)
		goto error;
	tmd_bin = (const signed_blob*)u8_get_file(u8_bin, "tmd.bin", &tmd_bin_size);
	if(tmd_bin == NULL || tmd_bin_size == 0)
		goto error;
	ret = ES_AddTitleStart(tmd_bin, tmd_bin_size, certBuffer, certSize, NULL, 0);
	if(ret < 0)
		goto error;
	ret = ES_AddTitleFinish();
	if(ret < 0)
		goto error;
	/* WARNING dirty, delete tik again */
	memset(&ISFS_Path, 0, ISFS_MAXPATH);
	strcpy(ISFS_Path, "/ticket/00010000/57465346.tik");
	ret = ISFS_Delete(ISFS_Path);
	if(ret < 0)
		goto error;
	/* Delete the unused ticket folder */
	memset(&ISFS_Path, 0, ISFS_MAXPATH);
	strcpy(ISFS_Path, "/ticket/00010000");
	ret = ISFS_ReadDir(ISFS_Path, NULL, &entries);
	if(ret < 0)
		goto error;
	if(entries == 0)
	{
		ret = ISFS_Delete(ISFS_Path);
		if(ret < 0)
			goto error;
	}
	banner_bin = u8_get_file(u8_bin, "banner.bin", &banner_bin_size);
	if(banner_bin == NULL || banner_bin_size == 0)
		goto error;
	memset(&ISFS_Path, 0, ISFS_MAXPATH);
	strcpy(ISFS_Path, BANNER_PATH);
	/* Write our banner */
	ISFS_CreateFile(ISFS_Path, 0, 3, 3, 3);
	fd = ISFS_Open(ISFS_Path, ISFS_OPEN_WRITE);
	if(fd < 0)
		goto error;
	ret = ISFS_Write(fd, banner_bin, banner_bin_size);
	ISFS_Close(fd);
	if(ret < 0)
	{
		ISFS_Delete(ISFS_Path);
		goto error;
	}
	free(certBuffer);
	if(u8_bin != save_bin)
		free(u8_bin);
	gprintf("Created WiiFlow Save\n");
done:
	loaded = true;
	return loaded;

error:
	gprintf("Error while creating WiiFlow Save\n");
	loaded = false;
	ES_AddTitleCancel();
	if(certBuffer != NULL)
		free(certBuffer);
	certBuffer = NULL;
	if(u8_bin != NULL)
		free(u8_bin);
	u8_bin = NULL;
	tik_bin = NULL;
	tmd_bin = NULL;
	banner_bin = NULL;
	return loaded;
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
/*
	This creates the file in the TMP dir and then moves it to the destination overwriting it!
	
	To work correctly on the real nand we must have the same filename for the
	source and destination!
*/
s32 NANDWriteFileSafe( char *pathdst, void *data, u32 size )
{
	char *path = (char*)heap_alloc_aligned( 0, 0x40, 32 );
	s32 i=0;

//Extract filename

	//search backwards for slash
	for( i=strlen(pathdst); i > 0; --i )
		if( pathdst[i] == '/' )
			break;

	_sprintf( path, "/tmp%s", pathdst + i );

	s32 r = ISFS_CreateFile( path, 0, 3, 3, 3 );
	if( r == FS_EEXIST2 )
	{
		ISFS_Delete( path );
		r = ISFS_CreateFile( path, 0, 3, 3, 3 );
		if( r < 0 )
		{
			//dbgprintf("ISFS_CreateFile(%s):%d\n",path,r);
			heap_free( 0, path );
			return r;
		}
	} else {
		if( r < 0 )
		{
			//dbgprintf("ISFS_CreateFile(%s):%d\n",path,r);
			heap_free( 0, path );
			return r;
		}
	}

	s32 fd = IOS_Open( path, 2 );
	if( fd < 0 )
	{
		//dbgprintf("IOS_Open(%s):%d\n",path,r);
		heap_free( 0, path );
		return r;
	}

	r = IOS_Write( fd, data, size );
	if( r < 0 || r != size )
	{
		//dbgprintf("IOS_Write():%d\n",r);
		IOS_Close( fd );
		heap_free( 0, path );
		return r;
	}

	IOS_Close( fd );

	r = ISFS_Rename( path, pathdst );
	if( r < 0 )
	{
		//dbgprintf("ISFS_Rename(%s,%s):%d\n",path,pathdst,r);
		heap_free( 0, path );
		return r;
	}

	heap_free( 0, path );
	return r;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
int main(int argc, char* argv[])
{
	__exception_setreload(10);
	
	int i, ret;
	
	Init_Console();
	printf("\x1b[%u;%um", 37, false);
	
	PAD_Init();
	WPAD_Init();
	WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
	
	printheadline();
	
	ret = ahbprot_menu();
	if (ret < 0)
	{
		ret = ios_selectionmenu(236);
		if (ret > 0)
		{
			printf("\t- Reloading to IOS%d... ", ret);
			WPAD_Shutdown();
			IOS_ReloadIOS(ret);
			sleep(2);
			PAD_Init();
			WPAD_Init();
			WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
			printf("done.\n\n");
		} else
		if (ret == 0)
		{
			printf("\t- Proceeding without IOS reload...\n\n");
		} else {
			Reboot();
		}
	}
	
	resetscreen();
	printheadline();
	
	/* Initialize NAND FS */
	ISFS_Initialize();
	
	/* Do our stuff */
	char path[ISFS_MAXPATH];
	char *filenames[10] = { "misc.bin", "nwc24dl.bin", "nwc24fl.bin", "nwc24fls.bin", "nwc24msg.cbk", "nwc24msg.cfg", \
							"mbox/wc24recv.ctl", "mbox/wc24recv.mbx", "mbox/wc24send.ctl", "mbox/wc24send.mbx" };
	
	for (i = 0; i < 10; i++)
	{
		snprintf(path, MAX_CHARACTERS(path), "/shared2/wc24/%s", filenames[i]);
		
		printf("%u. Deleting \"%s\"... ", i + 1, path);
		ret = ISFS_Delete(path);
		if (ret < 0)
		{
			switch (ret)
			{
				case -1:
				case -102:
					printf("\n\t- Error: Permission denied!");
					break;
				case -2:
				case -105:
					printf("\n\t- Error: File exists!");
					break;
				case -4:
				case -101:
					printf("\n\t- Error: Invalid argument!");
					break;
				case -6:
				case -106:
					printf("\n\t- Error: File not found!");
					break;
				case -8:
				case -118:
					printf("\n\t- Error: Resource busy!");
					break;
				case -12:
				case -103:
				case -114:
					printf("\n\t- Error: NAND ECC failure!");
					break;
				case -22:
					printf("\n\t- Error: Memory allocation failed during request!");
					break;
				case -107:
				case -109:
					printf("\n\t- Error: Too many files open!");
					break;
				case -108:
					printf("\n\t- Error: Memory full!");
					break;
				case -110:
					printf("\n\t- Error: Path name is too long!");
					break;
				case -111:
					printf("\n\t- Error: File already open!");
					break;
				case -115:
					printf("\n\t- Error: Directory not empty!");
					break;
				case -116:
					printf("\n\t- Error: Max directory depth exceeded!");
					break;
				default:
					printf("\n\t- FATAL / UNKNOWN ERROR!!!");
			}
			
			printf(" (ret = %d)\n\n", ret);
			
			if (ret <= -119) break;
		} else {
			printf("OK!\n\n");
		}
		
		usleep(2000000); // 2 seconds
	}
	
	/* Unmount NAND FS and exit */
	ISFS_Deinitialize();
	Reboot();
	
	return 0;
}
Esempio n. 17
0
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;
}
Esempio n. 18
0
void Delete_Priiloader_Files( u8 mode )
{
    bool settings = false;
    bool hacks = false;
    bool password = false;
    bool main_bin = false;
    bool ticket = false;
    switch(mode)
    {
    case 2: //remove
        main_bin = true;
        ticket = true;
    case 0: //install
        hacks = true;
    case 1: //update
        settings = true;
        password = true;
    default:
        break;
    }
    s32 ret = 0;
    static char file_path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
    memset(file_path,0,ISFS_MAXPATH);
    if(password)
    {
        sprintf(file_path, "/title/%08x/%08x/data/password.txt",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("password.txt : %d\n",ret);
        printf("password file : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);
    }
    if(settings)
    {
        sprintf(file_path, "/title/%08x/%08x/data/loader.ini",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("loader.ini : %d\n",ret);
        printf("Settings file : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);
    }
    //its best we delete that ticket but its completely useless and will only get in our
    //way when installing again later...
    if(ticket)
    {
        sprintf(file_path, "/title/%08x/%08x/content/ticket",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("ticket : %d\n",ret);
        printf("Ticket : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);
    }
    if(hacks)
    {
        sprintf(file_path, "/title/%08x/%08x/data/hacks_s.ini",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("hacks_s.ini : %d\n",ret);
        printf("Hacks_s.ini : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);

        sprintf(file_path, "/title/%08x/%08x/data/hacks.ini",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("hacks.ini : %d\n",ret);
        printf("Hacks.ini : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);

        sprintf(file_path, "/title/%08x/%08x/data/hacksh_s.ini",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("hacksh_s.ini : %d\n",ret);
        printf("Hacksh_s.ini : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);

        sprintf(file_path, "/title/%08x/%08x/data/hackshas.ini",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("hacks_hash : %d\n",ret);
        printf("Hacks_hash : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);

    }
    if(main_bin)
    {
        sprintf(file_path, "/title/%08x/%08x/data/main.nfo",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("main.nfo : %d\n",ret);
        sprintf(file_path, "/title/%08x/%08x/data/main.bin",(u32)(title_id >> 32),(u32) (title_id & 0xFFFFFFFF));
        ret = ISFS_Delete(file_path);
        gprintf("main.bin : %d\n",ret);
        printf("main.bin : ");
        proccess_delete_ret(ret);
        memset(file_path,0,ISFS_MAXPATH);
    }
    return;
}
Esempio n. 19
0
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;
}