[hos] Support new mailbox and refactor a little bit
This commit is contained in:
@@ -50,6 +50,19 @@ extern void sd_unmount();
|
||||
//#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
#define SECMON_MB_ADDR 0x40002EF8
|
||||
#define SECMON7_MB_ADDR 0x400000F8
|
||||
|
||||
// Secmon mailbox.
|
||||
typedef struct _secmon_mailbox_t
|
||||
{
|
||||
// < 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot.
|
||||
// >= 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot.
|
||||
u32 in;
|
||||
// Non-zero: Secmon ready.
|
||||
u32 out;
|
||||
} secmon_mailbox_t;
|
||||
|
||||
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
|
||||
@@ -68,7 +81,7 @@ static const u8 master_keyseed_retail[0x10] =
|
||||
static const u8 console_keyseed[0x10] =
|
||||
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
|
||||
|
||||
static const u8 key8_keyseed[] =
|
||||
static const u8 package2_keyseed[] =
|
||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
||||
|
||||
static const u8 master_keyseed_4xx_5xx_610[0x10] =
|
||||
@@ -129,9 +142,7 @@ void _pmc_scratch_lock(u32 kb)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) = 0xFFAAFFFF;
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
case KB_FIRMWARE_VERSION_600:
|
||||
default:
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF;
|
||||
@@ -165,34 +176,42 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
u8 tmp[0x20];
|
||||
u32 retries = 0;
|
||||
|
||||
tsec_ctxt->size = 0xF00;
|
||||
|
||||
if (kb > KB_FIRMWARE_VERSION_MAX)
|
||||
return 0;
|
||||
|
||||
// Get TSEC key.
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
tsec_ctxt->size = 0xF00;
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
tsec_ctxt->size = 0x2900;
|
||||
else
|
||||
tsec_ctxt->size = 0x3000;
|
||||
|
||||
// Prepare smmu tsec page for 6.2.0.
|
||||
if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
u8 *tsec_paged = (u8 *)page_alloc(3);
|
||||
memcpy(tsec_paged, (void *)tsec_ctxt->fw, tsec_ctxt->size);
|
||||
tsec_ctxt->fw = tsec_paged;
|
||||
}
|
||||
|
||||
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
|
||||
// Get TSEC key.
|
||||
if (kb <= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
memset(tmp, 0x00, 0x20);
|
||||
retries++;
|
||||
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
if (retries > 15)
|
||||
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%k\nFailed to get TSEC keys. Please try again.%k\n\n", 0xFFFF0000, 0xFFCCCCCC);
|
||||
return 0;
|
||||
memset(tmp, 0x00, 0x20);
|
||||
retries++;
|
||||
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
if (retries > 15)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%k\nFailed to get TSEC keys. Please try again.%k\n\n", 0xFFFF0000, 0xFFCCCCCC);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
// Set TSEC key.
|
||||
se_aes_key_set(12, tmp, 0x10);
|
||||
@@ -203,7 +222,7 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
se_aes_key_set(8, tmp + 0x10, 0x10);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_620);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_retail);
|
||||
se_aes_unwrap_key(8, 8, key8_keyseed);
|
||||
se_aes_unwrap_key(8, 8, package2_keyseed);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -264,7 +283,7 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
|
||||
// Package2 key.
|
||||
se_key_acc_ctrl(8, 0x15);
|
||||
se_aes_unwrap_key(8, 12, key8_keyseed);
|
||||
se_aes_unwrap_key(8, 12, package2_keyseed);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -285,10 +304,10 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
|
||||
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
|
||||
if (!ctxt->pkg1_id)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kUnknown pkg1,\nVersion (= '%s').%k\n", 0xFFFF0000, (char *)ctxt->pkg1 + 0x10, 0xFFCCCCCC);
|
||||
gfx_printf(&gfx_con, "%kUnknown pkg1 version.%k\n", 0xFFFF0000, 0xFFCCCCCC);
|
||||
goto out;
|
||||
}
|
||||
gfx_printf(&gfx_con, "Identified pkg1 ('%s'),\nKeyblob version %d\n\n", (char *)(ctxt->pkg1 + 0x10), ctxt->pkg1_id->kb);
|
||||
gfx_printf(&gfx_con, "Identified pkg1 and Keyblob %d\n\n", ctxt->pkg1_id->kb);
|
||||
|
||||
// Read the correct keyblob.
|
||||
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
@@ -371,7 +390,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
// Try to parse config if present.
|
||||
if (cfg && !_parse_boot_config(&ctxt, cfg))
|
||||
if (cfg && !parse_boot_config(&ctxt, cfg))
|
||||
return 0;
|
||||
|
||||
gfx_printf(&gfx_con, "Initializing...\n\n");
|
||||
@@ -384,10 +403,10 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (h_cfg.autonogc && !(fuse_read_odm(7) & ~0xF) && ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_400)
|
||||
config_kip1patch(&ctxt, "nogc");
|
||||
|
||||
gfx_printf(&gfx_con, "Loaded pkg1 and keyblob\n");
|
||||
gfx_printf(&gfx_con, "Loaded pkg1 & keyblob\n");
|
||||
|
||||
// Generate keys.
|
||||
if (!h_cfg.se_keygen_done || ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_620)
|
||||
if (!h_cfg.se_keygen_done || ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
tsec_ctxt.fw = (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = ctxt.pkg1;
|
||||
@@ -407,9 +426,13 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600)
|
||||
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 pkg1\n");
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
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 & unpacked pkg1\n");
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Replace 'warmboot.bin' if requested.
|
||||
@@ -439,7 +462,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
|
||||
}
|
||||
|
||||
gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n");
|
||||
gfx_printf(&gfx_con, "Loaded warmboot and secmon\n");
|
||||
|
||||
// Read package2.
|
||||
u8 *bootConfigBuf = _read_emmc_pkg2(&ctxt);
|
||||
@@ -498,7 +521,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
}
|
||||
|
||||
// Merge extra KIP1s into loaded ones.
|
||||
gfx_printf(&gfx_con, "%kPatching kernel initial processes%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
gfx_printf(&gfx_con, "%kPatching kips%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);
|
||||
|
||||
@@ -506,7 +529,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches);
|
||||
if (unappliedPatch != NULL)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to apply patch '%s'!%k\n", 0xFFFF0000, unappliedPatch, 0xFFCCCCCC);
|
||||
gfx_printf(&gfx_con, "%kFailed to apply '%s'!%k\n", 0xFFFF0000, unappliedPatch, 0xFFCCCCCC);
|
||||
sd_unmount(); // Just exiting is not enough until pkg2_patch_kips stops modifying the string passed into it.
|
||||
|
||||
_free_launch_components(&ctxt);
|
||||
@@ -516,7 +539,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
// Rebuild and encrypt package2.
|
||||
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
|
||||
|
||||
gfx_printf(&gfx_con, "Rebuilt and loaded pkg2\n");
|
||||
gfx_printf(&gfx_con, "Rebuilt & loaded pkg2\n");
|
||||
|
||||
gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF96FF00, 0xFFCCCCCC);
|
||||
|
||||
@@ -547,7 +570,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
case KB_FIRMWARE_VERSION_600:
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(15, 0xFF);
|
||||
case KB_FIRMWARE_VERSION_620:
|
||||
default:
|
||||
bootStateDramPkg2 = 2;
|
||||
bootStatePkg2Continue = 4;
|
||||
break;
|
||||
@@ -586,22 +609,22 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_620)
|
||||
_sysctr0_reset();
|
||||
|
||||
// Free allocated memory.
|
||||
ini_free_section(cfg);
|
||||
_free_launch_components(&ctxt);
|
||||
|
||||
// < 4.0.0 pkg1.1 locks PMC scratches.
|
||||
//_pmc_scratch_lock(ctxt.pkg1_id->kb);
|
||||
|
||||
// < 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot.
|
||||
// >= 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot.
|
||||
vu32 *mb_in = (vu32 *)0x40002EF8;
|
||||
// Non-zero: Secmon ready.
|
||||
vu32 *mb_out = (vu32 *)0x40002EFC;
|
||||
// Set secmon mailbox address.
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
||||
secmon_mb = (secmon_mailbox_t *)SECMON7_MB_ADDR;
|
||||
else
|
||||
secmon_mb = (secmon_mailbox_t *)SECMON_MB_ADDR;
|
||||
|
||||
// Start from DRAM ready signal.
|
||||
*mb_in = bootStateDramPkg2;
|
||||
*mb_out = 0;
|
||||
// Start from DRAM ready signal and reset outgoing value.
|
||||
secmon_mb->in = bootStateDramPkg2;
|
||||
secmon_mb->out = 0;
|
||||
|
||||
// Free allocated memory.
|
||||
ini_free_section(cfg);
|
||||
_free_launch_components(&ctxt);
|
||||
|
||||
// Disable display. This must be executed before secmon to provide support for all fw versions.
|
||||
display_end();
|
||||
@@ -611,14 +634,14 @@ int hos_launch(ini_sec_t *cfg)
|
||||
smmu_exit();
|
||||
else
|
||||
cluster_boot_cpu0(ctxt.pkg1_id->secmon_base);
|
||||
while (!*mb_out)
|
||||
while (!secmon_mb->out)
|
||||
usleep(1); // This only works when in IRAM or with a trained DRAM.
|
||||
|
||||
// Signal pkg2 ready and continue boot.
|
||||
*mb_in = bootStatePkg2Continue;
|
||||
secmon_mb->in = bootStatePkg2Continue;
|
||||
|
||||
// Halt ourselves in waitevent state and resume if there's JTAG activity.
|
||||
while (1)
|
||||
while (true)
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = 0x50000000;
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user