mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Merge branch 'master' into debugger_dev
This commit is contained in:
commit
aca8f53050
4 changed files with 85 additions and 41 deletions
|
@ -33,7 +33,7 @@ static const uint8_t g_seal_key_sources[CRYPTOUSECASE_MAX_5X][0x10] = {
|
||||||
{0x0E, 0xE0, 0xC4, 0x33, 0x82, 0x66, 0xE8, 0x08, 0x39, 0x13, 0x41, 0x7D, 0x04, 0x64, 0x2B, 0x6D},
|
{0x0E, 0xE0, 0xC4, 0x33, 0x82, 0x66, 0xE8, 0x08, 0x39, 0x13, 0x41, 0x7D, 0x04, 0x64, 0x2B, 0x6D},
|
||||||
{0xE1, 0xA8, 0xAA, 0x6A, 0x2D, 0x9C, 0xDE, 0x43, 0x0C, 0xDE, 0xC6, 0x17, 0xF6, 0xC7, 0xF1, 0xDE},
|
{0xE1, 0xA8, 0xAA, 0x6A, 0x2D, 0x9C, 0xDE, 0x43, 0x0C, 0xDE, 0xC6, 0x17, 0xF6, 0xC7, 0xF1, 0xDE},
|
||||||
{0x74, 0x20, 0xF6, 0x46, 0x77, 0xB0, 0x59, 0x2C, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9},
|
{0x74, 0x20, 0xF6, 0x46, 0x77, 0xB0, 0x59, 0x2C, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9},
|
||||||
{0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9}
|
{0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE6, 0xD8, 0x9A, 0xCF, 0xE5, 0x3F, 0xB3, 0x4B}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool usecase_is_invalid(unsigned int usecase) {
|
bool usecase_is_invalid(unsigned int usecase) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
|
#include "timers.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
|
@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) {
|
||||||
|
|
||||||
void clkrst_reboot(CarDevice dev) {
|
void clkrst_reboot(CarDevice dev) {
|
||||||
clkrst_disable(dev);
|
clkrst_disable(dev);
|
||||||
|
if (dev == CARDEVICE_KFUSE) {
|
||||||
|
/* Workaround for KFUSE clock. */
|
||||||
|
clk_enable(dev);
|
||||||
|
udelay(100);
|
||||||
|
rst_disable(dev);
|
||||||
|
udelay(200);
|
||||||
|
} else {
|
||||||
clkrst_enable(dev);
|
clkrst_enable(dev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clkrst_enable_fuse_regs(bool enable) {
|
void clkrst_enable_fuse_regs(bool enable) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
|
#include "timers.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
|
@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) {
|
||||||
|
|
||||||
void clkrst_reboot(CarDevice dev) {
|
void clkrst_reboot(CarDevice dev) {
|
||||||
clkrst_disable(dev);
|
clkrst_disable(dev);
|
||||||
|
if (dev == CARDEVICE_KFUSE) {
|
||||||
|
/* Workaround for KFUSE clock. */
|
||||||
|
clk_enable(dev);
|
||||||
|
udelay(100);
|
||||||
|
rst_disable(dev);
|
||||||
|
udelay(200);
|
||||||
|
} else {
|
||||||
clkrst_enable(dev);
|
clkrst_enable(dev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clkrst_enable_fuse_regs(bool enable) {
|
void clkrst_enable_fuse_regs(bool enable) {
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "tsec.h"
|
#include "tsec.h"
|
||||||
|
|
||||||
|
#define TSEC_KEYGEN_MAX_RETRIES 25
|
||||||
|
|
||||||
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
|
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
|
||||||
|
|
||||||
static void safe_memcpy(void *dst, void *src, uint32_t sz) {
|
static void safe_memcpy(void *dst, void *src, uint32_t sz) {
|
||||||
|
@ -168,14 +170,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
/* Copy package1 into IRAM. */
|
/* Copy package1 into IRAM. */
|
||||||
memcpy((void *)0x40010000, package1, package1_size);
|
memcpy((void *)0x40010000, package1, package1_size);
|
||||||
|
|
||||||
/* Load the TSEC firmware from IRAM. */
|
|
||||||
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
|
|
||||||
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable the aperture since it has precedence over the SMMU. */
|
|
||||||
mc_disable_ahb_redirect();
|
|
||||||
|
|
||||||
/* Setup TSEC's address space. */
|
/* Setup TSEC's address space. */
|
||||||
uint32_t *pdir = smmu_setup_tsec_as(1);
|
uint32_t *pdir = smmu_setup_tsec_as(1);
|
||||||
|
|
||||||
|
@ -189,6 +183,45 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
volatile uint32_t *iram_pages = smmu_alloc_page(48);
|
volatile uint32_t *iram_pages = smmu_alloc_page(48);
|
||||||
volatile uint32_t *expv_page = smmu_alloc_page(1);
|
volatile uint32_t *expv_page = smmu_alloc_page(1);
|
||||||
|
|
||||||
|
/* Map all necessary pages. */
|
||||||
|
smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||||
|
smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE);
|
||||||
|
smmu_map(pdir, 0x7000E000, (uint32_t)pmc_page, 1, _READABLE | _NONSECURE);
|
||||||
|
smmu_map(pdir, 0x60007000, (uint32_t)flow_page, 1, _WRITABLE | _NONSECURE);
|
||||||
|
smmu_map(pdir, 0x70012000, (uint32_t)se_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||||
|
smmu_map(pdir, 0x70019000, (uint32_t)mc_page, 1, _READABLE | _NONSECURE);
|
||||||
|
smmu_map(pdir, 0x40010000, (uint32_t)iram_pages, 48, _READABLE | _WRITABLE | _NONSECURE);
|
||||||
|
smmu_map(pdir, 0x6000F000, (uint32_t)expv_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||||
|
|
||||||
|
/* Enable the SMMU. */
|
||||||
|
smmu_enable();
|
||||||
|
|
||||||
|
/* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */
|
||||||
|
uint32_t key_buf[0x20/4] = {0};
|
||||||
|
unsigned int retries = 0;
|
||||||
|
while (true) {
|
||||||
|
if (retries++ > TSEC_KEYGEN_MAX_RETRIES) {
|
||||||
|
fatal_error("[SMMU] TSEC key generation race was lost too many times!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the TSEC firmware from IRAM. */
|
||||||
|
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
|
||||||
|
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable the aperture since it has precedence over the SMMU. */
|
||||||
|
mc_disable_ahb_redirect();
|
||||||
|
|
||||||
|
/* Clear all pages. */
|
||||||
|
memset((void *)car_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)fuse_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)pmc_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)flow_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)se_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)mc_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)iram_pages, 0, 48 * SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)expv_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
|
||||||
/* Copy CAR, MC and FUSE. */
|
/* Copy CAR, MC and FUSE. */
|
||||||
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
|
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
|
||||||
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
|
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
|
||||||
|
@ -204,35 +237,31 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
mc_page[0x65C/4] = 0;
|
mc_page[0x65C/4] = 0;
|
||||||
mc_page[0x660/4] = 0x80000000;
|
mc_page[0x660/4] = 0x80000000;
|
||||||
|
|
||||||
/* Map all necessary pages. */
|
|
||||||
smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
|
||||||
smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE);
|
|
||||||
smmu_map(pdir, 0x7000E000, (uint32_t)pmc_page, 1, _READABLE | _NONSECURE);
|
|
||||||
smmu_map(pdir, 0x60007000, (uint32_t)flow_page, 1, _WRITABLE | _NONSECURE);
|
|
||||||
smmu_map(pdir, 0x70012000, (uint32_t)se_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
|
||||||
smmu_map(pdir, 0x70019000, (uint32_t)mc_page, 1, _READABLE | _NONSECURE);
|
|
||||||
smmu_map(pdir, 0x40010000, (uint32_t)iram_pages, 48, _READABLE | _WRITABLE | _NONSECURE);
|
|
||||||
smmu_map(pdir, 0x6000F000, (uint32_t)expv_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
|
||||||
|
|
||||||
/* Enable the SMMU. */
|
|
||||||
smmu_enable();
|
|
||||||
|
|
||||||
/* Run the TSEC firmware. */
|
/* Run the TSEC firmware. */
|
||||||
tsec_run_fw();
|
tsec_run_fw();
|
||||||
|
|
||||||
/* Extract the keys from SE. */
|
/* Extract the keys from SE. */
|
||||||
uint32_t key_buf[0x20/4] = {0};
|
|
||||||
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
|
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
|
||||||
uint32_t old_key_data = *key_data;
|
uint32_t old_key_data = *key_data;
|
||||||
uint32_t buf_counter = 0;
|
uint32_t buf_counter = 0;
|
||||||
while (!(tsec->FALCON_CPUCTL & 0x10)) {
|
while (!(tsec->FALCON_CPUCTL & 0x10)) {
|
||||||
if (*key_data != old_key_data) {
|
const uint32_t new_key_data = *key_data;
|
||||||
old_key_data = *key_data;
|
if (new_key_data != old_key_data) {
|
||||||
key_buf[buf_counter] = *key_data;
|
old_key_data = new_key_data;
|
||||||
|
key_buf[buf_counter] = new_key_data;
|
||||||
buf_counter++;
|
buf_counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enable back the aperture. */
|
||||||
|
mc_enable_ahb_redirect();
|
||||||
|
|
||||||
|
if (buf_counter == 8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the TSEC firmware wrote over the exception vectors. */
|
/* Check if the TSEC firmware wrote over the exception vectors. */
|
||||||
volatile uint32_t *tsec_done_check = (volatile uint32_t *)((void *)expv_page + 0x200);
|
volatile uint32_t *tsec_done_check = (volatile uint32_t *)((void *)expv_page + 0x200);
|
||||||
if (!(*tsec_done_check)) {
|
if (!(*tsec_done_check)) {
|
||||||
|
@ -248,9 +277,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
/* Clear TSEC's address space. */
|
/* Clear TSEC's address space. */
|
||||||
smmu_clear_tsec_as(1);
|
smmu_clear_tsec_as(1);
|
||||||
|
|
||||||
/* Enable back the aperture. */
|
|
||||||
mc_enable_ahb_redirect();
|
|
||||||
|
|
||||||
/* Return the decrypted package1 from emulated IRAM. */
|
/* Return the decrypted package1 from emulated IRAM. */
|
||||||
memcpy(package1_dec, (void *)iram_pages, package1_size);
|
memcpy(package1_dec, (void *)iram_pages, package1_size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue