hos: add NX BIT/BC structures and utilize them
These are used to communicate between bootloader stages and pass config. The NX Boot Config is now passed as is from PKG2 partition.
This commit is contained in:
@@ -36,34 +36,6 @@
|
||||
({ gfx_con.mute = false; \
|
||||
gfx_printf("%k"text"%k\n", TXT_CLR_ERROR, args, TXT_CLR_DEFAULT); })
|
||||
|
||||
#define SECMON_BCT_CFG_ADDR 0x4003D000
|
||||
#define SECMON6_BCT_CFG_ADDR 0x4003F800
|
||||
|
||||
// Secmon mailbox.
|
||||
#define SECMON_MAILBOX_ADDR 0x40002E00
|
||||
#define SECMON7_MAILBOX_ADDR 0x40000000
|
||||
#define SECMON_STATE_OFFSET 0xF8
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SECMON_STATE_NOT_READY = 0,
|
||||
|
||||
PKG1_STATE_NOT_READY = 0,
|
||||
PKG1_STATE_BCT_COPIED = 1,
|
||||
PKG1_STATE_DRAM_READY = 2,
|
||||
PKG1_STATE_PKG2_READY_OLD = 3,
|
||||
PKG1_STATE_PKG2_READY = 4
|
||||
} pkg1_states_t;
|
||||
|
||||
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 eks_keyseeds[HOS_MKEY_VER_600 - HOS_MKEY_VER_100 + 1][SE_KEY_128_SIZE] = {
|
||||
{ 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.
|
||||
@@ -630,7 +602,7 @@ try_load:
|
||||
|
||||
static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
|
||||
{
|
||||
u8 *bctBuf = NULL;
|
||||
u8 *nx_bc = NULL;
|
||||
|
||||
emummc_storage_set_mmc_partition(EMMC_GPP);
|
||||
|
||||
@@ -644,27 +616,30 @@ DPRINTF("Parsed GPT\n");
|
||||
goto out;
|
||||
|
||||
// Read in package2 header and get package2 real size.
|
||||
static const u32 BCT_SIZE = SZ_16K;
|
||||
bctBuf = (u8 *)malloc(BCT_SIZE);
|
||||
emmc_part_read(pkg2_part, BCT_SIZE / EMMC_BLOCKSIZE, 1, bctBuf);
|
||||
u32 *hdr = (u32 *)(bctBuf + 0x100);
|
||||
static const u32 PKG2_OFFSET = SZ_16K;
|
||||
nx_bc = (u8 *)malloc(sizeof(nx_bc_t));
|
||||
emmc_part_read(pkg2_part, PKG2_OFFSET / EMMC_BLOCKSIZE, 1, nx_bc);
|
||||
u32 *hdr = (u32 *)(nx_bc + 0x100);
|
||||
u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3];
|
||||
DPRINTF("pkg2 size on emmc is %08X\n", pkg2_size);
|
||||
|
||||
// Read in Boot Config.
|
||||
emmc_part_read(pkg2_part, 0, BCT_SIZE / EMMC_BLOCKSIZE, bctBuf);
|
||||
// Check that size is valid.
|
||||
if (!pkg2_size || pkg2_size > SZ_8M)
|
||||
goto out;
|
||||
|
||||
// Read in NX Boot Config.
|
||||
emmc_part_read(pkg2_part, 0, sizeof(nx_bc_t) / EMMC_BLOCKSIZE, nx_bc);
|
||||
|
||||
// Read in package2.
|
||||
u32 pkg2_size_aligned = ALIGN(pkg2_size, EMMC_BLOCKSIZE);
|
||||
DPRINTF("pkg2 size aligned is %08X\n", pkg2_size_aligned);
|
||||
ctxt->pkg2 = malloc(pkg2_size_aligned);
|
||||
ctxt->pkg2_size = pkg2_size;
|
||||
emmc_part_read(pkg2_part, BCT_SIZE / EMMC_BLOCKSIZE,
|
||||
pkg2_size_aligned / EMMC_BLOCKSIZE, ctxt->pkg2);
|
||||
emmc_part_read(pkg2_part, PKG2_OFFSET / EMMC_BLOCKSIZE, pkg2_size_aligned / EMMC_BLOCKSIZE, ctxt->pkg2);
|
||||
out:
|
||||
emmc_gpt_free(&gpt);
|
||||
|
||||
return bctBuf;
|
||||
return nx_bc;
|
||||
}
|
||||
|
||||
static void _free_launch_components(launch_ctxt_t *ctxt)
|
||||
@@ -932,8 +907,8 @@ void hos_launch(ini_sec_t *cfg)
|
||||
gfx_puts("Loaded warmboot and secmon\n");
|
||||
|
||||
// Read package2.
|
||||
u8 *bootConfigBuf = _read_emmc_pkg2(&ctxt);
|
||||
if (!bootConfigBuf)
|
||||
u8 *pkg2_nx_bc = _read_emmc_pkg2(&ctxt);
|
||||
if (!pkg2_nx_bc)
|
||||
{
|
||||
_hos_crit_error("Pkg2 read failed!");
|
||||
goto error;
|
||||
@@ -1088,20 +1063,6 @@ void hos_launch(ini_sec_t *cfg)
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear BCT area for retail units and copy it over if dev unit.
|
||||
if (mkey <= HOS_MKEY_VER_500 && !is_exo)
|
||||
{
|
||||
memset((void *)SECMON_BCT_CFG_ADDR, 0, SZ_4K + SZ_8K);
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
memcpy((void *)SECMON_BCT_CFG_ADDR, bootConfigBuf, SZ_4K);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset((void *)SECMON6_BCT_CFG_ADDR, 0, SZ_2K);
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
memcpy((void *)SECMON6_BCT_CFG_ADDR, bootConfigBuf, SZ_2K);
|
||||
}
|
||||
|
||||
// Finalize MC carveout.
|
||||
if (mkey <= HOS_MKEY_VER_301 && !is_exo)
|
||||
mc_config_carveout();
|
||||
@@ -1116,23 +1077,25 @@ void hos_launch(ini_sec_t *cfg)
|
||||
// NX Bootloader locks LP0 Carveout secure scratch registers.
|
||||
//pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS);
|
||||
|
||||
// Set secmon mailbox address and clear it.
|
||||
volatile secmon_mailbox_t *secmon_mailbox;
|
||||
if (mkey >= HOS_MKEY_VER_700 || is_exo)
|
||||
{
|
||||
memset((void *)SECMON7_MAILBOX_ADDR, 0, 0x200);
|
||||
secmon_mailbox = (secmon_mailbox_t *)(SECMON7_MAILBOX_ADDR + SECMON_STATE_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mkey <= HOS_MKEY_VER_301)
|
||||
memset((void *)SECMON_MAILBOX_ADDR, 0, 0x200);
|
||||
secmon_mailbox = (secmon_mailbox_t *)(SECMON_MAILBOX_ADDR + SECMON_STATE_OFFSET);
|
||||
}
|
||||
// Copy the read NX BC to the correct address.
|
||||
nx_bc_t *nxbc = (mkey >= HOS_MKEY_VER_600 || is_exo) ?
|
||||
(nx_bc_t *)NX_BC6_ADDR :
|
||||
(nx_bc_t *)NX_BC1_ADDR;
|
||||
memcpy(nxbc, pkg2_nx_bc, sizeof(nx_bc_t)); // NX bootloader copies 4KB.
|
||||
|
||||
// Start directly from PKG2 ready signal and reset outgoing value.
|
||||
secmon_mailbox->in = pkg1_state_pkg2_ready;
|
||||
secmon_mailbox->out = SECMON_STATE_NOT_READY;
|
||||
// Set NX BIT mailbox address and clear it.
|
||||
nx_bit_t *nxbit = (mkey >= HOS_MKEY_VER_700 || is_exo) ?
|
||||
(nx_bit_t *)NX_BIT7_MAILBOX_ADDR :
|
||||
(nx_bit_t *)NX_BIT1_MAILBOX_ADDR;
|
||||
memset(nxbit, 0, sizeof(nx_bit_t));
|
||||
|
||||
// Set used NX BIT parameters.
|
||||
nxbit->bl_attribute = 0;
|
||||
nxbit->boot_type = BIT_BOOT_TYPE_COLD;
|
||||
|
||||
// Start directly from PKG2 ready signal and reset secmon state.
|
||||
nxbit->secldr_state = pkg1_state_pkg2_ready;
|
||||
nxbit->secmon_state = SECMON_STATE_NOT_READY;
|
||||
|
||||
// Disable display.
|
||||
display_end();
|
||||
|
||||
@@ -110,6 +110,56 @@ typedef struct _pk11_hdr_t
|
||||
/* 0x1C */ u32 sm_off;
|
||||
} pk11_hdr_t;
|
||||
|
||||
/*
|
||||
* NX BIT - Secure monitor mailbox
|
||||
*
|
||||
* On older versions the Tegra BIT was remaining intact.
|
||||
* The bootloader info from BCT was copied in the mailbox at 0x40002E10.
|
||||
* On >= 4.0.0 the boot reason was replaced by BCT boot type.
|
||||
* On newer versions (>= 7.0.0) the Tegra BIT is replaced with NX BIT.
|
||||
* That also includes secmon state mailbox and pkg1 and pkg11 headers.
|
||||
*/
|
||||
#define NX_BIT1_MAILBOX_ADDR 0x40002E00
|
||||
#define NX_BIT7_MAILBOX_ADDR 0x40000000
|
||||
|
||||
enum
|
||||
{
|
||||
SECMON_STATE_NOT_READY = 0,
|
||||
|
||||
PKG1_STATE_NOT_READY = 0,
|
||||
PKG1_STATE_NXBC_COPIED = 1,
|
||||
PKG1_STATE_DRAM_READY = 2,
|
||||
PKG1_STATE_PKG2_READY_OLD = 3,
|
||||
PKG1_STATE_PKG2_READY = 4
|
||||
};
|
||||
|
||||
#define NX_BIT_BL_ATTR_SAFE_MODE BIT(0)
|
||||
#define NX_BIT_BL_ATTR_SMC_BLACKLIST_STANDARD BIT(1) // Accounted only on >= 8.0.0.
|
||||
#define NX_BIT_BL_ATTR_SMC_BLACKLIST_DEVICEUD BIT(2) // Accounted only on >= 8.0.0.
|
||||
#define NX_BIT_BL_ATTR_SMC_BLACKLIST_SAFEMODE BIT(3) // Accounted only on >= 8.0.0.
|
||||
|
||||
typedef struct _nx_bit_t
|
||||
{
|
||||
/* 0x00 */ u32 secldr_tmr_start;
|
||||
/* 0x04 */ u32 secldr_tmr_end;
|
||||
/* 0x08 */ u32 secmon_tmr_start;
|
||||
/* 0x0C */ u32 secmon_tmr_end;
|
||||
/* 0x10 */ u32 bl_version;
|
||||
/* 0x14 */ u32 bl_start_block;
|
||||
/* 0x18 */ u32 bl_start_page;
|
||||
/* 0x1C */ u32 bl_attribute; // bit0: Safe, bit1-4: SMC blacklist mask.
|
||||
/* 0x20 */ u32 boot_type; // 0: None, 1: Coldboot, 2: RMC, 3: UART, 4: Exit RCM.
|
||||
/* 0x24 */ u8 padding_nxbit[12];
|
||||
|
||||
/* 0x30 */ pk1_hdr_t pk1_hdr; // (>= 7.0.0).
|
||||
/* 0x50 */ pk11_hdr_t pk11_hdr; // (>= 7.0.0).
|
||||
/* 0x70 */ u8 padding_pkg1[0x88];
|
||||
|
||||
/* 0xF8 */ vu32 secldr_state;
|
||||
/* 0xFC */ vu32 secmon_state;
|
||||
u8 padding_mail[0x100];
|
||||
} nx_bit_t;
|
||||
|
||||
const pkg1_id_t *pkg1_get_latest();
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
||||
int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
|
||||
|
||||
@@ -163,6 +163,51 @@ typedef struct _kip1_id_t
|
||||
const kip1_patchset_t *patchset;
|
||||
} kip1_id_t;
|
||||
|
||||
/*
|
||||
* NX NC - Package2 BOOT Configuration
|
||||
*
|
||||
* This is taken from the first 1KB of a Package2 partition.
|
||||
* On retail, it's not zeroes, but on devkits it has actual data.
|
||||
* The signed part is reserved for special in-house devkits.
|
||||
*/
|
||||
#define NX_BC1_ADDR 0x4003D000
|
||||
#define NX_BC6_ADDR 0x4003F800
|
||||
|
||||
#define NX_BC_DBG_FLAG00_DEV_MODE BIT(1)
|
||||
#define NX_BC_DBG_FLAG00_SERROR BIT(2)
|
||||
#define NX_BC_DBG_FLAG00_ALL_FLAGS 0xFF
|
||||
|
||||
#define NX_BC_HW_FLAG01_ALL_FLAGS 0xFF
|
||||
#define NX_BC_HW_FLAG03_MEM_MODE 0xFF
|
||||
#define NX_BC_HW_FLAG04_CNTCV_SET BIT(0)
|
||||
|
||||
#define NX_BC_PKG2_FLAG_DECRYPTED BIT(0)
|
||||
#define NX_BC_PKG2_FLAG_UNSIGNED BIT(1)
|
||||
|
||||
#define NX_BC_NCA_FLAG_UNSIGNED BIT(0)
|
||||
|
||||
typedef struct _nx_bc_t {
|
||||
/* Unsigned section */
|
||||
u32 version;
|
||||
u32 rsvd0[3];
|
||||
u8 dbg_flags[0x10]; // Normally all are set to 0xFF if devkit.
|
||||
u8 hw_flags[0x10];
|
||||
u64 cntcv_value;
|
||||
u8 padding0[0x1C8];
|
||||
|
||||
u8 rsa_pss_signature[0x100];
|
||||
|
||||
/* Signed section */
|
||||
u32 version_signed;
|
||||
u32 rsvd1;
|
||||
u8 pkg2_flags;
|
||||
u8 padding1[7];
|
||||
u32 ecid[4];
|
||||
u8 nca_flags[0x10];
|
||||
u8 unk_flags[0x10];
|
||||
u8 padding2[0xC0];
|
||||
} nx_bc_t;
|
||||
|
||||
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
|
||||
int pkg2_has_kip(link_t *info, u64 tid);
|
||||
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
||||
|
||||
Reference in New Issue
Block a user