fusee: Move nxboot hand-off to IRAM.
fusee/exosphere: Minor cleanup.
This commit is contained in:
@@ -175,8 +175,7 @@ bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src
|
||||
i2c_load_config(regs);
|
||||
|
||||
/* Config |= SEND; */
|
||||
regs->I2C_I2C_CNFG_0 |= 0x200;
|
||||
|
||||
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||
|
||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
@@ -203,8 +202,7 @@ bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_
|
||||
i2c_load_config(regs);
|
||||
|
||||
/* Config |= SEND; */
|
||||
regs->I2C_I2C_CNFG_0 |= 0x200;
|
||||
|
||||
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||
|
||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define I2C234_BASE 0x7000C000
|
||||
#define I2C56_BASE 0x7000D000
|
||||
#define I2C1234_BASE 0x7000C000
|
||||
#define I2C56_BASE 0x7000D000
|
||||
|
||||
#define I2C_1 0
|
||||
#define I2C_2 1
|
||||
@@ -82,10 +82,10 @@ typedef struct {
|
||||
uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0;
|
||||
} tegra_i2c_t;
|
||||
|
||||
#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000))
|
||||
#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400))
|
||||
#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500))
|
||||
#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700))
|
||||
#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000))
|
||||
#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400))
|
||||
#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500))
|
||||
#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700))
|
||||
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
||||
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->ERR_STATUS_REG) {
|
||||
if (se_get_regs()->ERR_STATUS_REG) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -53,8 +52,7 @@ void se_check_for_error(void) {
|
||||
}
|
||||
|
||||
void se_verify_flags_cleared(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->FLAGS_REG & 3) {
|
||||
if (se_get_regs()->FLAGS_REG & 3) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -193,9 +191,8 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||
}
|
||||
|
||||
void set_se_ctr(const void *ctr) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4);
|
||||
se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +234,6 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
}
|
||||
|
||||
void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
size_t num_dwords = (size >> 2);
|
||||
|
||||
if (num_dwords < 1) {
|
||||
@@ -249,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
|
||||
/* Copy endian swapped output. */
|
||||
while (num_dwords) {
|
||||
*p_out = read32be(se->RSA_OUTPUT, offset);
|
||||
*p_out = read32be(se_get_regs()->RSA_OUTPUT, offset);
|
||||
offset += 4;
|
||||
p_out--;
|
||||
num_dwords--;
|
||||
@@ -330,10 +326,8 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||
se_check_for_error();
|
||||
}
|
||||
|
||||
|
||||
/* Secure AES Functionality. */
|
||||
void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
uint8_t block[0x10] = {0};
|
||||
|
||||
if (src_size > sizeof(block) || dst_size > sizeof(block)) {
|
||||
@@ -346,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
|
||||
}
|
||||
|
||||
/* Trigger AES operation. */
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||
|
||||
/* Copy output data into dst. */
|
||||
@@ -407,7 +401,6 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si
|
||||
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202);
|
||||
}
|
||||
|
||||
|
||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
@@ -535,7 +528,6 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
se->CRYPTO_REG = (keyslot << 24) | (0x145);
|
||||
clear_aes_keyslot_iv(keyslot);
|
||||
|
||||
|
||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||
/* Handle aligned blocks. */
|
||||
if (num_blocks > 1) {
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE
|
||||
#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF
|
||||
|
||||
/* This keyslot was added in 5.0.0. */
|
||||
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
|
||||
|
||||
#define KEYSLOT_AES_MAX 0x10
|
||||
#define KEYSLOT_RSA_MAX 0x2
|
||||
|
||||
@@ -88,7 +91,7 @@
|
||||
|
||||
#define RSA_2048_BYTES 0x100
|
||||
|
||||
typedef struct security_engine {
|
||||
typedef struct {
|
||||
uint32_t _0x0;
|
||||
uint32_t _0x4;
|
||||
uint32_t OPERATION_REG;
|
||||
@@ -170,8 +173,6 @@ static inline volatile tegra_se_t *se_get_regs(void) {
|
||||
return (volatile tegra_se_t *)SE_BASE;
|
||||
}
|
||||
|
||||
/* This function MUST be registered to fire on the appropriate interrupt. */
|
||||
|
||||
void se_check_error_status_reg(void);
|
||||
void se_check_for_error(void);
|
||||
void se_trigger_interrupt(void);
|
||||
|
||||
@@ -6,6 +6,7 @@ PHDRS
|
||||
{
|
||||
crt0 PT_LOAD;
|
||||
chainloader PT_LOAD;
|
||||
nxboot PT_LOAD;
|
||||
main PT_LOAD;
|
||||
}
|
||||
|
||||
@@ -13,16 +14,17 @@ PHDRS
|
||||
MEMORY
|
||||
{
|
||||
main : ORIGIN = 0xF0000000, LENGTH = 0x10000000
|
||||
high_iram : ORIGIN = 0x40010000, LENGTH = 0x20000
|
||||
low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__start__ = 0xF0000000);
|
||||
PROVIDE(__stack_top__ = 0x40010000);
|
||||
PROVIDE(__stack_bottom__ = 0x4000C000);
|
||||
PROVIDE(__heap_start__ = 0xE0000000);
|
||||
PROVIDE(__heap_end__ = 0xF0000000);
|
||||
PROVIDE(__stack_top__ = 0x90020000);
|
||||
PROVIDE(__stack_bottom__ = 0x90010000);
|
||||
PROVIDE(__heap_start__ = 0x90020000);
|
||||
PROVIDE(__heap_end__ = 0xA0020000);
|
||||
|
||||
. = __start__;
|
||||
|
||||
@@ -53,6 +55,27 @@ SECTIONS
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__chainloader_end__ = ABSOLUTE(.));
|
||||
} >low_iram :NONE
|
||||
|
||||
.nxboot_loadable :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__nxboot_start__ = ABSOLUTE(.));
|
||||
PROVIDE (__nxboot_lma__ = LOADADDR(.nxboot_loadable));
|
||||
KEEP(*(.nxboot.text.start))
|
||||
nxboot_iram.o(.text*)
|
||||
nxboot_iram.o(.rodata*)
|
||||
nxboot_iram.o(.data*)
|
||||
. = ALIGN(32);
|
||||
} >high_iram AT>main :nxboot
|
||||
|
||||
.nxboot_bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__nxboot_bss_start__ = ABSOLUTE(.));
|
||||
nxboot_iram.o(.bss* COMMON)
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__nxboot_end__ = ABSOLUTE(.));
|
||||
} >high_iram :NONE
|
||||
|
||||
.text :
|
||||
{
|
||||
|
||||
@@ -175,8 +175,7 @@ bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src
|
||||
i2c_load_config(regs);
|
||||
|
||||
/* Config |= SEND; */
|
||||
regs->I2C_I2C_CNFG_0 |= 0x200;
|
||||
|
||||
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||
|
||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
@@ -203,8 +202,7 @@ bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_
|
||||
i2c_load_config(regs);
|
||||
|
||||
/* Config |= SEND; */
|
||||
regs->I2C_I2C_CNFG_0 |= 0x200;
|
||||
|
||||
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||
|
||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define I2C234_BASE 0x7000C000
|
||||
#define I2C56_BASE 0x7000D000
|
||||
#define I2C1234_BASE 0x7000C000
|
||||
#define I2C56_BASE 0x7000D000
|
||||
|
||||
#define I2C_1 0
|
||||
#define I2C_2 1
|
||||
@@ -82,10 +82,10 @@ typedef struct {
|
||||
uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0;
|
||||
} tegra_i2c_t;
|
||||
|
||||
#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000))
|
||||
#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400))
|
||||
#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500))
|
||||
#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700))
|
||||
#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000))
|
||||
#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400))
|
||||
#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500))
|
||||
#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700))
|
||||
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
||||
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
||||
|
||||
|
||||
@@ -51,8 +51,11 @@ static void __program_init_newlib_hooks(void) {
|
||||
static void __program_move_additional_sections(void) {
|
||||
#if defined(FUSEE_STAGE1_SRC) || defined(FUSEE_STAGE2_SRC)
|
||||
extern uint8_t __chainloader_lma__[], __chainloader_start__[], __chainloader_bss_start__[], __chainloader_end__[];
|
||||
extern uint8_t __nxboot_lma__[], __nxboot_start__[], __nxboot_bss_start__[], __nxboot_end__[];
|
||||
memcpy(__chainloader_start__, __chainloader_lma__, __chainloader_bss_start__ - __chainloader_start__);
|
||||
memset(__chainloader_bss_start__, 0, __chainloader_end__ - __chainloader_bss_start__);
|
||||
memcpy(__nxboot_start__, __nxboot_lma__, __nxboot_bss_start__ - __nxboot_start__);
|
||||
memset(__nxboot_bss_start__, 0, __nxboot_end__ - __nxboot_bss_start__);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,8 @@ int main(int argc, void **argv) {
|
||||
g_do_nxboot = loader_ctx->chainload_entrypoint == 0;
|
||||
if (g_do_nxboot) {
|
||||
printf("Now performing nxboot.\n");
|
||||
nxboot_main();
|
||||
uint32_t boot_memaddr = nxboot_main();
|
||||
nxboot_finish(boot_memaddr);
|
||||
} else {
|
||||
/* TODO: What else do we want to do in terms of argc/argv? */
|
||||
const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint];
|
||||
|
||||
@@ -185,9 +185,8 @@ static void nxboot_move_bootconfig() {
|
||||
|
||||
/* This is the main function responsible for booting Horizon. */
|
||||
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
||||
void nxboot_main(void) {
|
||||
uint32_t nxboot_main(void) {
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||
package2_header_t *package2;
|
||||
size_t package2_size;
|
||||
@@ -397,43 +396,6 @@ void nxboot_main(void) {
|
||||
}
|
||||
free(package2);
|
||||
|
||||
/* Clear used keyslots. */
|
||||
clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY);
|
||||
clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY);
|
||||
|
||||
/* Lock keyslots. */
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF);
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF);
|
||||
} else {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF);
|
||||
}
|
||||
|
||||
/* Finalize the GPU UCODE carveout. */
|
||||
mc_config_carveout_finalize();
|
||||
|
||||
/* Lock AES keyslots. */
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
set_aes_keyslot_flags(i, 0x15);
|
||||
|
||||
/* Lock RSA keyslots. */
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
set_rsa_keyslot_flags(i, 1);
|
||||
|
||||
/* Lock the Security Engine. */
|
||||
se->_0x4 = 0;
|
||||
se->AES_KEY_READ_DISABLE_REG = 0;
|
||||
se->RSA_KEY_READ_DISABLE_REG = 0;
|
||||
se->_0x0 &= 0xFFFFFFFB;
|
||||
|
||||
/* Boot up Exosphère. */
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
|
||||
}
|
||||
|
||||
printf("[NXBOOT]: Powering on the CCPLEX...\n");
|
||||
|
||||
/* Display splash screen. */
|
||||
@@ -442,26 +404,6 @@ void nxboot_main(void) {
|
||||
/* Unmount everything. */
|
||||
nxfs_unmount_all();
|
||||
|
||||
/* Terminate the display. */
|
||||
display_end();
|
||||
|
||||
/* Boot CPU0. */
|
||||
cluster_boot_cpu0((uint32_t)exosphere_memaddr);
|
||||
|
||||
/* Wait for Exosphère to wake up. */
|
||||
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* Signal Exosphère. */
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X;
|
||||
}
|
||||
|
||||
/* Halt ourselves in waitevent state. */
|
||||
while (1) {
|
||||
FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000;
|
||||
}
|
||||
/* Return the memory address for booting CPU0. */
|
||||
return (uint32_t)exosphere_memaddr;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ typedef struct {
|
||||
uint32_t boot_reason_state;
|
||||
} boot_reason_t;
|
||||
|
||||
void nxboot_main(void);
|
||||
uint32_t nxboot_main(void);
|
||||
void nxboot_finish(uint32_t boot_memaddr);
|
||||
|
||||
#endif
|
||||
|
||||
90
fusee/fusee-secondary/src/nxboot_iram.c
Normal file
90
fusee/fusee-secondary/src/nxboot_iram.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cluster.h"
|
||||
#include "di.h"
|
||||
#include "exocfg.h"
|
||||
#include "flow.h"
|
||||
#include "mc.h"
|
||||
#include "nxboot.h"
|
||||
#include "se.h"
|
||||
#include "timers.h"
|
||||
|
||||
void nxboot_finish(uint32_t boot_memaddr) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
/* Clear used keyslots. */
|
||||
clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY);
|
||||
clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY);
|
||||
|
||||
/* Lock keyslots. */
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF);
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF);
|
||||
} else {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF);
|
||||
}
|
||||
|
||||
/* Finalize the GPU UCODE carveout. */
|
||||
mc_config_carveout_finalize();
|
||||
|
||||
/* Lock AES keyslots. */
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
set_aes_keyslot_flags(i, 0x15);
|
||||
|
||||
/* Lock RSA keyslots. */
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
set_rsa_keyslot_flags(i, 1);
|
||||
|
||||
/* Lock the Security Engine. */
|
||||
se->_0x4 = 0;
|
||||
se->AES_KEY_READ_DISABLE_REG = 0;
|
||||
se->RSA_KEY_READ_DISABLE_REG = 0;
|
||||
se->_0x0 &= 0xFFFFFFFB;
|
||||
|
||||
/* Boot up Exosphère. */
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
|
||||
}
|
||||
|
||||
/* Terminate the display. */
|
||||
display_end();
|
||||
|
||||
/* Boot CPU0. */
|
||||
cluster_boot_cpu0(boot_memaddr);
|
||||
|
||||
/* Wait for Exosphère to wake up. */
|
||||
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* Signal Exosphère. */
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X;
|
||||
}
|
||||
|
||||
/* Halt ourselves in waitevent state. */
|
||||
while (1) {
|
||||
FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000;
|
||||
}
|
||||
}
|
||||
@@ -39,8 +39,7 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->ERR_STATUS_REG) {
|
||||
if (se_get_regs()->ERR_STATUS_REG) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -53,8 +52,7 @@ void se_check_for_error(void) {
|
||||
}
|
||||
|
||||
void se_verify_flags_cleared(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->FLAGS_REG & 3) {
|
||||
if (se_get_regs()->FLAGS_REG & 3) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -193,9 +191,8 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||
}
|
||||
|
||||
void set_se_ctr(const void *ctr) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4);
|
||||
se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +234,6 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
}
|
||||
|
||||
void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
size_t num_dwords = (size >> 2);
|
||||
|
||||
if (num_dwords < 1) {
|
||||
@@ -249,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
|
||||
/* Copy endian swapped output. */
|
||||
while (num_dwords) {
|
||||
*p_out = read32be(se->RSA_OUTPUT, offset);
|
||||
*p_out = read32be(se_get_regs()->RSA_OUTPUT, offset);
|
||||
offset += 4;
|
||||
p_out--;
|
||||
num_dwords--;
|
||||
@@ -330,10 +326,8 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||
se_check_for_error();
|
||||
}
|
||||
|
||||
|
||||
/* Secure AES Functionality. */
|
||||
void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
uint8_t block[0x10] = {0};
|
||||
|
||||
if (src_size > sizeof(block) || dst_size > sizeof(block)) {
|
||||
@@ -346,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
|
||||
}
|
||||
|
||||
/* Trigger AES operation. */
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||
|
||||
/* Copy output data into dst. */
|
||||
@@ -407,7 +401,6 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si
|
||||
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202);
|
||||
}
|
||||
|
||||
|
||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
@@ -535,7 +528,6 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
se->CRYPTO_REG = (keyslot << 24) | (0x145);
|
||||
clear_aes_keyslot_iv(keyslot);
|
||||
|
||||
|
||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||
/* Handle aligned blocks. */
|
||||
if (num_blocks > 1) {
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE
|
||||
#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF
|
||||
|
||||
/* This keyslot was added in 5.0.0. */
|
||||
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
|
||||
|
||||
#define KEYSLOT_AES_MAX 0x10
|
||||
#define KEYSLOT_RSA_MAX 0x2
|
||||
|
||||
@@ -88,7 +91,7 @@
|
||||
|
||||
#define RSA_2048_BYTES 0x100
|
||||
|
||||
typedef struct security_engine {
|
||||
typedef struct {
|
||||
uint32_t _0x0;
|
||||
uint32_t _0x4;
|
||||
uint32_t OPERATION_REG;
|
||||
@@ -170,8 +173,6 @@ static inline volatile tegra_se_t *se_get_regs(void) {
|
||||
return (volatile tegra_se_t *)SE_BASE;
|
||||
}
|
||||
|
||||
/* This function MUST be registered to fire on the appropriate interrupt. */
|
||||
|
||||
void se_check_error_status_reg(void);
|
||||
void se_check_for_error(void);
|
||||
void se_trigger_interrupt(void);
|
||||
|
||||
@@ -31,5 +31,5 @@ void display_splash_screen_bmp(const char *custom_splash_path) {
|
||||
/* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */
|
||||
|
||||
/* Display the splash screen for three seconds. */
|
||||
/* udelay(3000000); */
|
||||
udelay(3000000);
|
||||
}
|
||||
|
||||
@@ -70,3 +70,12 @@ _start:
|
||||
relocate_and_chainload:
|
||||
ldr sp, =__stack_top__
|
||||
b relocate_and_chainload_main
|
||||
|
||||
.section .nxboot.text.start, "ax", %progbits
|
||||
.arm
|
||||
.align 5
|
||||
.global nxboot
|
||||
.type nxboot, %function
|
||||
nxboot:
|
||||
ldr sp, =__stack_top__
|
||||
b nxboot_finish
|
||||
Reference in New Issue
Block a user