mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
[Tool] Support AutoRCM on devkits
This commit is contained in:
parent
a2ba2ecf26
commit
ed047ef5f5
5 changed files with 52 additions and 42 deletions
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 Rajko Stojadinovic
|
* Copyright (c) 2018 Rajko Stojadinovic
|
||||||
* Copyright (c) 2018 CTCaer
|
* Copyright (c) 2018-2019 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
|
|
@ -652,7 +652,7 @@ void bootrom_ipatches_info()
|
||||||
EPRINTFARGS("Failed to read evp_thunks. Error: %d", res);
|
EPRINTFARGS("Failed to read evp_thunks. Error: %d", res);
|
||||||
|
|
||||||
u32 words[192];
|
u32 words[192];
|
||||||
read_raw_fuses(words);
|
fuse_read_array(words);
|
||||||
emmcsn_path_impl(path, "/dumps", "raw_fuses.bin", NULL);
|
emmcsn_path_impl(path, "/dumps", "raw_fuses.bin", NULL);
|
||||||
if (!sd_save_to_file((u8 *)words, sizeof(words), path))
|
if (!sd_save_to_file((u8 *)words, sizeof(words), path))
|
||||||
gfx_puts("\nipatches.bin saved!\n");
|
gfx_puts("\nipatches.bin saved!\n");
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "../sec/se.h"
|
#include "../sec/se.h"
|
||||||
#include "../storage/nx_emmc.h"
|
#include "../storage/nx_emmc.h"
|
||||||
#include "../storage/sdmmc.h"
|
#include "../storage/sdmmc.h"
|
||||||
|
#include "../soc/fuse.h"
|
||||||
#include "../utils/btn.h"
|
#include "../utils/btn.h"
|
||||||
#include "../utils/util.h"
|
#include "../utils/util.h"
|
||||||
|
|
||||||
|
@ -247,6 +248,12 @@ void _toggle_autorcm(bool enable)
|
||||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||||
|
|
||||||
int i, sect = 0;
|
int i, sect = 0;
|
||||||
|
u8 corr_mod_byte0;
|
||||||
|
if ((fuse_read_odm(4) & 3) != 3)
|
||||||
|
corr_mod_byte0 = 0xF7;
|
||||||
|
else
|
||||||
|
corr_mod_byte0 = 0x37;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||||
|
@ -262,7 +269,7 @@ void _toggle_autorcm(bool enable)
|
||||||
tempbuf[0x10] ^= randomXor;
|
tempbuf[0x10] ^= randomXor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tempbuf[0x10] = 0xF7;
|
tempbuf[0x10] = corr_mod_byte0;
|
||||||
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,8 +311,16 @@ void menu_autorcm()
|
||||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||||
|
|
||||||
|
if ((fuse_read_odm(4) & 3) != 3)
|
||||||
|
{
|
||||||
if (tempbuf[0x10] != 0xF7)
|
if (tempbuf[0x10] != 0xF7)
|
||||||
disabled = false;
|
disabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tempbuf[0x10] != 0x37)
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
free(tempbuf);
|
free(tempbuf);
|
||||||
sdmmc_storage_end(&storage);
|
sdmmc_storage_end(&storage);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 shuffle2
|
* Copyright (c) 2018 shuffle2
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
|
* Copyright (c) 2019 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
@ -68,7 +69,21 @@ void fuse_wait_idle()
|
||||||
} while (((ctrl >> 16) & 0x1f) != 4);
|
} while (((ctrl >> 16) & 0x1f) != 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 parity32_even(u32 *words, u32 count)
|
u32 fuse_read(u32 addr)
|
||||||
|
{
|
||||||
|
FUSE(FUSE_ADDR) = addr;
|
||||||
|
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
||||||
|
fuse_wait_idle();
|
||||||
|
return FUSE(FUSE_RDATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fuse_read_array(u32 *words)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < 192; i++)
|
||||||
|
words[i] = fuse_read(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 _parity32_even(u32 *words, u32 count)
|
||||||
{
|
{
|
||||||
u32 acc = words[0];
|
u32 acc = words[0];
|
||||||
for (u32 i = 1; i < count; i++)
|
for (u32 i = 1; i < count; i++)
|
||||||
|
@ -85,10 +100,10 @@ u32 parity32_even(u32 *words, u32 count)
|
||||||
return (x & 1) ^ (x >> 1);
|
return (x & 1) ^ (x >> 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int patch_hash_one(u32 *word)
|
static int _patch_hash_one(u32 *word)
|
||||||
{
|
{
|
||||||
u32 bits20_31 = *word & 0xfff00000;
|
u32 bits20_31 = *word & 0xfff00000;
|
||||||
u32 parity_bit = parity32_even(&bits20_31, 1);
|
u32 parity_bit = _parity32_even(&bits20_31, 1);
|
||||||
u32 hash = 0;
|
u32 hash = 0;
|
||||||
for (u32 i = 0; i < 12; i++)
|
for (u32 i = 0; i < 12; i++)
|
||||||
{
|
{
|
||||||
|
@ -121,9 +136,9 @@ int patch_hash_one(u32 *word)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int patch_hash_multi(u32 *words, u32 count)
|
static int _patch_hash_multi(u32 *words, u32 count)
|
||||||
{
|
{
|
||||||
u32 parity_bit = parity32_even(words, count);
|
u32 parity_bit = _parity32_even(words, count);
|
||||||
u32 bits0_14 = words[0] & 0x7fff;
|
u32 bits0_14 = words[0] & 0x7fff;
|
||||||
u32 bit15 = words[0] & 0x8000;
|
u32 bit15 = words[0] & 0x8000;
|
||||||
u32 bits16_19 = words[0] & 0xf0000;
|
u32 bits16_19 = words[0] & 0xf0000;
|
||||||
|
@ -193,7 +208,7 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
|
||||||
u32 total_read = 0;
|
u32 total_read = 0;
|
||||||
|
|
||||||
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
|
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
|
||||||
word_count &= 0x7f;
|
word_count &= 0x7F;
|
||||||
word_addr = 191;
|
word_addr = 191;
|
||||||
|
|
||||||
while (word_count)
|
while (word_count)
|
||||||
|
@ -205,26 +220,21 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < word_count; i++)
|
for (u32 i = 0; i < word_count; i++)
|
||||||
{
|
words[i] = fuse_read(word_addr--);
|
||||||
FUSE(FUSE_ADDR) = word_addr--;
|
|
||||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
|
||||||
fuse_wait_idle();
|
|
||||||
words[i] = FUSE(FUSE_RDATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
word0 = words[0];
|
word0 = words[0];
|
||||||
if (patch_hash_multi(words, word_count) >= 2)
|
if (_patch_hash_multi(words, word_count) >= 2)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
u32 ipatch_count = (words[0] >> 16) & 0xf;
|
u32 ipatch_count = (words[0] >> 16) & 0xF;
|
||||||
if (ipatch_count)
|
if (ipatch_count)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < ipatch_count; i++)
|
for (u32 i = 0; i < ipatch_count; i++)
|
||||||
{
|
{
|
||||||
u32 word = words[i + 1];
|
u32 word = words[i + 1];
|
||||||
u32 addr = (word >> 16) * 2;
|
u32 addr = (word >> 16) * 2;
|
||||||
u32 data = word & 0xffff;
|
u32 data = word & 0xFFFF;
|
||||||
|
|
||||||
ipatch(addr, data);
|
ipatch(addr, data);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +242,7 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
|
||||||
words[0] = word0;
|
words[0] = word0;
|
||||||
if ((word0 >> 25) == 0)
|
if ((word0 >> 25) == 0)
|
||||||
break;
|
break;
|
||||||
if (patch_hash_one(&word0) >= 2)
|
if (_patch_hash_one(&word0) >= 2)
|
||||||
{
|
{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +265,7 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
|
||||||
memset(iram_evp_thunks, 0, *iram_evp_thunks_len);
|
memset(iram_evp_thunks, 0, *iram_evp_thunks_len);
|
||||||
|
|
||||||
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
|
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
|
||||||
word_count &= 0x7f;
|
word_count &= 0x7F;
|
||||||
word_addr = 191;
|
word_addr = 191;
|
||||||
|
|
||||||
while (word_count)
|
while (word_count)
|
||||||
|
@ -267,19 +277,14 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < word_count; i++)
|
for (u32 i = 0; i < word_count; i++)
|
||||||
{
|
words[i] = fuse_read(word_addr--);
|
||||||
FUSE(FUSE_ADDR) = word_addr--;
|
|
||||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
|
||||||
fuse_wait_idle();
|
|
||||||
words[i] = FUSE(FUSE_RDATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
word0 = words[0];
|
word0 = words[0];
|
||||||
if (patch_hash_multi(words, word_count) >= 2)
|
if (_patch_hash_multi(words, word_count) >= 2)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
u32 ipatch_count = (words[0] >> 16) & 0xf;
|
u32 ipatch_count = (words[0] >> 16) & 0xF;
|
||||||
u32 insn_count = word_count - ipatch_count - 1;
|
u32 insn_count = word_count - ipatch_count - 1;
|
||||||
if (insn_count)
|
if (insn_count)
|
||||||
{
|
{
|
||||||
|
@ -303,7 +308,7 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
|
||||||
words[0] = word0;
|
words[0] = word0;
|
||||||
if ((word0 >> 25) == 0)
|
if ((word0 >> 25) == 0)
|
||||||
break;
|
break;
|
||||||
if (patch_hash_one(&word0) >= 2)
|
if (_patch_hash_one(&word0) >= 2)
|
||||||
{
|
{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
@ -313,13 +318,3 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_raw_fuses(u32 *words)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < 192; i++)
|
|
||||||
{
|
|
||||||
FUSE(FUSE_ADDR) = i;
|
|
||||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
|
||||||
fuse_wait_idle();
|
|
||||||
words[i] = FUSE(FUSE_RDATA);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -57,6 +57,6 @@ u32 fuse_read_odm(u32 idx);
|
||||||
void fuse_wait_idle();
|
void fuse_wait_idle();
|
||||||
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
|
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
|
||||||
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
|
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
|
||||||
void read_raw_fuses(u32 *words);
|
void fuse_read_array(u32 *words);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue