[main] Add brick protection for RCM patched units

- If AutoRCM was found enabled, force disable it.
 (In case of chainloading.)
- Additionally disable AutoRCM function.
This commit is contained in:
ctcaer@gmail.com 2019-04-16 20:09:04 +03:00
parent ed047ef5f5
commit c80fecd080
6 changed files with 92 additions and 2 deletions

View file

@ -44,6 +44,7 @@ void set_default_configuration()
h_cfg.errors = 0;
h_cfg.autonogc = 1;
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.rcm_patched = true;
}
int create_config_entry()

View file

@ -30,10 +30,11 @@ typedef struct _hekate_config
u32 autohosoff;
u32 autonogc;
// Global temporary config.
int se_keygen_done;
bool se_keygen_done;
u32 sbar_time_keeping;
u32 errors;
int sept_run;
bool rcm_patched;
} hekate_config;
typedef enum

View file

@ -294,6 +294,16 @@ void menu_autorcm()
gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0);
if (h_cfg.rcm_patched)
{
gfx_printf("%kThis device is RCM patched and\nAutoRCM function is disabled.\n\n"
"In case %kAutoRCM%k is enabled\nthis will %kBRICK%k your device PERMANENTLY!!%k",
0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFCCCCCC);
btn_wait();
return;
}
// Do a simple check on the main BCT.
sdmmc_storage_t storage;
sdmmc_t sdmmc;

View file

@ -34,10 +34,12 @@
#include "mem/sdram.h"
#include "power/max77620.h"
#include "rtc/max77620-rtc.h"
#include "soc/fuse.h"
#include "soc/hw_init.h"
#include "soc/i2c.h"
#include "soc/t210.h"
#include "soc/uart.h"
#include "storage/nx_emmc.h"
#include "storage/sdmmc.h"
#include "utils/btn.h"
#include "utils/dirlist.h"
@ -945,6 +947,48 @@ out:
b_cfg.boot_cfg &= ~(BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_FROM_LAUNCH);
}
void patched_rcm_protection()
{
sdmmc_storage_t storage;
sdmmc_t sdmmc;
h_cfg.rcm_patched = fuse_check_patched_rcm();
if (!h_cfg.rcm_patched)
return;
// Check if AutoRCM is enabled and protect from a permanent brick.
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
return;
u8 *tempbuf = (u8 *)malloc(0x200);
sdmmc_storage_set_mmc_partition(&storage, 1);
u8 corr_mod_byte0;
int i, sect = 0;
if ((fuse_read_odm(4) & 3) != 3)
corr_mod_byte0 = 0xF7;
else
corr_mod_byte0 = 0x37;
for (i = 0; i < 4; i++)
{
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
sdmmc_storage_read(&storage, sect, 1, tempbuf);
// If AutoRCM is enabled, disable it.
if (tempbuf[0x10] != corr_mod_byte0)
{
tempbuf[0x10] = corr_mod_byte0;
sdmmc_storage_write(&storage, sect, 1, tempbuf);
}
}
free(tempbuf);
sdmmc_storage_end(&storage);
}
void about()
{
static const char credits[] =
@ -1087,7 +1131,7 @@ ment_t ment_tools[] = {
//MDEF_HANDLER("Reset all battery cfg", reset_pmic_fuel_gauge_charger_config),
//MDEF_HANDLER("Minerva", minerva), // Uncomment for testing Minerva Training Cell
MDEF_CHGLINE(),
MDEF_CAPTION("------ Dangerous -----", 0xFFFF0000),
MDEF_CAPTION("-------- Other -------", 0xFFFFDD00),
MDEF_HANDLER("AutoRCM", menu_autorcm),
MDEF_END()
};
@ -1163,6 +1207,9 @@ void ipl_main()
// Check if we had a panic while in CFW.
secmon_exo_check_panic();
// Check if RCM is patched and protect from a possible brick.
patched_rcm_protection();
// Load saved configuration and auto boot if enabled.
auto_launch_firmware();

View file

@ -318,3 +318,32 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
return 0;
}
bool fuse_check_patched_rcm()
{
// Check if XUSB in use.
if (FUSE(FUSE_RESERVED_SW) & (1<<7))
return true;
// Check if RCM is ipatched.
u32 word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE) & 0x7F;
u32 word_addr = 191;
while (word_count)
{
u32 word0 = fuse_read(word_addr);
u32 ipatch_count = (word0 >> 16) & 0xF;
for (u32 i = 0; i < ipatch_count; i++)
{
u32 word = fuse_read(word_addr - (i + 1));
u32 addr = (word >> 16) * 2;
if (addr == 0x769A)
return true;
}
word_addr -= word_count;
word_count = word0 >> 25;
}
return false;
}

View file

@ -42,6 +42,7 @@
#define FUSE_PRIVATE_KEY1 0x1A8
#define FUSE_PRIVATE_KEY2 0x1AC
#define FUSE_PRIVATE_KEY3 0x1B0
#define FUSE_RESERVED_SW 0x1C0
/*! Fuse commands. */
#define FUSE_READ 0x1
@ -58,5 +59,6 @@ void fuse_wait_idle();
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
void fuse_read_array(u32 *words);
bool fuse_check_patched_rcm();
#endif