sept-s: First functional version.

This commit is contained in:
Michael Scire 2019-02-20 13:12:15 -08:00
parent f1068d6c3f
commit ddc5222208
12 changed files with 72 additions and 87 deletions

View file

@ -99,6 +99,14 @@ int main(int argc, void **argv) {
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, u8"Welcome to Atmosphère Fusée Stage 2!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]);
/* Load BCT0 from SD if needed. */
if (strcmp(g_stage2_args->bct0, "") == 0) {
read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini");
if (!read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini")) {
fatal_error("Failed to read BCT0 from SD!\n");
}
}
/* This will load all remaining binaries off of the SD. */
load_payload(g_stage2_args->bct0);
@ -106,10 +114,7 @@ int main(int argc, void **argv) {
g_do_nxboot = loader_ctx->chainload_entrypoint == 0;
if (g_do_nxboot) {
/* Display splash screen. */
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000);
print(SCREEN_LOG_LEVEL_MANDATORY, "Now performing nxboot.\n");
print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n");
uint32_t boot_memaddr = nxboot_main();
/* Wait for the splash screen to have been displayed as long as it should be. */
splash_screen_wait_delay();

View file

@ -38,6 +38,7 @@
#include "flow.h"
#include "timers.h"
#include "key_derivation.h"
#include "masterkey.h"
#include "package1.h"
#include "package2.h"
#include "smmu.h"
@ -47,6 +48,7 @@
#include "exocfg.h"
#include "display/video_fb.h"
#include "lib/ini.h"
#include "splash_screen.h"
#define u8 uint8_t
#define u32 uint32_t
@ -419,7 +421,7 @@ uint32_t nxboot_main(void) {
}
}
print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n");
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Loaded firmware from eMMC...\n");
/* Get the TSEC keys. */
uint8_t tsec_key[0x10] = {0};
@ -428,7 +430,12 @@ uint32_t nxboot_main(void) {
/* Detect whether we need to run sept-secondary in order to derive keys. */
if (!get_and_clear_has_run_sept()) {
reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size);
} else {
if (mkey_detect_revision(fuse_get_retail_type() != 0) != 0) {
fatal_error("[NXBOOT]: Sept derived incorrect keys!\n");
}
}
get_and_clear_has_run_sept();
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
uint8_t tsec_keys[0x20] = {0};
@ -445,6 +452,10 @@ uint32_t nxboot_main(void) {
}
}
//fatal_error("Ran sept!");
/* Display splash screen. */
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000);
/* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */
unsigned int keygen_type = 0;
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) {
@ -528,11 +539,13 @@ uint32_t nxboot_main(void) {
pmc->scratch1 = (uint32_t)warmboot_memaddr;
}
print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Rebuilding package2...\n");
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Rebuilding package2...\n");
/* Parse stratosphere config. */
nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Configured Stratosphere...\n");
/* Patch package2, adding Thermosphère + custom KIPs. */
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);

View file

@ -153,6 +153,7 @@ void wait_for_button(void) {
}
__attribute__ ((noreturn)) void generic_panic(void) {
print(SCREEN_LOG_LEVEL_ERROR, "generic panic from %p", __builtin_return_address(0));
panic(0xFF000006);
}

View file

@ -111,7 +111,7 @@ void display_init()
exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4);
exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94);
exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 61);
exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60);
udelay(10000);
@ -149,8 +149,8 @@ void display_init()
udelay(20000);
exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3);
exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21);
exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3);
MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4;
exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10);

View file

@ -190,7 +190,6 @@
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION (1 << 0)
#define V_DIRECTION (1 << 2)
#define SCAN_COLUMN (1 << 4)
#define COLOR_EXPAND (1 << 6)
#define CSC_ENABLE (1 << 18)
#define WIN_ENABLE (1 << 30)
@ -238,8 +237,6 @@
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
#define DC_WIN_DV_CONTROL 0x70E
/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
@ -350,8 +347,6 @@
#define DSI_PAD_CONTROL_4 0x52
#define DSI_INIT_SEQ_DATA_15 0x5F
typedef struct _cfg_op_t
{
uint32_t off;

View file

@ -128,7 +128,7 @@ static const cfg_op_t _display_config_2[94] = {
};
//DSI Init config.
static const cfg_op_t _display_config_3[61] = {
static const cfg_op_t _display_config_3[60] = {
{DSI_WR_DATA, 0},
{DSI_INT_ENABLE, 0},
{DSI_INT_STATUS, 0},
@ -137,7 +137,6 @@ static const cfg_op_t _display_config_3[61] = {
{DSI_INIT_SEQ_DATA_1, 0},
{DSI_INIT_SEQ_DATA_2, 0},
{DSI_INIT_SEQ_DATA_3, 0},
{DSI_INIT_SEQ_DATA_15, 0},
{DSI_DCS_CMDS, 0},
{DSI_PKT_SEQ_0_LO, 0},
{DSI_PKT_SEQ_1_LO, 0},
@ -289,7 +288,7 @@ static const cfg_op_t _display_config_7[10] = {
static const cfg_op_t _display_config_8[6] = {
{0x18, 0},
{2, 0xF3F10000},
{0x16, 0},
{0x16, 1},
{0x18, 0},
{0x18, 0x10010},
{0x17, 0x300}
@ -475,10 +474,10 @@ static const cfg_op_t _display_config_13[16] = {
{DSI_PAD_CONTROL_1, 0},
{DSI_PHY_TIMING_0, 0x6070601},
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30118},
{DSI_PHY_TIMING_2, 0x30109},
{DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},

View file

@ -185,23 +185,30 @@ void config_se_brom()
void nx_hwinit()
{
volatile tegra_car_t *car = car_get_regs();
volatile tegra_pmc_t *pmc = pmc_get_regs();
volatile tegra_car_t *car = car_get_regs();
/* This stuff was handled by whatever loaded us. */
/* Bootrom stuff we skipped by going through RCM. */
config_se_brom();
AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F;
pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD);
/* Apply the memory built-in self test workaround. */
mbist_workaround();
/* Reboot SE. */
clkrst_reboot(CARDEVICE_SE);
/* Initialize the fuse driver. */
fuse_init();
/* Initialize the memory controller. */
mc_enable();
/* Configure oscillators. */
config_oscillators();
/* Disable pinmux tristate input clamping. */
APB_MISC_PP_PINMUX_GLOBAL_0 = 0;

View file

@ -48,7 +48,6 @@ static const uint8_t AL16 new_master_kek_seed_7x[0x10] = {
void derive_7x_keys(const void *tsec_key, void *tsec_root_key) {
uint8_t AL16 work_buffer[0x10];
uint8_t AL16 master_kek[0x10];
/* Set keyslot flags properly in preparation of derivation. */
set_aes_keyslot_flags(0xE, 0x15);
@ -61,15 +60,12 @@ void derive_7x_keys(const void *tsec_key, void *tsec_root_key) {
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, keyblob_seed_00, 0x10);
decrypt_data_into_keyslot(0xF, 0xE, work_buffer, 0x10);
/* Derive the master kek. */
set_aes_keyslot(0xC, tsec_root_key, 0x10);
se_aes_ecb_decrypt_block(0xC, master_kek, 0x10, new_master_kek_seed_7x, 0x10);
/* Clear the SBK. */
clear_aes_keyslot(0xE);
/* Set master kek. */
set_aes_keyslot(0xC, master_kek, 0x10);
/* Derive the master kek. */
set_aes_keyslot(0xC, tsec_root_key, 0x10);
decrypt_data_into_keyslot(0xC, 0xC, new_master_kek_seed_7x, 0x10);
/* Derive keys for exosphere. */
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
@ -78,8 +74,7 @@ void derive_7x_keys(const void *tsec_key, void *tsec_root_key) {
decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10);
/* Clear master kek from memory. */
for (size_t i = 0; i < sizeof(master_kek); i++) {
master_kek[i] = 0xCC;
for (size_t i = 0; i < sizeof(work_buffer); i++) {
work_buffer[i] = 0xCC;
}
}

View file

@ -83,7 +83,7 @@ static void exfiltrate_keys_and_reboot_if_needed(void) {
}
/* Clear the security engine state. */
for (size_t i = 0; i < 0x1000; i += 4) {
for (size_t i = 0; i < 0x840; i += 4) {
MAKE_REG32((uintptr_t)(enc_se_state) + i) = 0xCCCCCCCC;
MAKE_REG32((uintptr_t)(dec_se_state) + i) = 0xCCCCCCCC;
}
@ -140,6 +140,9 @@ static void exit_callback(int rc) {
}
int main(void) {
const char *stage2_path;
stage2_args_t *stage2_args;
uint32_t stage2_version = 0;
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY;
/* Extract keys from the security engine, which TSEC FW locked down. */
@ -166,9 +169,18 @@ int main(void) {
/* Mark EMC scratch to say that sept has run. */
MAKE_EMC_REG(EMC_SCRATCH0) |= 0x80000000;
while (true) { }
/* Load the loader payload into DRAM. */
load_stage2();
/* TODO: Chainload to payload. */
/* Setup argument data. */
stage2_path = stage2_get_program_path();
strcpy(g_chainloader_arg_data, stage2_path);
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
memcpy(&stage2_args->version, &stage2_version, 4);
memcpy(&stage2_args->log_level, &log_level, sizeof(log_level));
stage2_args->display_initialized = false;
strcpy(stage2_args->bct0, "");
g_chainloader_argc = 2;
/* Wait a while. */
mdelay(1000);

View file

@ -25,58 +25,16 @@ const char *stage2_get_program_path(void) {
return g_stage2_path;
}
static int stage2_ini_handler(void *user, const char *section, const char *name, const char *value) {
stage2_config_t *config = (stage2_config_t *)user;
uintptr_t x = 0;
if (strcmp(section, "stage1") == 0) {
if (strcmp(name, STAGE2_NAME_KEY) == 0) {
strncpy(config->path, value, sizeof(config->path) - 1);
config->path[sizeof(config->path) - 1] = '\0';
} else if (strcmp(name, STAGE2_ADDRESS_KEY) == 0) {
/* Read in load address as a hex string. */
sscanf(value, "%x", &x);
config->load_address = x;
if (config->entrypoint == 0) {
config->entrypoint = config->load_address;
}
} else if (strcmp(name, STAGE2_ENTRYPOINT_KEY) == 0) {
/* Read in entrypoint as a hex string. */
sscanf(value, "%x", &x);
config->entrypoint = x;
} else {
return 0;
}
} else {
return 0;
}
return 1;
}
void load_stage2(const char *bct0) {
stage2_config_t config = {0};
/* We get the luxury of assuming a constant filename/load address. */
void load_stage2(void) {
FILINFO info;
size_t size;
uintptr_t tmp_addr;
if (ini_parse_string(bct0, stage2_ini_handler, &config) < 0) {
fatal_error("Failed to parse BCT.ini!\n");
}
if (config.load_address == 0 || config.path[0] == '\x00') {
fatal_error("Failed to determine where to load stage2!\n");
}
if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) {
print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n");
}
if (!check_32bit_address_loadable(config.entrypoint)) {
fatal_error("Stage2's entrypoint is invalid!\n");
}
if (!check_32bit_address_loadable(config.load_address)) {
fatal_error("Stage2's load address is invalid!\n");
}
stage2_config_t config = {
.path = "sept/payload.bin",
.load_address = 0xF0000000,
.entrypoint = 0xF0000000,
};
print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n");
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path);

View file

@ -50,6 +50,6 @@ typedef struct {
} stage2_args_t;
const char *stage2_get_program_path(void);
void load_stage2(const char *bct0);
void load_stage2(void);
#endif