diff --git a/README.md b/README.md index 23a6ec8..092fd52 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,49 @@ Nintendo Switch bootloader, firmware patcher, and more. + ## ipl config The ipl can be configured via 'hekate_ipl.ini' (if it is present on the SD card). Each ini section represents a boot entry, except for the special section 'config' that controls the global configuration. -Possible key/value combinations: +### Possible key/value combinations: - - warmboot={SD path} - - secmon={SD path} - - kernel={SD path} - - kip1={SD path} +| Config option | Description | +| ------------------ | ---------------------------------------------------------- | +| warmboot={SD path} | Replaces the warmboot binary | +| secmon={SD path} | Replaces the security monitor binary | +| kernel={SD path} | Replaces the kernel binary | +| kip1={SD path} | Replaces/Adds kernel initial process. Multiple can be set. | +| fullsvcperm=1 | Disables SVC verification | +| debugmode=1 | Enables Debug mode | + + + +``` +hekate (C) 2018 naehrwert, st4rk. + +Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8. +Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute. + +Open source and free packages used: + - FatFs R0.13a, Copyright (C) 2017, ChaN + - bcl-1.2.0, Copyright (C) 2003-2006, Marcus Geelnard + + ___ + .-' `'. + / \ + | ; + | | ___.--, + _.._ |0) = (0) | _.---'`__.-( (_. + __.--'`_.. '.__.\ '--. \_.-' ,.--'` `""` + ( ,.--'` ',__ /./; ;, '.__.'` __ + _`) ) .---.__.' / | |\ \__..--"" """--.,_ + `---' .'.''-._.-'`_./ /\ '. \ _.--''````'''--._`-.__.' + | | .' _.-' | | \ \ '. `----` + \ \/ .' \ \ '. '-._) + \/ / \ \ `=.__`'-. + / /\ `) ) / / `"".`\ + , _.-'.'\ \ / / ( ( / / + `--'` ) ) .-'.' '.'. | ( + (/` ( (` ) ) '-; [switchbrew] +``` \ No newline at end of file diff --git a/ipl/hos.c b/ipl/hos.c index 22e250a..d8dd821 100755 --- a/ipl/hos.c +++ b/ipl/hos.c @@ -190,6 +190,9 @@ typedef struct _launch_ctxt_t void *kernel; u32 kernel_size; link_t kip1_list; + + u8 *svcperm; + u8 *debugmode; } launch_ctxt_t; typedef struct _merge_kip_t @@ -321,6 +324,26 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value) return 1; } +static int _config_svcperm(launch_ctxt_t *ctxt, const char *value) +{ + if (*(u8 *)value == '1') + { + DPRINTF("Disabled SVC verification\n"); + ctxt->svcperm = malloc(1); + } + + return 1; +} + +static int _config_debugmode(launch_ctxt_t *ctxt, const char *value) +{ + if (*(u8 *)value == '1') + { + DPRINTF("Enabled Debug mode\n"); + ctxt->debugmode = malloc(1); + } +} + typedef struct _cfg_handler_t { const char *key; @@ -332,6 +355,8 @@ static const cfg_handler_t _config_handlers[] = { { "secmon", _config_secmon }, { "kernel", _config_kernel }, { "kip1", _config_kip1 }, + { "fullsvcperm", _config_svcperm }, + { "debugmode", _config_debugmode }, { NULL, NULL }, }; @@ -384,12 +409,18 @@ int hos_launch(ini_sec_t *cfg) { //Else we patch it to allow for an unsigned package2. patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset; + //In case a kernel patch option is set. Allows to disable Svc Verififcation or/and enable Debug mode + patch_t *kernel_patchset = ctxt.pkg1_id->kernel_patchset; - if (secmon_patchset != NULL) { - for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++) - *(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val; + if (secmon_patchset != NULL || (kernel_patchset != NULL && (ctxt.svcperm || ctxt.debugmode))) { + if (secmon_patchset != NULL) + { + gfx_printf(&gfx_con, "%kPatching Security Monitor%k\n", 0xFF00BAFF, 0xFFCCCCCC); + for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++) + *(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val; + } - DPRINTF("loaded warmboot.bin and secmon\n"); + gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n"); //Read package2. if (!_read_emmc_pkg2(&ctxt)) @@ -409,9 +440,19 @@ int hos_launch(ini_sec_t *cfg) { ctxt.kernel = pkg2_hdr->data; ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL]; + + if (kernel_patchset != NULL && (ctxt.svcperm || ctxt.debugmode)) + { + gfx_printf(&gfx_con, "%kPatching kernel%k\n", 0xFF00BAFF, 0xFFCCCCCC); + if (ctxt.svcperm && kernel_patchset[0].off != 0xFFFFFFFF) + *(vu32 *)(ctxt.kernel + kernel_patchset[0].off) = kernel_patchset[0].val; + if (ctxt.debugmode && kernel_patchset[1].off != 0xFFFFFFFF) + *(vu32 *)(ctxt.kernel + kernel_patchset[1].off) = kernel_patchset[1].val; + } } //Merge extra KIP1s into loaded ones. + gfx_printf(&gfx_con, "%kPatching kernel initial processes%k\n", 0xFF00BAFF, 0xFFCCCCCC); LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link) pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1); @@ -428,6 +469,8 @@ int hos_launch(ini_sec_t *cfg) } } + gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF00FF96, 0xFFCCCCCC); + se_aes_key_clear(0x8); se_aes_key_clear(0xB); diff --git a/ipl/pkg1.c b/ipl/pkg1.c index fd5e383..3787e7e 100755 --- a/ipl/pkg1.c +++ b/ipl/pkg1.c @@ -48,15 +48,15 @@ PATCHSET_DEF(_secmon_3_patchset, { 0xAC8 + 0xADC, _NOP() } //Sections SHA2. ); -PATCHSET_DEF(_secmon_5_patchset, +PATCHSET_DEF(_secmon_4_patchset, //Patch package2 decryption and signature/hash checks. { 0x1218 + 0x6E68, _NOP() }, //Header signature. { 0x1218 + 0x6E74, _NOP() }, //Version. { 0x1218 + 0x6FE4, _NOP() }, //Sections SHA2. - { 0x1218 + 0x2DC, _NOP() } //Unknown. + { 0x1218 + 0x2DC, _NOP() } //Unknown. ); -PATCHSET_DEF(_secmon_6_patchset, +PATCHSET_DEF(_secmon_5_patchset, //Patch package2 decryption and signature/hash checks. { 0x12b0 + 0x4d0, _NOP() }, { 0x12b0 + 0x4dc, _NOP() }, @@ -65,6 +65,32 @@ PATCHSET_DEF(_secmon_6_patchset, //{ 0x12b0 + 0xa18 , _NOP() } // BootConfig Retail Check ); +// Include kernel patches here, so we can utilize pkg1 id +PATCHSET_DEF(_kernel_1_patchset, + { 0x3764C, _NOP() }, // Disable SVC verifications + { 0x44074, _MOVZX(8, 1, 0) } // Enable Debug Patch +); + +PATCHSET_DEF(_kernel_2_patchset, + { 0x54834, _NOP() }, // Disable SVC verifications + { 0x6086C, _MOVZX(8, 1, 0) } // Enable Debug Patch +); + +PATCHSET_DEF(_kernel_3_patchset, + { 0x3BD24, _NOP() }, // Disable SVC verifications + { 0x483FC, _MOVZX(8, 1, 0) } // Enable Debug Patch +); + +PATCHSET_DEF(_kernel_4_patchset, + { 0x41EB4, _NOP() }, // Disable SVC verifications + { 0x4EBFC, _MOVZX(8, 1, 0) } // Enable Debug Patch +); + +PATCHSET_DEF(_kernel_5_patchset, + { 0xFFFFFFFF, 0xFFFFFFFF }, // TODO: MISSING + { 0x5513C, _MOVZX(8, 1, 0) } // Enable Debug Patch +); + /* * package1.1 header: * package1.1 layout: @@ -77,12 +103,12 @@ PATCHSET_DEF(_secmon_6_patchset, */ static const pkg1_id_t _pkg1_ids[] = { - { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, _secmon_1_patchset }, //1.0.0 - { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_2_patchset }, //2.0.0 - { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_3_patchset }, //3.0.0 - { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_3_patchset }, //3.0.1 - { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_5_patchset }, //4.0.0 - { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_6_patchset }, //5.0.0 + { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, _secmon_1_patchset, _kernel_1_patchset }, //1.0.0 + { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_2_patchset, _kernel_2_patchset }, //2.0.0 - 2.3.0 + { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_3_patchset, _kernel_3_patchset }, //3.0.0 + { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_3_patchset, _kernel_3_patchset }, //3.0.1 - 3.0.2 + { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_4_patchset, _kernel_4_patchset }, //4.0.0 - 4.1.0 + { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_5_patchset, _kernel_5_patchset }, //5.0.0 - 5.0.2 { NULL, 0, 0, 0, 0 } //End. };