2016-12-10 15:32:03 +01:00
# include "fsperm.h"
# include "fsdrive.h"
# include "virtual.h"
# include "image.h"
2017-02-15 16:34:25 +01:00
# include "nand.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"
# define PATH_SYS_LVL2 "1: / rw / sys / LocalFriendCodeSeed_B", "1: / rw / sys / SecureInfo_A", "1: / rw / sys / SecureInfo_B", \
" 1:/private/movable.sed " , " S:/ctrnand_fat.bin " , " S:/ctrnand_full.bin "
# 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"
# define PATH_PERM_CHK "E:", "S:", "1: / rw / sys", "1: / private"
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
2017-02-15 16:34:25 +01:00
// TODO: handle entypoints other than A9LH (!!!)
2016-12-10 15:32:03 +01:00
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 + + )
if ( strncmp ( path , path_lvl3 [ i ] , 256 ) = = 0 ) lvl = 3 ;
for ( u32 i = 0 ; ( i < sizeof ( path_lvl2 ) / sizeof ( char * ) ) & & ( lvl < 2 ) ; i + + )
if ( strncmp ( path , path_lvl2 [ i ] , 256 ) = = 0 ) lvl = 2 ;
for ( u32 i = 0 ; ( i < sizeof ( path_lvl1 ) / sizeof ( char * ) ) & & ( lvl < 1 ) ; i + + )
if ( strncmp ( path , path_lvl1 [ i ] , 256 ) = = 0 ) lvl = 1 ;
2016-12-10 15:32:03 +01:00
}
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 + + )
if ( strncmp ( path , path_lvl1 [ i ] , 256 ) = = 0 ) lvl = 1 ;
}
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-02-15 16:34:25 +01:00
} else if ( strncmp ( 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 ;
// ask the user
if ( ! ShowPrompt ( true , " Writing to %s is locked! \n Unlock it now? " , area_name ) )
return false ;
return SetWritePermissions ( perm , true ) ;
}
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-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 ;
case PERM_CART :
ShowPrompt ( false , " Unlock write permission for \n game carts is not allowed. " ) ;
return false ;
break ;
2016-12-10 15:32:03 +01:00
case PERM_GAME :
ShowPrompt ( false , " Unlock write permission for \n game images is not allowed. " ) ;
return false ;
break ;
case PERM_XORPAD :
ShowPrompt ( false , " Unlock write permission for \n XORpad drive is not allowed. " ) ;
return false ;
break ;
# 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-02-15 16:34:25 +01:00
if ( ! ShowUnlockSequence ( 4 , " !Better be careful! \n \n You want to enable memory \n writing permissions. \n nWriting 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 :
if ( ! ShowUnlockSequence ( 5 , " !THIS IS YOUR ONLY WARNING! \n \n You want to enable SysNAND \n lvl3 writing permissions. \n \n This enables you to OVERWRITE \n your A9LH installation and \n BRICK your console! " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
2017-02-15 16:34:25 +01:00
case PERM_ALL : // maybe get rid of this (???)
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 ;
}