diff --git a/ipl/hos.c b/ipl/hos.c index dbbfd92..fb83617 100755 --- a/ipl/hos.c +++ b/ipl/hos.c @@ -74,6 +74,21 @@ static const u8 master_keyseed_4xx[0x10] = static const u8 console_keyseed_4xx[0x10] = { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 }; +#define CRC32C_POLY 0x82f63b78 + +u32 crc32c(const u8 *buf, u32 len) +{ + int i; + u32 crc = 0; + + crc = ~crc; + while (len--) { + crc ^= *buf++; + for (i = 0; i < 8; i++) + crc = crc & 1 ? (crc >> 1) ^ CRC32C_POLY : crc >> 1; + } + return ~crc; +} static void _se_lock() { @@ -178,6 +193,7 @@ typedef struct _launch_ctxt_t void *pkg1; const pkg1_id_t *pkg1_id; + const pkg2_kernel_id_t *pkg2_kernel_id; void *warmboot; u32 warmboot_size; @@ -413,18 +429,14 @@ int hos_launch(ini_sec_t *cfg) } else { - //Else we patch it to allow for an unsigned package2. + //Else we patch it to allow for an unsigned package2 and patched kernel. 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 || (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; - } + + 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; gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n"); @@ -447,13 +459,22 @@ 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)) + if (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; + u32 kernel_crc32 = crc32c((u8 *)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 Verififcation or/and enable Debug mode + patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset; + + if (kernel_patchset != NULL) + { + 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; + } } } diff --git a/ipl/main.c b/ipl/main.c index 74bde69..82ac234 100755 --- a/ipl/main.c +++ b/ipl/main.c @@ -792,7 +792,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part) if (!maxSplitParts) { - EPRINTF("Not enough free space for partial dumping."); + EPRINTF("Not enough free space for Partial Backup."); return 0; } diff --git a/ipl/pkg1.c b/ipl/pkg1.c index 7842ba4..e7da955 100755 --- a/ipl/pkg1.c +++ b/ipl/pkg1.c @@ -68,32 +68,6 @@ PATCHSET_DEF(_secmon_5_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, - { 0x45E6C, _NOP() }, // Disable SVC verifications - { 0x5513C, _MOVZX(8, 1, 0) } // Enable Debug Patch -); - /* * package1.1 header: * package1.1 layout: @@ -106,12 +80,12 @@ PATCHSET_DEF(_kernel_5_patchset, */ static const pkg1_id_t _pkg1_ids[] = { - { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, 1, _secmon_1_patchset, _kernel_1_patchset }, //1.0.0 (Patched relocator) - { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_2_patchset, _kernel_2_patchset }, //2.0.0 - 2.3.0 - { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset, _kernel_3_patchset }, //3.0.0 - { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset, _kernel_3_patchset }, //3.0.1 - 3.0.2 - { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0, _secmon_4_patchset, _kernel_4_patchset }, //4.0.0 - 4.1.0 - { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0, _secmon_5_patchset, _kernel_5_patchset }, //5.0.0 - 5.0.2 + { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, 1, _secmon_1_patchset }, //1.0.0 (Patched relocator) + { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_2_patchset }, //2.0.0 - 2.3.0 + { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset }, //3.0.0 + { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset }, //3.0.1 - 3.0.2 + { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0, _secmon_4_patchset }, //4.0.0 - 4.1.0 + { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0, _secmon_5_patchset }, //5.0.0 - 5.1.0 { NULL, 0, 0, 0, 0 } //End. }; diff --git a/ipl/pkg1.h b/ipl/pkg1.h index 5936273..a1ef5b0 100755 --- a/ipl/pkg1.h +++ b/ipl/pkg1.h @@ -25,12 +25,6 @@ { 0xFFFFFFFF, 0xFFFFFFFF } \ } -typedef struct _patch_t -{ - u32 off; - u32 val; -} patch_t; - typedef struct _pkg1_id_t { const char *id; @@ -42,7 +36,6 @@ typedef struct _pkg1_id_t u32 warmboot_base; int set_warmboot; patch_t *secmon_patchset; - patch_t *kernel_patchset; } pkg1_id_t; typedef struct _pk11_hdr_t diff --git a/ipl/pkg2.c b/ipl/pkg2.c index 4cf6e9f..cd66c94 100755 --- a/ipl/pkg2.c +++ b/ipl/pkg2.c @@ -25,6 +25,58 @@ extern gfx_con_t gfx_con; #define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/ #define DPRINTF(...) +#define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) +#define _NOP() 0xD503201F + +// 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_302_patchset, + { 0x3BD24, _NOP() }, // Disable SVC verifications + { 0x48414, _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, + { 0x45E6C, _NOP() }, // Disable SVC verifications + { 0x5513C, _MOVZX(8, 1, 0) } // Enable Debug Patch +); + +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. +}; + +const pkg2_kernel_id_t *pkg2_identify(u32 id) +{ + for (u32 i = 0; _pkg2_kernel_ids[i].crc32c_id; i++) + if (id == _pkg2_kernel_ids[i].crc32c_id) + return &_pkg2_kernel_ids[i]; + return NULL; +} + static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1) { u32 size = sizeof(pkg2_kip1_t); diff --git a/ipl/pkg2.h b/ipl/pkg2.h index b9a10db..5adfd24 100755 --- a/ipl/pkg2.h +++ b/ipl/pkg2.h @@ -27,6 +27,12 @@ #define INI1_MAGIC 0x31494E49 +#define PATCHSET_DEF(name, ...) \ + patch_t name[] = { \ + __VA_ARGS__, \ + { 0xFFFFFFFF, 0xFFFFFFFF } \ + } + typedef struct _pkg2_hdr_t { u8 ctr[0x10]; @@ -82,12 +88,19 @@ typedef struct _pkg2_kip1_info_t link_t link; } pkg2_kip1_info_t; +typedef struct _pkg2_kernel_id_t +{ + u32 crc32c_id; + patch_t *kernel_patchset; +} pkg2_kernel_id_t; + void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2); int pkg2_has_kip(link_t *info, u64 tid); void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1); void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1); void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1); +const pkg2_kernel_id_t *pkg2_identify(u32 id); pkg2_hdr_t *pkg2_decrypt(void *data); void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info); diff --git a/ipl/types.h b/ipl/types.h index 56dd81e..5b8a059 100755 --- a/ipl/types.h +++ b/ipl/types.h @@ -34,4 +34,10 @@ 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