Preliminary Exosphère support

This commit is contained in:
Kostas Missos 2018-07-01 05:03:17 +03:00
parent d9dba2b182
commit ffeb8c60df
9 changed files with 300 additions and 61 deletions

View file

@ -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
___ ___
.-' `'. .-' `'.

View file

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

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

View file

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

View file

@ -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[] =

View file

@ -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__, \

View file

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

View file

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

View file

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