220 lines
8.5 KiB
C
Raw Permalink Normal View History

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"
#include "essentials.h"
2022-03-22 18:13:18 -05:00
#include "language.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
#define PATH_SYS_LVL1 "S:/twln.bin", "S:/twlp.bin"
#define PATH_SYS_LVL2 "1:/rw/sys/LocalFriendCodeSeed_B", "1:/rw/sys/LocalFriendCodeSeed_A", \
"1:/rw/sys/SecureInfo_A", "1:/rw/sys/SecureInfo_B", \
"1:/private/movable.sed", "1:/ro/sys/HWCAL0.dat", "1:/ro/sys/HWCAL1.dat", \
"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[UTF_BUFFER_BYTESIZE(16)];
2016-12-10 15:32:03 +01:00
int drvtype = DriveType(path);
u32 perm;
2019-10-12 17:14:16 +02:00
// create a standardized path string
char path_f[256];
char* p = (char*) path;
path_f[255] = '\0';
for (u32 i = 0; i < 255; i++) {
path_f[i] = *(p++);
while ((path_f[i] == '/') && (*p == '/')) p++;
if (!path_f[i]) break;
}
2016-12-10 15:32:03 +01:00
// 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) {
2022-03-22 18:13:18 -05:00
ShowPrompt(false, "%s", STR_SD_WRITE_PROTECTED_CANT_CONTINUE);
2018-02-27 16:53:45 +09:00
return false;
}
2016-12-10 15:32:03 +01:00
// check drive type, get permission type
if (drvtype & DRV_SYSNAND) {
static const u32 perms[] = { PERM_SYS_LVL0, PERM_SYS_LVL1, PERM_SYS_LVL2, PERM_SYS_LVL3 };
2017-02-15 16:34:25 +01:00
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++)
2019-10-12 17:14:16 +02:00
if (strncasecmp(path_f, 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++)
2019-10-12 17:14:16 +02:00
if (strncasecmp(path_f, 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++)
2019-10-12 17:14:16 +02:00
if (strncasecmp(path_f, 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
if ((drvtype & DRV_CTRNAND) || (lvl == 2)) lvl = 3;
}
2017-02-15 16:34:25 +01:00
perm = perms[lvl];
snprintf(area_name, sizeof(area_name), STR_SYSNAND_LVL_N, lvl);
2016-12-10 15:32:03 +01:00
} else if (drvtype & DRV_EMUNAND) {
static const u32 perms[] = { PERM_EMU_LVL0, PERM_EMU_LVL1 };
2017-02-15 16:34:25 +01:00
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++)
2019-10-12 17:14:16 +02:00
if (strncasecmp(path_f, path_lvl1[i], 256) == 0) lvl = 1;
2017-02-15 16:34:25 +01:00
}
perm = perms[lvl];
snprintf(area_name, sizeof(area_name), STR_EMUNAND_LVL_N, lvl);
2016-12-10 15:32:03 +01:00
} else if (drvtype & DRV_GAME) {
perm = PERM_GAME;
snprintf(area_name, sizeof(area_name), "%s", STR_GAME_IMAGES);
2017-01-13 14:20:42 +01:00
} else if (drvtype & DRV_CART) {
perm = PERM_CART;
snprintf(area_name, sizeof(area_name), "%s", STR_GAMECART_SAVES);
} else if (drvtype & DRV_VRAM) {
perm = PERM_VRAM;
snprintf(area_name, sizeof(area_name), "vram0");
2016-12-10 15:32:03 +01:00
} else if (drvtype & DRV_XORPAD) {
perm = PERM_XORPAD;
snprintf(area_name, sizeof(area_name), "XORpads");
2016-12-10 15:32:03 +01:00
} else if (drvtype & DRV_IMAGE) {
perm = PERM_IMAGE;
snprintf(area_name, sizeof(area_name), "%s", STR_IMAGES);
2016-12-10 15:32:03 +01:00
} else if (drvtype & DRV_MEMORY) {
perm = PERM_MEMORY;
snprintf(area_name, sizeof(area_name), "%s", STR_MEMORY_AREAS);
2019-10-12 17:14:16 +02:00
} else if (strncasecmp(path_f, "0:/Nintendo 3DS", 15) == 0) { // this check could be better
2016-12-10 15:32:03 +01:00
perm = PERM_SDDATA;
snprintf(area_name, sizeof(area_name), "%s", STR_SD_SYSTEM_DATA);
2016-12-10 15:32:03 +01:00
} else if (drvtype & DRV_SDCARD) {
perm = PERM_SDCARD;
snprintf(area_name, sizeof(area_name), "%s", STR_SD_CARD);
2016-12-10 15:32:03 +01:00
} else if (drvtype & DRV_RAMDRIVE) {
perm = PERM_RAMDRIVE;
snprintf(area_name, sizeof(area_name), "%s", STR_RAM_DRIVE);
2016-12-10 15:32:03 +01:00
} else {
return false;
}
2016-12-10 15:32:03 +01:00
// check permission, return if already set
if ((write_permissions & perm) == perm)
return true;
// offer unlock if possible
if (!(perm & (PERM_VRAM|PERM_GAME|PERM_XORPAD))) {
// ask the user
2022-03-22 18:13:18 -05:00
if (!ShowPrompt(true, STR_WRITING_TO_DRIVE_IS_LOCKED_UNLOCK_NOW, area_name))
return false;
return SetWritePermissions(perm, true);
}
// unlock not possible
2022-03-22 18:13:18 -05:00
ShowPrompt(false, STR_UNLOCK_WRITE_FOR_DRIVE_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) {
static const char* path_chk[] = { PATH_SYS_LVL3, PATH_SYS_LVL2, PATH_SYS_LVL1, PATH_EMU_LVL1 };
2017-02-15 16:34:25 +01:00
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;
}
2016-12-10 15:32:03 +01:00
switch (perm) {
case PERM_BASE:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(1, "%s", STR_ENABLE_BASE_WRITE))
2016-12-10 15:32:03 +01:00
return false;
break;
case PERM_SDCARD:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(1, "%s", STR_ENABLE_SD_WRITE))
2016-12-10 15:32:03 +01:00
return false;
break;
2017-02-15 16:34:25 +01:00
case PERM_IMAGE:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(1, "%s", STR_ENABLE_IMAGE_WRITE))
2017-02-15 16:34:25 +01:00
return false;
break;
2016-12-10 15:32:03 +01:00
case PERM_RAMDRIVE:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(1, "%s", STR_ENABLE_RAM_DRIVE_WRITE))
2016-12-10 15:32:03 +01:00
return false;
2017-07-26 14:07:34 +02:00
break;
2017-02-15 16:34:25 +01:00
case PERM_EMU_LVL0:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(1, "%s", STR_ENABLE_EMUNAND_0_WRITE))
2016-12-10 15:32:03 +01:00
return false;
break;
2017-02-15 16:34:25 +01:00
case PERM_SYS_LVL0:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(1, "%s", STR_ENABLE_SYSNAND_0_WRITE))
2017-02-15 16:34:25 +01:00
return false;
break;
case PERM_EMU_LVL1:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(2, "%s", STR_ENABLE_EMUNAND_1_WRITE))
2016-12-10 15:32:03 +01:00
return false;
break;
2017-02-15 16:34:25 +01:00
case PERM_SYS_LVL1:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(2, "%s", STR_ENABLE_SYSNAND_1_WRITE))
2017-02-15 16:34:25 +01:00
return false;
break;
case PERM_CART:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(2, "%s", STR_ENABLE_GAMECART_SAVE_WRITE))
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:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(3, "%s", STR_ENABLE_SYSNAND_2_WRITE))
2016-12-10 15:32:03 +01:00
return false;
break;
case PERM_MEMORY:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(4, "%s", STR_ENABLE_MEMORY_WRITE))
2016-12-10 15:32:03 +01:00
return false;
break;
case PERM_SDDATA:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(5, "%s", STR_ENABLE_SD_DATA_WRITE))
return false;
break;
2017-02-15 16:34:25 +01:00
case PERM_SYS_LVL3:
2022-03-22 18:13:18 -05:00
if (!ShowUnlockSequence(6, "%s", STR_ENABLE_SYSNAND_3_WRITE))
2016-12-10 15:32:03 +01:00
return false;
break;
default:
2022-03-22 18:13:18 -05:00
ShowPrompt(false, "%s", STR_UNLOCK_WRITE_NOT_ALLOWED);
2016-12-10 15:32:03 +01:00
return false;
break;
#else
default:
2022-03-22 18:13:18 -05:00
ShowPrompt(false, "%s", STR_CANT_UNLOCK_WRITE_TRY_GODMODE9);
2016-12-10 15:32:03 +01:00
return false;
break;
#endif
}
2016-12-10 15:32:03 +01:00
write_permissions = add_perm ? write_permissions | perm : perm;
2016-12-10 15:32:03 +01:00
return true;
}
u32 GetWritePermissions() {
return write_permissions;
}