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"
2018-08-26 23:06:32 +02:00
# include "essentials.h"
2016-12-10 15:32:03 +01:00
# include "ui.h"
2018-02-27 16:53:45 +09:00
# include "sdmmc.h"
2016-12-10 15:32:03 +01:00
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 " , \
2018-08-26 23:06:32 +02:00
" S:/ctrnand_fat.bin " , " S:/ctrnand_full.bin " , " S:/ " ESSENTIAL_NAME
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
2018-02-27 16:53:45 +09:00
// SD card write protection check
if ( ( drvtype & ( DRV_SDCARD | DRV_EMUNAND | DRV_ALIAS ) ) & & SD_WRITE_PROTECTED ) {
ShowPrompt ( false , " SD card is write protected! \n Can't continue. " ) ;
return false ;
}
2016-12-10 15:32:03 +01:00
// 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
}
2019-06-03 00:34:26 +02:00
if ( ! IS_UNLOCKED ) { // changed SysNAND permission levels on locked systems
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 " ) ;
2017-12-07 02:54:12 +01:00
} else if ( drvtype & DRV_VRAM ) {
perm = PERM_VRAM ;
snprintf ( area_name , 16 , " vram0 " ) ;
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
2017-12-07 02:54:12 +01:00
if ( ! ( perm & ( PERM_VRAM | PERM_CART | PERM_GAME | PERM_XORPAD ) ) ) {
2017-07-25 12:44:27 +02:00
// 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 :
2019-06-03 00:34:26 +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 your bootloader installation, \n essential system files and/or \n BRICK your console! " ) )
2016-12-10 15:32:03 +01:00
return false ;
break ;
default :
ShowPrompt ( false , " Unlock write permission is not allowed. " ) ;
return false ;
break ;
# else
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 ;
}