From ddc52222082b367062053c0b383dbf47f7144c36 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 20 Feb 2019 13:12:15 -0800 Subject: [PATCH] sept-s: First functional version. --- fusee/fusee-primary/src/main.c | 2 +- fusee/fusee-secondary/src/main.c | 13 ++++-- fusee/fusee-secondary/src/nxboot.c | 17 ++++++- fusee/fusee-secondary/src/utils.c | 1 + sept/sept-secondary/src/di.c | 4 +- sept/sept-secondary/src/di.h | 5 -- sept/sept-secondary/src/di.inl | 9 ++-- sept/sept-secondary/src/hwinit.c | 13 ++++-- sept/sept-secondary/src/key_derivation.c | 15 ++---- sept/sept-secondary/src/main.c | 20 ++++++-- sept/sept-secondary/src/stage2.c | 58 ++++-------------------- sept/sept-secondary/src/stage2.h | 2 +- 12 files changed, 72 insertions(+), 87 deletions(-) diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 718130467..8299c70e8 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -149,7 +149,7 @@ int main(void) { /* Say hello. */ print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); - print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); + print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); /* Load the loader payload into DRAM. */ load_stage2(bct0); diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index bf2474fc3..f0ba2c261 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -98,6 +98,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(); diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 5a11aa923..f9c50f77f 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -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); diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index a847320a6..698cf7cd8 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -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); } diff --git a/sept/sept-secondary/src/di.c b/sept/sept-secondary/src/di.c index f3f76209b..b6f8116c9 100644 --- a/sept/sept-secondary/src/di.c +++ b/sept/sept-secondary/src/di.c @@ -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); diff --git a/sept/sept-secondary/src/di.h b/sept/sept-secondary/src/di.h index 5d667ecd2..4aa4f944d 100644 --- a/sept/sept-secondary/src/di.h +++ b/sept/sept-secondary/src/di.h @@ -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; diff --git a/sept/sept-secondary/src/di.inl b/sept/sept-secondary/src/di.inl index f842bfddc..e438ca5cb 100644 --- a/sept/sept-secondary/src/di.inl +++ b/sept/sept-secondary/src/di.inl @@ -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}, diff --git a/sept/sept-secondary/src/hwinit.c b/sept/sept-secondary/src/hwinit.c index 655054791..d3c7b82a2 100644 --- a/sept/sept-secondary/src/hwinit.c +++ b/sept/sept-secondary/src/hwinit.c @@ -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; diff --git a/sept/sept-secondary/src/key_derivation.c b/sept/sept-secondary/src/key_derivation.c index 0567d510a..5e05bed0a 100644 --- a/sept/sept-secondary/src/key_derivation.c +++ b/sept/sept-secondary/src/key_derivation.c @@ -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; } } diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 856578423..a87efc830 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -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) { } - - /* TODO: Chainload to payload. */ + /* Load the loader payload into DRAM. */ + load_stage2(); + + /* 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); diff --git a/sept/sept-secondary/src/stage2.c b/sept/sept-secondary/src/stage2.c index 4d1e1d9da..1a6a05b04 100644 --- a/sept/sept-secondary/src/stage2.c +++ b/sept/sept-secondary/src/stage2.c @@ -25,59 +25,17 @@ 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); print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address); diff --git a/sept/sept-secondary/src/stage2.h b/sept/sept-secondary/src/stage2.h index e453d159f..3b2579d74 100644 --- a/sept/sept-secondary/src/stage2.h +++ b/sept/sept-secondary/src/stage2.h @@ -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