diff --git a/README.md b/README.md index c913b22..dcd6f32 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ 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 - - Atmosphère (se_calculate_sha256), Copyright (C) 2018, Atmosphère-NX + - Atmosphère (SE sha256, prc id kernel patches), Copyright (C) 2018, Atmosphère-NX ___ .-' `'. diff --git a/ipl/arm64.h b/ipl/arm64.h index da15bf1..5325df1 100755 --- a/ipl/arm64.h +++ b/ipl/arm64.h @@ -27,7 +27,7 @@ #define _ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F) #define _BL(a, o) 0x94000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF) -#define _B(a, o) 0x94000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF) +#define _B(a, o) 0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF) #define _MOVKX(r, i, s) 0xF2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) #define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) #define _NOP() 0xD503201F diff --git a/ipl/hos.c b/ipl/hos.c index 4d8c5c9..a8d2410 100755 --- a/ipl/hos.c +++ b/ipl/hos.c @@ -65,6 +65,7 @@ typedef struct _launch_ctxt_t int svcperm; int debugmode; + int atmosphere; } launch_ctxt_t; typedef struct _merge_kip_t @@ -80,6 +81,9 @@ typedef struct _merge_kip_t #define KB_FIRMWARE_VERSION_500 4 #define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_500 +// Exosphere magic "XBC0" +#define MAGIC_EXOSPHERE 0x30434258 + static const u8 keyblob_keyseeds[][0x10] = { { 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, //1.0.0 { 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, //3.0.0 @@ -205,6 +209,23 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw) return 1; } +static void _copy_bootconfig(launch_ctxt_t *ctxt) +{ + sdmmc_storage_t storage; + sdmmc_t sdmmc; + + sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4); + + //Read BCT. + u8 *buf = (u8 *)0x4003D000; + sdmmc_storage_set_mmc_partition(&storage, 1); + sdmmc_storage_read(&storage, 0, 0x3000 / NX_EMMC_BLOCKSIZE, buf); + + gfx_printf(&gfx_con, "Copied BCT to 0x4003D000\n"); + + sdmmc_storage_end(&storage); +} + static int _read_emmc_pkg1(launch_ctxt_t *ctxt) { int res = 0; @@ -348,6 +369,16 @@ static int _config_debugmode(launch_ctxt_t *ctxt, const char *value) return 1; } +static int _config_atmosphere(launch_ctxt_t *ctxt, const char *value) +{ + if (*value == '1') + { + DPRINTF("Enabled atmosphere patching\n"); + ctxt->atmosphere = 1; + } + return 1; +} + typedef struct _cfg_handler_t { const char *key; @@ -361,6 +392,7 @@ static const cfg_handler_t _config_handlers[] = { { "kip1", _config_kip1 }, { "fullsvcperm", _config_svcperm }, { "debugmode", _config_debugmode }, + { "atmosphere", _config_atmosphere }, { NULL, NULL }, }; @@ -376,8 +408,9 @@ static int _config(launch_ctxt_t *ctxt, ini_sec_t *cfg) int hos_launch(ini_sec_t *cfg) { - int bootStateDramPkg2; - int bootStatePkg2Continue; + int bootStateDramPkg2 = 0; + int bootStatePkg2Continue = 0; + int exoFwNumber = 0; int end_di = 0; launch_ctxt_t ctxt; @@ -388,23 +421,23 @@ int hos_launch(ini_sec_t *cfg) gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_con_setpos(&gfx_con, 0, 0); - //Try to parse config if present. + // Try to parse config if present. if (cfg && !_config(&ctxt, cfg)) return 0; gfx_printf(&gfx_con, "Initializing...\n\n"); - //Read package1 and the correct keyblob. + // Read package1 and the correct keyblob. if (!_read_emmc_pkg1(&ctxt)) return 0; gfx_printf(&gfx_con, "Loaded package1 and keyblob\n"); - //Generate keys. + // Generate keys. keygen(ctxt.keyblob, ctxt.pkg1_id->kb, (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off); DPRINTF("Generated keys\n"); - //Decrypt and unpack package1 if we require parts of it. + // Decrypt and unpack package1 if we require parts of it. if (!ctxt.warmboot || !ctxt.secmon) { pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1); @@ -412,19 +445,19 @@ int hos_launch(ini_sec_t *cfg) gfx_printf(&gfx_con, "Decrypted and unpacked package1\n"); } - //Replace 'warmboot.bin' if requested. + // Replace 'warmboot.bin' if requested. if (ctxt.warmboot) memcpy((void *)ctxt.pkg1_id->warmboot_base, ctxt.warmboot, ctxt.warmboot_size); - //Set warmboot address in PMC if required. + // Set warmboot address in PMC if required. if (ctxt.pkg1_id->set_warmboot) PMC(APBDEV_PMC_SCRATCH1) = ctxt.pkg1_id->warmboot_base; - //Replace 'SecureMonitor' if requested. + // Replace 'SecureMonitor' if requested. if (ctxt.secmon) memcpy((void *)ctxt.pkg1_id->secmon_base, ctxt.secmon, ctxt.secmon_size); else { - //Else we patch it to allow for an unsigned package2 and patched kernel. + // Else we patch it to allow for an unsigned package2 and patched kernel. patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset; gfx_printf(&gfx_con, "%kPatching Security Monitor%k\n", 0xFFFFBA00, 0xFFCCCCCC); for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++) @@ -433,13 +466,13 @@ int hos_launch(ini_sec_t *cfg) gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n"); - //Read package2. + // Read package2. if (!_read_emmc_pkg2(&ctxt)) return 0; gfx_printf(&gfx_con, "Read package2\n"); - //Decrypt package2 and parse KIP1 blobs in INI1 section. + // Decrypt package2 and parse KIP1 blobs in INI1 section. pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2); LIST_INIT(kip1_info); @@ -447,41 +480,50 @@ int hos_launch(ini_sec_t *cfg) gfx_printf(&gfx_con, "Parsed ini1\n"); - //Use the kernel included in package2 in case we didn't load one already. + // Use the kernel included in package2 in case we didn't load one already. if (!ctxt.kernel) { ctxt.kernel = pkg2_hdr->data; ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL]; - if (ctxt.svcperm || ctxt.debugmode) + if (ctxt.svcperm || ctxt.debugmode || ctxt.atmosphere) { u32 kernel_crc32 = crc32c(ctxt.kernel, ctxt.kernel_size); ctxt.pkg2_kernel_id = pkg2_identify(kernel_crc32); - //In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode. - patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset; + // In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode. + kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset; if (kernel_patchset != NULL) { gfx_printf(&gfx_con, "%kPatching kernel%k\n", 0xFFFFBA00, 0xFFCCCCCC); - //TODO: this is a bit ugly, perhaps attach a 'key' to the patchset and pass it via ini. - 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; + u32 *temp; + for (u32 i = 0; kernel_patchset[i].id != 0xFFFFFFFF; i++) + { + if ((ctxt.svcperm && kernel_patchset[i].id == SVC_VERIFY_DS) + || (ctxt.debugmode && kernel_patchset[i].id == DEBUG_MODE_EN) + || (ctxt.atmosphere && kernel_patchset[i].id == ATM_GEN_PATCH)) + *(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val; + else if (ctxt.atmosphere && kernel_patchset[i].id == ATM_ARR_PATCH) + { + temp = (u32 *)kernel_patchset[i].ptr; + for (u32 j = 0; j < kernel_patchset[i].val; j++) + *(vu32 *)(ctxt.kernel + kernel_patchset[i].off + (j << 2)) = temp[j]; + } + } } } } - //Merge extra KIP1s into loaded ones. + // Merge extra KIP1s into loaded ones. gfx_printf(&gfx_con, "%kPatching kernel initial processes%k\n", 0xFFFFBA00, 0xFFCCCCCC); LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link) pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1); - //Rebuild and encrypt package2. + // Rebuild and encrypt package2. pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info); gfx_printf(&gfx_con, "Rebuilt and loaded package2\n"); - //Unmount SD card. + // Unmount SD card. sd_unmount(); gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF96FF00, 0xFFCCCCCC); @@ -489,9 +531,17 @@ int hos_launch(ini_sec_t *cfg) se_aes_key_clear(8); se_aes_key_clear(11); + // Final per firmware configuration. switch (ctxt.pkg1_id->kb) { case KB_FIRMWARE_VERSION_100_200: + if (!exoFwNumber) + { + if(!strcmp(ctxt.pkg1_id->id, "20161121183008")) + exoFwNumber = 1; + else + exoFwNumber = 2; + } case KB_FIRMWARE_VERSION_300: case KB_FIRMWARE_VERSION_301: se_key_acc_ctrl(12, 0xFF); @@ -499,21 +549,39 @@ int hos_launch(ini_sec_t *cfg) bootStateDramPkg2 = 2; bootStatePkg2Continue = 3; end_di = 1; + if (!exoFwNumber) + exoFwNumber = 3; break; default: case KB_FIRMWARE_VERSION_400: + if (!exoFwNumber) + exoFwNumber = 4; case KB_FIRMWARE_VERSION_500: se_key_acc_ctrl(12, 0xFF); se_key_acc_ctrl(15, 0xFF); bootStateDramPkg2 = 2; bootStatePkg2Continue = 4; + if (!exoFwNumber) + exoFwNumber = 5; break; } - //TODO: Don't Clear 'BootConfig' for retail >1.0.0. + // Copy BCT if debug mode is enabled. memset((void *)0x4003D000, 0, 0x3000); + if(ctxt.debugmode) + _copy_bootconfig(&ctxt); - //Lock SE before starting 'SecureMonitor'. + // Config Exosphere if booting Atmosphere. + if (ctxt.atmosphere) + { + vu32 *mb_exo_magic = (vu32 *)0x40002E40; + vu32 *mb_exo_fw_no = (vu32 *)0x40002E44; + + *mb_exo_magic = MAGIC_EXOSPHERE; + *mb_exo_fw_no = exoFwNumber; + } + + // Lock SE before starting 'SecureMonitor'. _se_lock(); //< 4.0.0 Signals. 0: Nothing ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot diff --git a/ipl/link.ld b/ipl/link.ld index 695cba7..2d7956d 100755 --- a/ipl/link.ld +++ b/ipl/link.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - PROVIDE(__ipl_start = 0x40003000); + PROVIDE(__ipl_start = 0x40008000); . = __ipl_start; .text : { *(.text*); diff --git a/ipl/main.c b/ipl/main.c index 178badc..7269e55 100755 --- a/ipl/main.c +++ b/ipl/main.c @@ -1804,7 +1804,7 @@ void about() " Copyright (C) 2018, ChaN\n\n" " - bcl-1.2.0,\n" " Copyright (C) 2003-2006, Marcus Geelnard\n\n" - " - Atmosphere (se_calculate_sha256),\n" + " - Atmosphere (SE sha256, prc id patches),\n" " Copyright (C) 2018, Atmosphere-NX\n" " ___________________________________________\n\n"; static const char octopus[] = diff --git a/ipl/pkg1.h b/ipl/pkg1.h index a1ef5b0..487a5ec 100755 --- a/ipl/pkg1.h +++ b/ipl/pkg1.h @@ -19,6 +19,12 @@ #include "types.h" +typedef struct _patch_t +{ + u32 off; + u32 val; +} patch_t; + #define PATCHSET_DEF(name, ...) \ patch_t name[] = { \ __VA_ARGS__, \ diff --git a/ipl/pkg2.c b/ipl/pkg2.c index 217b94d..4dec099 100755 --- a/ipl/pkg2.c +++ b/ipl/pkg2.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (C) 2018 CTCaer +* Copyright (c) 2018 CTCaer +* 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, @@ -27,45 +28,197 @@ extern gfx_con_t gfx_con; #define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/ #define DPRINTF(...) +//TODO: Replace hardcoded AArch64 instructions with instruction macros. +//TODO: Reduce hardcoded values without searching kernel for patterns? +// The process ID send/receive kernel patches were taken from Atmosphère's kernel patches. +// They should only be used when running Atmosphère. +#define FREE_CODE_OFF_1ST_100 0x4797C +#define FREE_CODE_OFF_1ST_200 0x6486C +#define FREE_CODE_OFF_1ST_300 0x494A4 +#define FREE_CODE_OFF_1ST_302 0x494BC +#define FREE_CODE_OFF_1ST_400 0x4FBC0 +#define FREE_CODE_OFF_1ST_500 0x5C020 + +#define ID_SND_OFF_100 0x23CC0 +#define ID_SND_OFF_200 0x3F134 +#define ID_SND_OFF_300 0x26080 +#define ID_SND_OFF_302 0x26080 +#define ID_SND_OFF_400 0x2AF64 +#define ID_SND_OFF_500 0x2AD34 + +#define ID_RCV_OFF_100 0x219F0 +#define ID_RCV_OFF_200 0x3D1A8 +#define ID_RCV_OFF_300 0x240F0 +#define ID_RCV_OFF_302 0x240F0 +#define ID_RCV_OFF_400 0x28F6C +#define ID_RCV_OFF_500 0x28DAC + +static u32 PRC_ID_SND_100[] = +{ + 0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA +}; +#define FREE_CODE_OFF_2ND_100 (FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100) + 4) +static u32 PRC_ID_RCV_100[] = +{ + 0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, + 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA +}; + +static u32 PRC_ID_SND_200[] = +{ + 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA +}; +#define FREE_CODE_OFF_2ND_200 (FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200) + 4) +static u32 PRC_ID_RCV_200[] = +{ + 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, + 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA +}; + +static u32 PRC_ID_SND_300[] = +{ + 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA +}; +#define FREE_CODE_OFF_2ND_300 (FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300) + 4) +static u32 PRC_ID_RCV_300[] = +{ + 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, + 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA +}; + +static u32 PRC_ID_SND_302[] = +{ + 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA +}; +#define FREE_CODE_OFF_2ND_302 (FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302) + 4) +static u32 PRC_ID_RCV_302[] = +{ + 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, + 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA +}; + +static u32 PRC_ID_SND_400[] = +{ + 0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, + 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F +}; +#define FREE_CODE_OFF_2ND_400 (FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400) + 4) +static u32 PRC_ID_RCV_400[] = +{ + 0xD280000D, 0x2A0E03ED, 0xD37EF5AD, 0xF86D6B4D, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A0901AD, + 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F +}; + +static u32 PRC_ID_SND_500[] = +{ + 0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, + 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA +}; +#define FREE_CODE_OFF_2ND_500 (FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500) + 4) +static u32 PRC_ID_RCV_500[] = +{ + 0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, + 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA +}; + // 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 +KERNEL_PATCHSET_DEF(_kernel_1_patchset, + { SVC_VERIFY_DS, 0x3764C, _NOP(), NULL }, // Disable SVC verifications + { DEBUG_MODE_EN, 0x44074, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch + // Atmosphère kernel patches. + { ATM_GEN_PATCH, ID_SND_OFF_100, _B(ID_SND_OFF_100, FREE_CODE_OFF_1ST_100), NULL}, // Send process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_100, sizeof(PRC_ID_SND_100) >> 2, PRC_ID_SND_100}, // Send process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), ID_SND_OFF_100 + 4), NULL}, + { ATM_GEN_PATCH, ID_RCV_OFF_100, _B(ID_RCV_OFF_100, FREE_CODE_OFF_2ND_100), NULL}, // Receive process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_100, sizeof(PRC_ID_RCV_100) >> 2, PRC_ID_RCV_100}, // Receive process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), ID_RCV_OFF_100 + 4), NULL} ); -PATCHSET_DEF(_kernel_2_patchset, - { 0x54834, _NOP() }, // Disable SVC verifications - { 0x6086C, _MOVZX(8, 1, 0) } // Enable Debug Patch +KERNEL_PATCHSET_DEF(_kernel_2_patchset, + { SVC_VERIFY_DS, 0x54834, _NOP(), NULL }, // Disable SVC verifications + { DEBUG_MODE_EN, 0x6086C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch + // Atmosphère kernel patches. + { ATM_GEN_PATCH, ID_SND_OFF_200, _B(ID_SND_OFF_200, FREE_CODE_OFF_1ST_200), NULL}, // Send process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_200, sizeof(PRC_ID_SND_200) >> 2, PRC_ID_SND_200}, // Send process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), ID_SND_OFF_200 + 4), NULL}, + { ATM_GEN_PATCH, ID_RCV_OFF_200, _B(ID_RCV_OFF_200, FREE_CODE_OFF_2ND_200), NULL}, // Receive process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_200, sizeof(PRC_ID_RCV_200) >> 2, PRC_ID_RCV_200}, // Receive process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), ID_RCV_OFF_200 + 4), NULL} ); -PATCHSET_DEF(_kernel_3_patchset, - { 0x3BD24, _NOP() }, // Disable SVC verifications - { 0x483FC, _MOVZX(8, 1, 0) } // Enable Debug Patch +KERNEL_PATCHSET_DEF(_kernel_3_patchset, + { SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications + { DEBUG_MODE_EN, 0x483FC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch + // Atmosphère kernel patches. + { ATM_GEN_PATCH, ID_SND_OFF_300, _B(ID_SND_OFF_300, FREE_CODE_OFF_1ST_300), NULL}, // Send process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_300, sizeof(PRC_ID_SND_300) >> 2, PRC_ID_SND_300}, // Send process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), ID_SND_OFF_300 + 4), NULL}, + { ATM_GEN_PATCH, ID_RCV_OFF_300, _B(ID_RCV_OFF_300, FREE_CODE_OFF_2ND_300), NULL}, // Receive process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_300, sizeof(PRC_ID_RCV_300) >> 2, PRC_ID_RCV_300}, // Receive process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), ID_RCV_OFF_300 + 4), NULL} ); -PATCHSET_DEF(_kernel_302_patchset, - { 0x3BD24, _NOP() }, // Disable SVC verifications - { 0x48414, _MOVZX(8, 1, 0) } // Enable Debug Patch +KERNEL_PATCHSET_DEF(_kernel_302_patchset, + { SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications + { DEBUG_MODE_EN, 0x48414, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch + // Atmosphère kernel patches. + { ATM_GEN_PATCH, ID_SND_OFF_302, _B(ID_SND_OFF_302, FREE_CODE_OFF_1ST_302), NULL}, // Send process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_302, sizeof(PRC_ID_SND_302) >> 2, PRC_ID_SND_302}, // Send process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302), ID_SND_OFF_302 + 4), NULL}, + { ATM_GEN_PATCH, ID_RCV_OFF_302, _B(ID_RCV_OFF_302, FREE_CODE_OFF_2ND_302), NULL}, // Receive process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_302, sizeof(PRC_ID_RCV_302) >> 2, PRC_ID_RCV_302}, // Receive process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_302), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_302), ID_RCV_OFF_302 + 4), NULL} ); -PATCHSET_DEF(_kernel_4_patchset, - { 0x41EB4, _NOP() }, // Disable SVC verifications - { 0x4EBFC, _MOVZX(8, 1, 0) } // Enable Debug Patch +KERNEL_PATCHSET_DEF(_kernel_4_patchset, + { SVC_VERIFY_DS, 0x41EB4, _NOP(), NULL }, // Disable SVC verifications + { DEBUG_MODE_EN, 0x4EBFC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch + // Atmosphère kernel patches. + { ATM_GEN_PATCH, ID_SND_OFF_400, _B(ID_SND_OFF_400, FREE_CODE_OFF_1ST_400), NULL}, // Send process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_400, sizeof(PRC_ID_SND_400) >> 2, PRC_ID_SND_400}, // Send process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), // Branch back and skip 2 instructions. + _B(FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), ID_SND_OFF_400 + 8), NULL}, + { ATM_GEN_PATCH, ID_RCV_OFF_400, _B(ID_RCV_OFF_400, FREE_CODE_OFF_2ND_400), NULL}, // Receive process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_400, sizeof(PRC_ID_RCV_400) >> 2, PRC_ID_RCV_400}, // Receive process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), // Branch back and skip 1 instruction. + _B(FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), ID_RCV_OFF_400 + 4), NULL} ); -PATCHSET_DEF(_kernel_5_patchset, - { 0x45E6C, _NOP() }, // Disable SVC verifications - { 0x5513C, _MOVZX(8, 1, 0) } // Enable Debug Patch +KERNEL_PATCHSET_DEF(_kernel_5_patchset, + { SVC_VERIFY_DS, 0x45E6C, _NOP(), NULL }, // Disable SVC verifications + { DEBUG_MODE_EN, 0x5513C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch + // Atmosphère kernel patches. + { ATM_GEN_PATCH, ID_SND_OFF_500, _B(ID_SND_OFF_500, FREE_CODE_OFF_1ST_500), NULL}, // Send process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_500, sizeof(PRC_ID_SND_500) >> 2, PRC_ID_SND_500}, // Send process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), // Branch back and skip 2 instructions. + _B(FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), ID_SND_OFF_500 + 8), NULL}, + { ATM_GEN_PATCH, ID_RCV_OFF_500, _B(ID_RCV_OFF_500, FREE_CODE_OFF_2ND_500), NULL}, // Receive process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_500, sizeof(PRC_ID_RCV_500) >> 2, PRC_ID_RCV_500}, // Receive process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), // Branch back and skip 2 instructions. + _B(FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), ID_RCV_OFF_500 + 8), NULL} ); -static const pkg2_kernel_id_t _pkg2_kernel_ids[] = { +static const pkg2_kernel_id_t _pkg2_kernel_ids[] = +{ { 0x427f2647, _kernel_1_patchset }, //1.0.0 { 0xae19cf1b, _kernel_2_patchset }, //2.0.0 - 2.3.0 { 0x73c9e274, _kernel_3_patchset }, //3.0.0 - 3.0.1 { 0xe0e8cdc4, _kernel_302_patchset }, //3.0.2 { 0x485d0157, _kernel_4_patchset }, //4.0.0 - 4.1.0 { 0xf3c363f2, _kernel_5_patchset }, //5.0.0 - 5.1.0 - { 0, 0 } //End. + { 0, 0 } //End. }; const pkg2_kernel_id_t *pkg2_identify(u32 id) diff --git a/ipl/pkg2.h b/ipl/pkg2.h index ec25ac5..16cb57c 100755 --- a/ipl/pkg2.h +++ b/ipl/pkg2.h @@ -28,12 +28,30 @@ #define INI1_MAGIC 0x31494E49 -#define PATCHSET_DEF(name, ...) \ - patch_t name[] = { \ +typedef struct _kernel_patch_t +{ + u32 id; + u32 off; + u32 val; + u32 *ptr; +} kernel_patch_t; + +#define KERNEL_PATCHSET_DEF(name, ...) \ + kernel_patch_t name[] = { \ __VA_ARGS__, \ - { 0xFFFFFFFF, 0xFFFFFFFF } \ + {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32 *)0xFFFFFFFF} \ } +enum +{ + // Generic instruction patches + SVC_VERIFY_DS = 0x10, // 0x0-0xF are RESERVED. + DEBUG_MODE_EN, + ATM_GEN_PATCH, + // >4 bytes patches. Value is a pointer of a u32 array. + ATM_ARR_PATCH, +}; + typedef struct _pkg2_hdr_t { u8 ctr[0x10]; @@ -92,7 +110,7 @@ typedef struct _pkg2_kip1_info_t typedef struct _pkg2_kernel_id_t { u32 crc32c_id; - patch_t *kernel_patchset; + kernel_patch_t *kernel_patchset; } pkg2_kernel_id_t; void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2); diff --git a/ipl/types.h b/ipl/types.h index 5aa59e9..0ae3ce8 100755 --- a/ipl/types.h +++ b/ipl/types.h @@ -38,10 +38,4 @@ typedef volatile unsigned char vu8; typedef volatile unsigned short vu16; typedef volatile unsigned int vu32; -typedef struct _patch_t -{ - u32 off; - u32 val; -} patch_t; - #endif