mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
Preliminary Exosphère support
This commit is contained in:
parent
d9dba2b182
commit
ffeb8c60df
9 changed files with 300 additions and 61 deletions
|
@ -33,7 +33,7 @@ Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
||||||
Open source and free packages used:
|
Open source and free packages used:
|
||||||
- FatFs R0.13a, Copyright (C) 2017, ChaN
|
- FatFs R0.13a, Copyright (C) 2017, ChaN
|
||||||
- bcl-1.2.0, Copyright (C) 2003-2006, Marcus Geelnard
|
- 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
|
||||||
|
|
||||||
___
|
___
|
||||||
.-' `'.
|
.-' `'.
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#define _ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F)
|
#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 _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 _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 _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F)
|
||||||
#define _NOP() 0xD503201F
|
#define _NOP() 0xD503201F
|
||||||
|
|
120
ipl/hos.c
120
ipl/hos.c
|
@ -65,6 +65,7 @@ typedef struct _launch_ctxt_t
|
||||||
|
|
||||||
int svcperm;
|
int svcperm;
|
||||||
int debugmode;
|
int debugmode;
|
||||||
|
int atmosphere;
|
||||||
} launch_ctxt_t;
|
} launch_ctxt_t;
|
||||||
|
|
||||||
typedef struct _merge_kip_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_500 4
|
||||||
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_500
|
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_500
|
||||||
|
|
||||||
|
// Exosphere magic "XBC0"
|
||||||
|
#define MAGIC_EXOSPHERE 0x30434258
|
||||||
|
|
||||||
static const u8 keyblob_keyseeds[][0x10] = {
|
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
|
{ 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
|
{ 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;
|
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)
|
static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
@ -348,6 +369,16 @@ static int _config_debugmode(launch_ctxt_t *ctxt, const char *value)
|
||||||
return 1;
|
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
|
typedef struct _cfg_handler_t
|
||||||
{
|
{
|
||||||
const char *key;
|
const char *key;
|
||||||
|
@ -361,6 +392,7 @@ static const cfg_handler_t _config_handlers[] = {
|
||||||
{ "kip1", _config_kip1 },
|
{ "kip1", _config_kip1 },
|
||||||
{ "fullsvcperm", _config_svcperm },
|
{ "fullsvcperm", _config_svcperm },
|
||||||
{ "debugmode", _config_debugmode },
|
{ "debugmode", _config_debugmode },
|
||||||
|
{ "atmosphere", _config_atmosphere },
|
||||||
{ NULL, NULL },
|
{ 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 hos_launch(ini_sec_t *cfg)
|
||||||
{
|
{
|
||||||
int bootStateDramPkg2;
|
int bootStateDramPkg2 = 0;
|
||||||
int bootStatePkg2Continue;
|
int bootStatePkg2Continue = 0;
|
||||||
|
int exoFwNumber = 0;
|
||||||
int end_di = 0;
|
int end_di = 0;
|
||||||
launch_ctxt_t ctxt;
|
launch_ctxt_t ctxt;
|
||||||
|
|
||||||
|
@ -388,23 +421,23 @@ int hos_launch(ini_sec_t *cfg)
|
||||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||||
gfx_con_setpos(&gfx_con, 0, 0);
|
gfx_con_setpos(&gfx_con, 0, 0);
|
||||||
|
|
||||||
//Try to parse config if present.
|
// Try to parse config if present.
|
||||||
if (cfg && !_config(&ctxt, cfg))
|
if (cfg && !_config(&ctxt, cfg))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gfx_printf(&gfx_con, "Initializing...\n\n");
|
gfx_printf(&gfx_con, "Initializing...\n\n");
|
||||||
|
|
||||||
//Read package1 and the correct keyblob.
|
// Read package1 and the correct keyblob.
|
||||||
if (!_read_emmc_pkg1(&ctxt))
|
if (!_read_emmc_pkg1(&ctxt))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gfx_printf(&gfx_con, "Loaded package1 and keyblob\n");
|
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);
|
keygen(ctxt.keyblob, ctxt.pkg1_id->kb, (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off);
|
||||||
DPRINTF("Generated keys\n");
|
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)
|
if (!ctxt.warmboot || !ctxt.secmon)
|
||||||
{
|
{
|
||||||
pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1);
|
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");
|
gfx_printf(&gfx_con, "Decrypted and unpacked package1\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Replace 'warmboot.bin' if requested.
|
// Replace 'warmboot.bin' if requested.
|
||||||
if (ctxt.warmboot)
|
if (ctxt.warmboot)
|
||||||
memcpy((void *)ctxt.pkg1_id->warmboot_base, ctxt.warmboot, ctxt.warmboot_size);
|
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)
|
if (ctxt.pkg1_id->set_warmboot)
|
||||||
PMC(APBDEV_PMC_SCRATCH1) = ctxt.pkg1_id->warmboot_base;
|
PMC(APBDEV_PMC_SCRATCH1) = ctxt.pkg1_id->warmboot_base;
|
||||||
|
|
||||||
//Replace 'SecureMonitor' if requested.
|
// Replace 'SecureMonitor' if requested.
|
||||||
if (ctxt.secmon)
|
if (ctxt.secmon)
|
||||||
memcpy((void *)ctxt.pkg1_id->secmon_base, ctxt.secmon, ctxt.secmon_size);
|
memcpy((void *)ctxt.pkg1_id->secmon_base, ctxt.secmon, ctxt.secmon_size);
|
||||||
else
|
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;
|
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
|
||||||
gfx_printf(&gfx_con, "%kPatching Security Monitor%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
gfx_printf(&gfx_con, "%kPatching Security Monitor%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||||
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
|
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");
|
gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n");
|
||||||
|
|
||||||
//Read package2.
|
// Read package2.
|
||||||
if (!_read_emmc_pkg2(&ctxt))
|
if (!_read_emmc_pkg2(&ctxt))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gfx_printf(&gfx_con, "Read package2\n");
|
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);
|
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
|
||||||
|
|
||||||
LIST_INIT(kip1_info);
|
LIST_INIT(kip1_info);
|
||||||
|
@ -447,41 +480,50 @@ int hos_launch(ini_sec_t *cfg)
|
||||||
|
|
||||||
gfx_printf(&gfx_con, "Parsed ini1\n");
|
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)
|
if (!ctxt.kernel)
|
||||||
{
|
{
|
||||||
ctxt.kernel = pkg2_hdr->data;
|
ctxt.kernel = pkg2_hdr->data;
|
||||||
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
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);
|
u32 kernel_crc32 = crc32c(ctxt.kernel, ctxt.kernel_size);
|
||||||
ctxt.pkg2_kernel_id = pkg2_identify(kernel_crc32);
|
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.
|
// 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;
|
kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset;
|
||||||
if (kernel_patchset != NULL)
|
if (kernel_patchset != NULL)
|
||||||
{
|
{
|
||||||
gfx_printf(&gfx_con, "%kPatching kernel%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
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.
|
u32 *temp;
|
||||||
if (ctxt.svcperm && kernel_patchset[0].off != 0xFFFFFFFF)
|
for (u32 i = 0; kernel_patchset[i].id != 0xFFFFFFFF; i++)
|
||||||
*(vu32 *)(ctxt.kernel + kernel_patchset[0].off) = kernel_patchset[0].val;
|
{
|
||||||
if (ctxt.debugmode && kernel_patchset[1].off != 0xFFFFFFFF)
|
if ((ctxt.svcperm && kernel_patchset[i].id == SVC_VERIFY_DS)
|
||||||
*(vu32 *)(ctxt.kernel + kernel_patchset[1].off) = kernel_patchset[1].val;
|
|| (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);
|
gfx_printf(&gfx_con, "%kPatching kernel initial processes%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||||
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
||||||
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
|
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);
|
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
|
||||||
gfx_printf(&gfx_con, "Rebuilt and loaded package2\n");
|
gfx_printf(&gfx_con, "Rebuilt and loaded package2\n");
|
||||||
|
|
||||||
//Unmount SD card.
|
// Unmount SD card.
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
|
|
||||||
gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF96FF00, 0xFFCCCCCC);
|
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(8);
|
||||||
se_aes_key_clear(11);
|
se_aes_key_clear(11);
|
||||||
|
|
||||||
|
// Final per firmware configuration.
|
||||||
switch (ctxt.pkg1_id->kb)
|
switch (ctxt.pkg1_id->kb)
|
||||||
{
|
{
|
||||||
case KB_FIRMWARE_VERSION_100_200:
|
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_300:
|
||||||
case KB_FIRMWARE_VERSION_301:
|
case KB_FIRMWARE_VERSION_301:
|
||||||
se_key_acc_ctrl(12, 0xFF);
|
se_key_acc_ctrl(12, 0xFF);
|
||||||
|
@ -499,21 +549,39 @@ int hos_launch(ini_sec_t *cfg)
|
||||||
bootStateDramPkg2 = 2;
|
bootStateDramPkg2 = 2;
|
||||||
bootStatePkg2Continue = 3;
|
bootStatePkg2Continue = 3;
|
||||||
end_di = 1;
|
end_di = 1;
|
||||||
|
if (!exoFwNumber)
|
||||||
|
exoFwNumber = 3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case KB_FIRMWARE_VERSION_400:
|
case KB_FIRMWARE_VERSION_400:
|
||||||
|
if (!exoFwNumber)
|
||||||
|
exoFwNumber = 4;
|
||||||
case KB_FIRMWARE_VERSION_500:
|
case KB_FIRMWARE_VERSION_500:
|
||||||
se_key_acc_ctrl(12, 0xFF);
|
se_key_acc_ctrl(12, 0xFF);
|
||||||
se_key_acc_ctrl(15, 0xFF);
|
se_key_acc_ctrl(15, 0xFF);
|
||||||
bootStateDramPkg2 = 2;
|
bootStateDramPkg2 = 2;
|
||||||
bootStatePkg2Continue = 4;
|
bootStatePkg2Continue = 4;
|
||||||
|
if (!exoFwNumber)
|
||||||
|
exoFwNumber = 5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Don't Clear 'BootConfig' for retail >1.0.0.
|
// Copy BCT if debug mode is enabled.
|
||||||
memset((void *)0x4003D000, 0, 0x3000);
|
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();
|
_se_lock();
|
||||||
|
|
||||||
//< 4.0.0 Signals. 0: Nothing ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot
|
//< 4.0.0 Signals. 0: Nothing ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
PROVIDE(__ipl_start = 0x40003000);
|
PROVIDE(__ipl_start = 0x40008000);
|
||||||
. = __ipl_start;
|
. = __ipl_start;
|
||||||
.text : {
|
.text : {
|
||||||
*(.text*);
|
*(.text*);
|
||||||
|
|
|
@ -1804,7 +1804,7 @@ void about()
|
||||||
" Copyright (C) 2018, ChaN\n\n"
|
" Copyright (C) 2018, ChaN\n\n"
|
||||||
" - bcl-1.2.0,\n"
|
" - bcl-1.2.0,\n"
|
||||||
" Copyright (C) 2003-2006, Marcus Geelnard\n\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"
|
" Copyright (C) 2018, Atmosphere-NX\n"
|
||||||
" ___________________________________________\n\n";
|
" ___________________________________________\n\n";
|
||||||
static const char octopus[] =
|
static const char octopus[] =
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
typedef struct _patch_t
|
||||||
|
{
|
||||||
|
u32 off;
|
||||||
|
u32 val;
|
||||||
|
} patch_t;
|
||||||
|
|
||||||
#define PATCHSET_DEF(name, ...) \
|
#define PATCHSET_DEF(name, ...) \
|
||||||
patch_t name[] = { \
|
patch_t name[] = { \
|
||||||
__VA_ARGS__, \
|
__VA_ARGS__, \
|
||||||
|
|
195
ipl/pkg2.c
195
ipl/pkg2.c
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* 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
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* 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(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
|
||||||
#define DPRINTF(...)
|
#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
|
// Include kernel patches here, so we can utilize pkg1 id
|
||||||
PATCHSET_DEF(_kernel_1_patchset,
|
KERNEL_PATCHSET_DEF(_kernel_1_patchset,
|
||||||
{ 0x3764C, _NOP() }, // Disable SVC verifications
|
{ SVC_VERIFY_DS, 0x3764C, _NOP(), NULL }, // Disable SVC verifications
|
||||||
{ 0x44074, _MOVZX(8, 1, 0) } // Enable Debug Patch
|
{ 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,
|
KERNEL_PATCHSET_DEF(_kernel_2_patchset,
|
||||||
{ 0x54834, _NOP() }, // Disable SVC verifications
|
{ SVC_VERIFY_DS, 0x54834, _NOP(), NULL }, // Disable SVC verifications
|
||||||
{ 0x6086C, _MOVZX(8, 1, 0) } // Enable Debug Patch
|
{ 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,
|
KERNEL_PATCHSET_DEF(_kernel_3_patchset,
|
||||||
{ 0x3BD24, _NOP() }, // Disable SVC verifications
|
{ SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications
|
||||||
{ 0x483FC, _MOVZX(8, 1, 0) } // Enable Debug Patch
|
{ 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,
|
KERNEL_PATCHSET_DEF(_kernel_302_patchset,
|
||||||
{ 0x3BD24, _NOP() }, // Disable SVC verifications
|
{ SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications
|
||||||
{ 0x48414, _MOVZX(8, 1, 0) } // Enable Debug Patch
|
{ 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,
|
KERNEL_PATCHSET_DEF(_kernel_4_patchset,
|
||||||
{ 0x41EB4, _NOP() }, // Disable SVC verifications
|
{ SVC_VERIFY_DS, 0x41EB4, _NOP(), NULL }, // Disable SVC verifications
|
||||||
{ 0x4EBFC, _MOVZX(8, 1, 0) } // Enable Debug Patch
|
{ 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,
|
KERNEL_PATCHSET_DEF(_kernel_5_patchset,
|
||||||
{ 0x45E6C, _NOP() }, // Disable SVC verifications
|
{ SVC_VERIFY_DS, 0x45E6C, _NOP(), NULL }, // Disable SVC verifications
|
||||||
{ 0x5513C, _MOVZX(8, 1, 0) } // Enable Debug Patch
|
{ 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
|
{ 0x427f2647, _kernel_1_patchset }, //1.0.0
|
||||||
{ 0xae19cf1b, _kernel_2_patchset }, //2.0.0 - 2.3.0
|
{ 0xae19cf1b, _kernel_2_patchset }, //2.0.0 - 2.3.0
|
||||||
{ 0x73c9e274, _kernel_3_patchset }, //3.0.0 - 3.0.1
|
{ 0x73c9e274, _kernel_3_patchset }, //3.0.0 - 3.0.1
|
||||||
{ 0xe0e8cdc4, _kernel_302_patchset }, //3.0.2
|
{ 0xe0e8cdc4, _kernel_302_patchset }, //3.0.2
|
||||||
{ 0x485d0157, _kernel_4_patchset }, //4.0.0 - 4.1.0
|
{ 0x485d0157, _kernel_4_patchset }, //4.0.0 - 4.1.0
|
||||||
{ 0xf3c363f2, _kernel_5_patchset }, //5.0.0 - 5.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)
|
const pkg2_kernel_id_t *pkg2_identify(u32 id)
|
||||||
|
|
26
ipl/pkg2.h
26
ipl/pkg2.h
|
@ -28,12 +28,30 @@
|
||||||
|
|
||||||
#define INI1_MAGIC 0x31494E49
|
#define INI1_MAGIC 0x31494E49
|
||||||
|
|
||||||
#define PATCHSET_DEF(name, ...) \
|
typedef struct _kernel_patch_t
|
||||||
patch_t name[] = { \
|
{
|
||||||
|
u32 id;
|
||||||
|
u32 off;
|
||||||
|
u32 val;
|
||||||
|
u32 *ptr;
|
||||||
|
} kernel_patch_t;
|
||||||
|
|
||||||
|
#define KERNEL_PATCHSET_DEF(name, ...) \
|
||||||
|
kernel_patch_t name[] = { \
|
||||||
__VA_ARGS__, \
|
__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
|
typedef struct _pkg2_hdr_t
|
||||||
{
|
{
|
||||||
u8 ctr[0x10];
|
u8 ctr[0x10];
|
||||||
|
@ -92,7 +110,7 @@ typedef struct _pkg2_kip1_info_t
|
||||||
typedef struct _pkg2_kernel_id_t
|
typedef struct _pkg2_kernel_id_t
|
||||||
{
|
{
|
||||||
u32 crc32c_id;
|
u32 crc32c_id;
|
||||||
patch_t *kernel_patchset;
|
kernel_patch_t *kernel_patchset;
|
||||||
} pkg2_kernel_id_t;
|
} pkg2_kernel_id_t;
|
||||||
|
|
||||||
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2);
|
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2);
|
||||||
|
|
|
@ -38,10 +38,4 @@ typedef volatile unsigned char vu8;
|
||||||
typedef volatile unsigned short vu16;
|
typedef volatile unsigned short vu16;
|
||||||
typedef volatile unsigned int vu32;
|
typedef volatile unsigned int vu32;
|
||||||
|
|
||||||
typedef struct _patch_t
|
|
||||||
{
|
|
||||||
u32 off;
|
|
||||||
u32 val;
|
|
||||||
} patch_t;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue