mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
[hos] Support new mailbox and refactor a little bit
This commit is contained in:
parent
2fb37db707
commit
7d908c9ac5
4 changed files with 126 additions and 106 deletions
|
@ -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,20 +176,27 @@ 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;
|
||||
}
|
||||
|
||||
// Get TSEC key.
|
||||
if (kb <= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
|
||||
{
|
||||
memset(tmp, 0x00, 0x20);
|
||||
|
@ -191,8 +209,9 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
|||
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);
|
||||
|
||||
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 and unpacked pkg1\n");
|
||||
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;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -20,8 +20,11 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "pkg1.h"
|
||||
#include "../utils/aarch64_util.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../utils/aarch64_util.h"
|
||||
|
||||
extern gfx_con_t gfx_con;
|
||||
|
||||
#define _NOPv7() 0xE320F000
|
||||
|
||||
|
@ -116,20 +119,6 @@ PATCHSET_DEF(_warmboot_4_patchset,
|
|||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_5_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_6_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_620_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
/*
|
||||
* package1.1 header: <wb, ldr, sm>
|
||||
|
@ -150,15 +139,19 @@ static const pkg1_id_t _pkg1_ids[] = {
|
|||
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.1 - 3.0.2
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_4_patchset, _warmboot_4_patchset }, //4.0.0 - 4.1.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset, _warmboot_5_patchset }, //5.0.0 - 5.1.0
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset, _warmboot_6_patchset }, //6.0.0 - 6.1.0
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_620_patchset, _warmboot_620_patchset }, //6.2.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset, _warmboot_4_patchset }, //5.0.0 - 5.1.0
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset, _warmboot_4_patchset }, //6.0.0 - 6.1.0
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_620_patchset, _warmboot_4_patchset }, //6.2.0
|
||||
{ NULL } //End.
|
||||
};
|
||||
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1)
|
||||
{
|
||||
char build_date[15];
|
||||
memcpy(build_date, (char *)(pkg1 + 0x10), 14);
|
||||
build_date[14] = 0;
|
||||
gfx_printf(&gfx_con, "Found pkg1 ('%s').\n\n", build_date);
|
||||
|
||||
for (u32 i = 0; _pkg1_ids[i].id; i++)
|
||||
if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 12))
|
||||
return &_pkg1_ids[i];
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
#include "../gfx/gfx.h"
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
extern gfx_con_t gfx_con;
|
||||
|
||||
/*#include "util.h"
|
||||
|
@ -902,3 +905,4 @@ DPRINTF("INI1 encrypted\n");
|
|||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
|
|
@ -117,16 +117,16 @@ typedef struct _pkg2_kernel_id_t
|
|||
|
||||
typedef struct _kip1_patch_t
|
||||
{
|
||||
u32 offset; //section+offset of patch to apply
|
||||
u32 length; //in bytes, 0 means last patch
|
||||
const char* srcData; //that must match
|
||||
const char* dstData; //that it gets replaced by
|
||||
u32 offset; // section+offset of patch to apply.
|
||||
u32 length; // In bytes, 0 means last patch.
|
||||
const char* srcData; // That must match.
|
||||
const char* dstData; // That it gets replaced by.
|
||||
} kip1_patch_t;
|
||||
|
||||
typedef struct _kip1_patchset_t
|
||||
{
|
||||
const char* name; //NULL means end
|
||||
kip1_patch_t* patches; //NULL means not necessary
|
||||
const char* name; // NULL means end.
|
||||
kip1_patch_t* patches; // NULL means not necessary.
|
||||
} kip1_patchset_t;
|
||||
|
||||
typedef struct _kip1_id_t
|
||||
|
|
Loading…
Reference in a new issue