diff --git a/Makefile b/Makefile index 60ab0d5..a052421 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ include $(DEVKITARM)/base_rules IPL_LOAD_ADDR := 0x40003000 LPVERSION_MAJOR := 0 LPVERSION_MINOR := 6 -LPVERSION_BUGFX := 6 +LPVERSION_BUGFX := 7 ################################################################################ diff --git a/source/incognito/incognito.c b/source/incognito/incognito.c index 3f1daa0..1ee178c 100644 --- a/source/incognito/incognito.c +++ b/source/incognito/incognito.c @@ -69,7 +69,8 @@ extern int sd_save_to_file(void *buf, u32 size, const char *filename); extern hekate_config h_cfg; u32 _key_count = 0; -sdmmc_storage_t storage; +//sdmmc_storage_t storage; +emmc_part_t prodinfo_part; sdmmc_t sdmmc; #define SECTORS_IN_CLUSTER 32 @@ -184,7 +185,7 @@ bool dump_keys() tsec_ctxt_t tsec_ctxt; - if (emummc_storage_init_mmc(&storage, &sdmmc) == 2) + if (emummc_storage_init_mmc(&emmc_storage, &sdmmc) == 2) { EPRINTF("Unable to init MMC."); return false; @@ -192,8 +193,8 @@ bool dump_keys() // Read package1. u8 *pkg1 = (u8 *)malloc(0x40000); - emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0); - emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1); + emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0); + emummc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1); const pkg1_id_t *pkg1_id = pkg1_identify(pkg1); if (!pkg1_id) { @@ -298,7 +299,7 @@ bool dump_keys() } // verify keyblob is not corrupt - emummc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + i, 1, keyblob_block); + emummc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + i, 1, keyblob_block); se_aes_key_set(3, keyblob_mac_key[i], 0x10); se_aes_cmac(3, keyblob_mac, 0x10, keyblob_block + 0x10, 0xa0); if (memcmp(keyblob_block, keyblob_mac, 0x10) != 0) @@ -351,14 +352,13 @@ bool dump_keys() memcpy(bis_key[3], bis_key[2], 0x20); } - emummc_storage_set_mmc_partition(&storage, EMMC_GPP); + emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP); // Parse eMMC GPT. LIST_INIT(gpt); - nx_emmc_gpt_parse(&gpt, &storage); + nx_emmc_gpt_parse(&gpt, &emmc_storage); // Find PRODINFO partition. emmc_part_t *prodinfo_part = nx_emmc_part_find(&gpt, "PRODINFO"); - //prodinfo_part = nx_emmc_part_find(&gpt, "PRODINFO"); if (!prodinfo_part) { EPRINTF("Failed to locate PRODINFO."); @@ -497,10 +497,10 @@ u32 divideCeil(u32 x, u32 y) void cleanUp() { - - h_cfg.emummc_force_disable = emummc_load_cfg(); - //nx_emmc_gpt_free(&gpt); - //emummc_storage_end(&storage); + emummc_load_cfg(); + // Ignore whether emummc is enabled. + h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path; + emummc_storage_end(&emmc_storage); } static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed) diff --git a/source/incognito/incognito.h b/source/incognito/incognito.h index 84d1bba..70d8951 100644 --- a/source/incognito/incognito.h +++ b/source/incognito/incognito.h @@ -17,7 +17,7 @@ #ifndef _KEYS_H_ #define _KEYS_H_ -#include "../utils/types.h" +#include //testing diff --git a/source/incognito/io/io.c b/source/incognito/io/io.c index fcc9f12..d75192a 100644 --- a/source/incognito/io/io.c +++ b/source/incognito/io/io.c @@ -1,81 +1,81 @@ #include "io.h" -#include "../../storage/sdmmc.h" +#include #include "../../storage/nx_emmc.h" #include "../../storage/emummc.h" #include -#include "../../sec/se.h" +#include extern sdmmc_storage_t storage; extern emmc_part_t *prodinfo_part; static inline void _gf256_mul_x_le(void *block) { - u8 *pdata = (u8 *)block; + u32 *pdata = (u32 *)block; u32 carry = 0; - for (u32 i = 0; i < 0x10; i++) + for (u32 i = 0; i < 4; i++) { - u8 b = pdata[i]; + u32 b = pdata[i]; pdata[i] = (b << 1) | carry; - carry = b >> 7; + carry = b >> 31; } if (carry) pdata[0x0] ^= 0x87; } -static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 secsize) +static int _nx_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u32 sec, void *dst, const void *src, u32 sec_size) { - int res = 0; - u8 *pdst = (u8 *)dst; - u8 *psrc = (u8 *)src; + u32 *pdst = (u32 *)dst; + u32 *psrc = (u32 *)src; + u32 *ptweak = (u32 *)tweak; - if (regen_tweak) - { - for (int i = 0xF; i >= 0; i--) - { - tweak[i] = sec & 0xFF; - sec >>= 8; - } - if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak)) - goto out; - } + if (regen_tweak) + { + for (int i = 0xF; i >= 0; i--) + { + tweak[i] = sec & 0xFF; + sec >>= 8; + } + if (!se_aes_crypt_block_ecb(tweak_ks, 1, tweak, tweak)) + return 0; + } - for (u32 i = 0; i < tweak_exp * 0x20; i++) - _gf256_mul_x_le(tweak); + // tweak_exp allows us to use a saved tweak to reduce _gf256_mul_x_le calls. + for (u32 i = 0; i < (tweak_exp << 5); i++) + _gf256_mul_x_le(tweak); - u8 temptweak[0x10]; - memcpy(temptweak, tweak, 0x10); + u8 orig_tweak[0x10]; + memcpy(orig_tweak, tweak, 0x10); - //We are assuming a 0x10-aligned sector size in this implementation. - for (u32 i = 0; i < secsize / 0x10; i++) - { - for (u32 j = 0; j < 0x10; j++) - pdst[j] = psrc[j] ^ tweak[j]; - _gf256_mul_x_le(tweak); - psrc += 0x10; - pdst += 0x10; - } + // We are assuming a 0x10-aligned sector size in this implementation. + for (u32 i = 0; i < (sec_size >> 4); i++) + { + for (u32 j = 0; j < 4; j++) + pdst[j] = psrc[j] ^ ptweak[j]; - se_aes_crypt_ecb(ks2, enc, dst, secsize, src, secsize); + _gf256_mul_x_le(tweak); + psrc += 4; + pdst += 4; + } - pdst = (u8 *)dst; + if (!se_aes_crypt_ecb(crypt_ks, enc, dst, sec_size, dst, sec_size)) + return 0; - memcpy(tweak, temptweak, 0x10); - for (u32 i = 0; i < secsize / 0x10; i++) - { - for (u32 j = 0; j < 0x10; j++) - pdst[j] = pdst[j] ^ tweak[j]; - _gf256_mul_x_le(tweak); - pdst += 0x10; - } + pdst = (u32 *)dst; + ptweak = (u32 *)orig_tweak; + for (u32 i = 0; i < (sec_size >> 4); i++) + { + for (u32 j = 0; j < 4; j++) + pdst[j] = pdst[j] ^ ptweak[j]; - res = 1; + _gf256_mul_x_le(orig_tweak); + pdst += 4; + } -out:; - return res; + return 1; } // replacement for nx_emmc_part_write in storage/nx_emmc, which uses sdmmc_storage_write @@ -100,7 +100,7 @@ bool prodinfo_read( u32 tweak_exp = 0; bool regen_tweak = true; - if (nx_emmc_part_read(&storage, prodinfo_part, sector, count, buff)) + if (nx_emmc_part_read(&emmc_storage, prodinfo_part, sector, count, buff)) { if (prev_cluster != sector / 0x20) { // sector in different cluster than last read @@ -118,7 +118,7 @@ bool prodinfo_read( } // fatfs will never pull more than a cluster - result = _emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200); + result = _nx_aes_xts_crypt_sec(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200); prev_sector = sector + count - 1; return result; @@ -155,10 +155,10 @@ bool prodinfo_write( } // fatfs will never pull more than a cluster - if(!_emmc_xts(9, 8, 1, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200)){ + if(!_nx_aes_xts_crypt_sec(9, 8, 1, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200)){ return false; } - if (nx_emummc_part_write(&storage, prodinfo_part, sector, count, buff)) + if (nx_emummc_part_write(&emmc_storage, prodinfo_part, sector, count, buff)) { prev_sector = sector + count - 1; return true; diff --git a/source/incognito/io/io.h b/source/incognito/io/io.h index 6383220..94cc096 100644 --- a/source/incognito/io/io.h +++ b/source/incognito/io/io.h @@ -1,7 +1,7 @@ #ifndef _IO_DEFINED #define _IO_DEFINED -#include "../../utils/types.h" +#include bool prodinfo_read (u8 *buff, u32 sector, u32 count); bool prodinfo_write (u8 *buff, u32 sector, u32 count); diff --git a/source/main.c b/source/main.c index a49ac5b..aee85f7 100644 --- a/source/main.c +++ b/source/main.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -246,7 +247,7 @@ void launch_tools() memcpy(dir, "sd:/bootloader/payloads", 24); - filelist = dirlist(dir, NULL, false); + filelist = dirlist(dir, NULL, false, false); u32 i = 0; u32 i_off = 2; @@ -485,25 +486,43 @@ extern void pivot_stack(u32 stack_top); void ipl_main() { + // Do initial HW configuration. This is compatible with consecutive reruns without a reset. config_hw(); + + // Pivot the stack so we have enough space. pivot_stack(IPL_STACK_TOP); + + // Tegra/Horizon configuration goes to 0x80000000+, package2 goes to 0xA9800000, we place our heap in between. heap_init(IPL_HEAP_START); +#ifdef DEBUG_UART_PORT + uart_send(DEBUG_UART_PORT, (u8 *)"hekate: Hello!\r\n", 16); + uart_wait_idle(DEBUG_UART_PORT, UART_TX_IDLE); +#endif + + // Set bootloader's default configuration. set_default_configuration(); sd_mount(); + minerva_init(); minerva_change_freq(FREQ_1600); display_init(); - u32 *fb = display_init_framebuffer(); + + u32 *fb = display_init_framebuffer_pitch(); gfx_init_ctxt(fb, 720, 1280, 720); + gfx_con_init(); + display_backlight_pwm_init(); + // Overclock BPMP. bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); - h_cfg.emummc_force_disable = emummc_load_cfg(); + emummc_load_cfg(); + // Ignore whether emummc is enabled. + h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path; // if (b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN) // {