[PKG2] Switch kernel patching to crc32c based kernel id

This provides support for the 3.0.2 kernel, where pkg1 has the same id with 3.0.1.

Thanks @roblabla for noticing and providing the Debug mode kernel patch.
This commit is contained in:
Kostas Missos 2018-06-05 02:04:08 +03:00
parent fb9e91ed0c
commit b299cb40c7
7 changed files with 116 additions and 57 deletions

View file

@ -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;
}
gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n");
@ -447,7 +459,15 @@ 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)
{
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)
@ -456,6 +476,7 @@ int hos_launch(ini_sec_t *cfg)
*(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);

View file

@ -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;
}

View file

@ -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: <wb, ldr, sm>
* 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.
};

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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