Skip to content

Commit

Permalink
Preliminary Exosphère support
Browse files Browse the repository at this point in the history
  • Loading branch information
CTCaer committed Jul 1, 2018
1 parent d9dba2b commit ffeb8c6
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 61 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
___
.-' `'.
Expand Down
2 changes: 1 addition & 1 deletion ipl/arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
120 changes: 94 additions & 26 deletions ipl/hos.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ typedef struct _launch_ctxt_t

int svcperm;
int debugmode;
int atmosphere;
} launch_ctxt_t;

typedef struct _merge_kip_t
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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 },
};

Expand All @@ -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;

Expand All @@ -388,43 +421,43 @@ 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);
pkg1_unpack((void *)ctxt.pkg1_id->warmboot_base, (void *)ctxt.pkg1_id->secmon_base, NULL, ctxt.pkg1_id, ctxt.pkg1);
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++)
Expand All @@ -433,87 +466,122 @@ 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);
pkg2_parse_kips(&kip1_info, pkg2_hdr);

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

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);
se_key_acc_ctrl(13, 0xFF);
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);

// 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'.
// 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
Expand Down
2 changes: 1 addition & 1 deletion ipl/link.ld
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ENTRY(_start)

SECTIONS {
PROVIDE(__ipl_start = 0x40003000);
PROVIDE(__ipl_start = 0x40008000);
. = __ipl_start;
.text : {
*(.text*);
Expand Down
2 changes: 1 addition & 1 deletion ipl/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] =
Expand Down
6 changes: 6 additions & 0 deletions ipl/pkg1.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__, \
Expand Down

1 comment on commit ffeb8c6

@CTCaer
Copy link
Owner Author

@CTCaer CTCaer commented on ffeb8c6 Jul 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not actually preliminary.
It works fully with the current Atmosphere commits.

Please sign in to comment.