[Tool] Support AutoRCM on devkits

This commit is contained in:
ctcaer@gmail.com 2019-04-16 20:05:35 +03:00
parent a2ba2ecf26
commit ed047ef5f5
5 changed files with 52 additions and 42 deletions

View file

@ -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,

View file

@ -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");

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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