2016-12-10 15:32:03 +01:00
# include "fsperm.h"
# include "fsdrive.h"
# include "virtual.h"
# include "image.h"
2017-02-26 13:35:37 +01:00
# include "unittype.h"
2016-12-10 15:32:03 +01:00
# include "ui.h"
2017-02-15 16:34:25 +01:00
# define PATH_SYS_LVL1 "S: / twln.bin", "S: / twlp.bin"
2017-03-23 19:30:51 +01:00
# define PATH_SYS_LVL2 "1: / rw / sys / LocalFriendCodeSeed_B", "1: / rw / sys / LocalFriendCodeSeed_A", \
" 1:/rw/sys/SecureInfo_A " , " 1:/rw/sys/SecureInfo_B " , \
2017-08-04 16:56:06 +02:00
" 1:/private/movable.sed " , " 1:/ro/sys/HWCAL0.dat " , " 1:/ro/sys/HWCAL1.dat " , \
" S:/ctrnand_fat.bin " , " S:/ctrnand_full.bin "
2017-02-15 16:34:25 +01:00
# define PATH_SYS_LVL3 "S: / firm0.bin", "S: / firm1.bin", "S: / nand.bin", "S: / nand_minsize.bin", "S: / nand_hdr.bin", \
" S:/sector0x96.bin " , " S:/twlmbr.bin "
# define PATH_EMU_LVL1 "E: / ctrnand_fat.bin", "E: / ctrnand_full.bin", "E: / nand.bin", "E: / nand_minsize.bin", "E: / nand_hdr.bin"
2016-12-10 15:32:03 +01:00
// write permissions - careful with this
static u32 write_permissions = PERM_BASE ;
bool CheckWritePermissions ( const char * path ) {
char area_name [ 16 ] ;
int drvtype = DriveType ( path ) ;
u32 perm ;
// check mounted image write permissions
if ( ( drvtype & DRV_IMAGE ) & & ! CheckWritePermissions ( GetMountPath ( ) ) )
return false ; // endless loop when mounted file inside image, but not possible
// check drive type, get permission type
if ( drvtype & DRV_SYSNAND ) {
2017-02-15 16:34:25 +01:00
u32 perms [ ] = { PERM_SYS_LVL0 , PERM_SYS_LVL1 , PERM_SYS_LVL2 , PERM_SYS_LVL3 } ;
u32 lvl = ( drvtype & ( DRV_TWLNAND | DRV_ALIAS | DRV_CTRNAND ) ) ? 1 : 0 ;
if ( drvtype & ( DRV_CTRNAND | DRV_VIRTUAL ) ) { // check for paths
const char * path_lvl3 [ ] = { PATH_SYS_LVL3 } ;
const char * path_lvl2 [ ] = { PATH_SYS_LVL2 } ;
const char * path_lvl1 [ ] = { PATH_SYS_LVL1 } ;
for ( u32 i = 0 ; ( i < sizeof ( path_lvl3 ) / sizeof ( char * ) ) & & ( lvl < 3 ) ; i + + )
2017-07-27 20:30:07 +02:00
if ( strncasecmp ( path , path_lvl3 [ i ] , 256 ) = = 0 ) lvl = 3 ;
2017-02-15 16:34:25 +01:00
for ( u32 i = 0 ; ( i < sizeof ( path_lvl2 ) / sizeof ( char * ) ) & & ( lvl < 2 ) ; i + + )
2017-07-27 20:30:07 +02:00
if ( strncasecmp ( path , path_lvl2 [ i ] , 256 ) = = 0 ) lvl = 2 ;
2017-02-15 16:34:25 +01:00
for ( u32 i = 0 ; ( i < sizeof ( path_lvl1 ) / sizeof ( char * ) ) & & ( lvl < 1 ) ; i + + )
2017-07-27 20:30:07 +02:00
if ( strncasecmp ( path , path_lvl1 [ i ] , 256 ) = = 0 ) lvl = 1 ;
2016-12-10 15:32:03 +01:00
}
2017-02-26 13:35:37 +01:00
if ( ! IS_A9LH ) { // changed SysNAND permission levels on non-A9LH
2017-02-22 18:43:57 +01:00
if ( ( drvtype & DRV_CTRNAND ) | | ( lvl = = 2 ) ) lvl = 3 ;
}
2017-02-15 16:34:25 +01:00
perm = perms [ lvl ] ;
snprintf ( area_name , 16 , " SysNAND (lvl%lu) " , lvl ) ;
2016-12-10 15:32:03 +01:00
} else if ( drvtype & DRV_EMUNAND ) {
2017-02-15 16:34:25 +01:00
u32 perms [ ] = { PERM_EMU_LVL0 , PERM_EMU_LVL1 } ;
u32 lvl = ( drvtype & ( DRV_ALIAS | DRV_CTRNAND ) ) ? 1 : 0 ;
if ( drvtype & DRV_VIRTUAL ) { // check for paths
const char * path_lvl1 [ ] = { PATH_EMU_LVL1 } ;
for ( u32 i = 0 ; ( i < sizeof ( path_lvl1 ) / sizeof ( char * ) ) & & ( lvl < 1 ) ; i + + )
2017-07-27 20:30:07 +02:00
if ( strncasecmp ( path , path_lvl1 [ i ] , 256 ) = = 0 ) lvl = 1 ;
2017-02-15 16:34:25 +01:00
}
perm = perms [ lvl ] ;
snprintf ( area_name , 16 , " EmuNAND (lvl%lu) " , lvl ) ;
2016-12-10 15:32:03 +01:00
} else if ( drvtype & DRV_GAME ) {
perm = PERM_GAME ;
snprintf ( area_name , 16 , " game images " ) ;
2017-01-13 14:20:42 +01:00
} else if ( drvtype & DRV_CART ) {
perm = PERM_CART ;
snprintf ( area_name , 16 , " gamecarts " ) ;
2016-12-10 15:32:03 +01:00
} else if ( drvtype & DRV_XORPAD ) {
perm = PERM_XORPAD ;
snprintf ( area_name , 16 , " XORpads " ) ;
} else if ( drvtype & DRV_IMAGE ) {
perm = PERM_IMAGE ;
snprintf ( area_name , 16 , " images " ) ;
} else if ( drvtype & DRV_MEMORY ) {
perm = PERM_MEMORY ;
snprintf ( area_name , 16 , " memory areas " ) ;
2017-07-27 20:30:07 +02:00
} else if ( strncasecmp ( path , " 0:/Nintendo 3DS " , 15 ) = = 0 ) { // this check could be better
2016-12-10 15:32:03 +01:00
perm = PERM_SDDATA ;
snprintf ( area_name , 16 , " SD system data " ) ;
} else if ( drvtype & DRV_SDCARD ) {
perm = PERM_SDCARD ;
2017-02-15 16:34:25 +01:00
snprintf ( area_name , 16 , " SD card " ) ;
2016-12-10 15:32:03 +01:00
} else if ( drvtype & DRV_RAMDRIVE ) {
perm = PERM_RAMDRIVE ;
2017-02-15 16:34:25 +01:00
snprintf ( area_name , 16 , " RAM drive " ) ;
2016-12-10 15:32:03 +01:00
} else {
return false ;
}
// check permission, return if already set
if ( ( write_permissions & perm ) = = perm )
return true ;
2017-07-25 12:44:27 +02:00
// offer unlock if possible
if ( ! ( perm & ( PERM_CART | PERM_GAME | PERM_XORPAD ) ) ) {
// ask the user
if ( ! ShowPrompt ( true , " Writing to %s is locked! \n Unlock it now? " , area_name ) )
return false ;
return SetWritePermissions ( perm , true ) ;
}
// unlock not possible
ShowPrompt ( false , " Unlock write permission for \n %s is not allowed. " , area_name ) ;
return false ;
2016-12-10 15:32:03 +01:00
}
2017-02-15 16:34:25 +01:00
bool CheckDirWritePermissions ( const char * path ) {
const char * path_chk [ ] = { PATH_SYS_LVL3 , PATH_SYS_LVL2 , PATH_SYS_LVL1 , PATH_EMU_LVL1 } ;
for ( u32 i = 0 ; i < sizeof ( path_chk ) / sizeof ( char * ) ; i + + ) {
const char * path_cmp = path_chk [ i ] ;
u32 p = 0 ;
for ( ; p < 256 ; p + + )
if ( ! path [ p ] | | ! path_cmp [ p ] | | ( path [ p ] ! = path_cmp [ p ] ) ) break ;
if ( ! path [ p ] & & ( path_cmp [ p ] = = ' / ' ) )
return CheckWritePermissions ( path_cmp ) ; // special dir, check object
}
return CheckWritePermissions ( path ) ; // not a special dir, just check path
}
2016-12-10 15:32:03 +01:00
bool SetWritePermissions ( u32 perm , bool add_perm ) {
if ( ( write_permissions & perm ) = = perm ) { // write permissions already given
if ( ! add_perm ) write_permissions = perm ;
return true ;
}
switch ( perm ) {
case PERM_BASE :
if ( ! ShowUnlockSequence ( 1 , " You want to enable base \n writing permissions. " ) )
return false ;
break ;
case PERM_SDCARD :
if ( ! ShowUnlockSequence ( 1 , " You want to enable SD card \n writing permissions. " ) )
return false ;
break ;
2017-02-15 16:34:25 +01:00
case PERM_IMAGE :
if ( ! ShowUnlockSequence ( 1 , " You want to enable image \n writing permissions. " ) )
return false ;
break ;
2016-12-10 15:32:03 +01:00
case PERM_RAMDRIVE :
if ( ! ShowUnlockSequence ( 1 , " You want to enable RAM drive \n writing permissions. " ) )
return false ;
2017-07-26 14:07:34 +02:00
break ;
2017-02-15 16:34:25 +01:00
case PERM_EMU_LVL0 :
if ( ! ShowUnlockSequence ( 1 , " You want to enable EmuNAND \n lvl0 writing permissions. " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
2017-02-15 16:34:25 +01:00
case PERM_SYS_LVL0 :
if ( ! ShowUnlockSequence ( 1 , " You want to enable SysNAND \n lvl0 writing permissions. " ) )
return false ;
break ;
case PERM_EMU_LVL1 :
if ( ! ShowUnlockSequence ( 2 , " You want to enable EmuNAND \n lvl1 writing permissions. \n \n This enables you to modify \n recoverable system data, \n user data & savegames. " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
2017-02-15 16:34:25 +01:00
case PERM_SYS_LVL1 :
if ( ! ShowUnlockSequence ( 2 , " You want to enable SysNAND \n lvl1 writing permissions. \n \n This enables you to modify \n system data, installations, \n user data & savegames. " ) )
return false ;
break ;
case PERM_SDDATA :
if ( ! ShowUnlockSequence ( 2 , " You want to enable SD data \n writing permissions. \n \n This enables you to modify \n installations, user data & \n savegames. " ) )
return false ;
break ;
2016-12-10 15:32:03 +01:00
# ifndef SAFEMODE
2017-02-15 16:34:25 +01:00
case PERM_SYS_LVL2 :
if ( ! ShowUnlockSequence ( 3 , " !Better be careful! \n \n You want to enable SysNAND \n lvl2 writing permissions. \n \n This enables you to modify \n irrecoverable system data! " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
case PERM_MEMORY :
2017-06-03 12:22:12 +02:00
if ( ! ShowUnlockSequence ( 4 , " !Better be careful! \n \n You want to enable memory \n writing permissions. \n \n Writing to certain areas may \n lead to unexpected results. " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
2017-02-15 16:34:25 +01:00
case PERM_SYS_LVL3 :
2017-05-21 13:18:11 +02:00
if ( ! ShowUnlockSequence ( 6 , " !THIS IS YOUR ONLY WARNING! \n \n You want to enable SysNAND \n lvl3 writing permissions. \n \n This enables you to OVERWRITE \n %s " , IS_SIGHAX ? " your B9S installation and/or \n BRICK your console! " : IS_A9LH ? " your A9LH installation and/or \n BRICK your console! " : " essential system files and/or \n BRICK your console! " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
2017-03-10 18:52:39 +01:00
case PERM_ALL : // not accessible from GM9
2017-02-15 16:34:25 +01:00
if ( ! ShowUnlockSequence ( 3 , " !Better be careful! \n \n You want to enable ALL \n writing permissions. \n \n This enables you to do some \n really dangerous stuff! " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
default :
ShowPrompt ( false , " Unlock write permission is not allowed. " ) ;
return false ;
break ;
# else
2017-02-15 16:34:25 +01:00
case PERM_ALL : // dito (???)
if ( ! ShowUnlockSequence ( 2 , " You want to enable ALL safe \n writing permissions. \n \n This enables you to modify \n system data, installations, \n user data & savegames. " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
default :
ShowPrompt ( false , " Can't unlock write permission. \n Try GodMode9 instead! " ) ;
return false ;
break ;
# endif
}
write_permissions = add_perm ? write_permissions | perm : perm ;
return true ;
}
u32 GetWritePermissions ( ) {
return write_permissions ;
}