From c80fecd0809e624c28ddf0012e875a59ad383361 Mon Sep 17 00:00:00 2001 From: "ctcaer@gmail.com" Date: Tue, 16 Apr 2019 20:09:04 +0300 Subject: [PATCH] [main] Add brick protection for RCM patched units - If AutoRCM was found enabled, force disable it. (In case of chainloading.) - Additionally disable AutoRCM function. --- bootloader/config/config.c | 1 + bootloader/config/config.h | 3 ++- bootloader/frontend/fe_tools.c | 10 +++++++ bootloader/main.c | 49 +++++++++++++++++++++++++++++++++- bootloader/soc/fuse.c | 29 ++++++++++++++++++++ bootloader/soc/fuse.h | 2 ++ 6 files changed, 92 insertions(+), 2 deletions(-) diff --git a/bootloader/config/config.c b/bootloader/config/config.c index 61f28d6..668340d 100644 --- a/bootloader/config/config.c +++ b/bootloader/config/config.c @@ -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() diff --git a/bootloader/config/config.h b/bootloader/config/config.h index d63f6d1..e12136f 100644 --- a/bootloader/config/config.h +++ b/bootloader/config/config.h @@ -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 diff --git a/bootloader/frontend/fe_tools.c b/bootloader/frontend/fe_tools.c index 063f706..a457b8e 100644 --- a/bootloader/frontend/fe_tools.c +++ b/bootloader/frontend/fe_tools.c @@ -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; diff --git a/bootloader/main.c b/bootloader/main.c index 7601976..28534bf 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -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(); diff --git a/bootloader/soc/fuse.c b/bootloader/soc/fuse.c index 9659876..38f63e9 100644 --- a/bootloader/soc/fuse.c +++ b/bootloader/soc/fuse.c @@ -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; +} diff --git a/bootloader/soc/fuse.h b/bootloader/soc/fuse.h index f1ffda9..7f801d4 100644 --- a/bootloader/soc/fuse.h +++ b/bootloader/soc/fuse.h @@ -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